Skip to content

Commit

Permalink
mixed v3.1.x bits with git master
Browse files Browse the repository at this point in the history
taking most of xpra/client and xpra/platform/darwin/

with some changes where it makes sense to minimize the integration effort.

build this with:
BUILD_ARGS='--without-strict --without-enc_ffmepg --without-dec_avcodec2' PYTHON=python3 ./make-all.sh

then run it with:
./Xpra.app/Contents/MacOS/Xpra attach tcp://host:port/ --no-mmap --no-speaker --no-microphone --opengl=force
  • Loading branch information
totaam committed Mar 5, 2023
1 parent deed568 commit 8cc8c83
Show file tree
Hide file tree
Showing 112 changed files with 8,527 additions and 9,667 deletions.
14 changes: 9 additions & 5 deletions xpra/client/auth/env_handler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import os


class Handler:
class Handler(object):

def __init__(self, client, **kwargs):
self.client = client
Expand All @@ -15,8 +15,12 @@ def __init__(self, client, **kwargs):
def __repr__(self):
return "env"

def get_digest(self) -> str:
def get_digest(self):
return None

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
return os.environ.get(self.var_name)
def handle(self, packet):
password = os.environ.get(self.var_name)
if not password:
return False
self.client.send_challenge_reply(packet, password)
return True
20 changes: 9 additions & 11 deletions xpra/client/auth/file_handler.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import os

from xpra.os_util import load_binary_file
from xpra.log import Logger

log = Logger("auth")


class Handler:
class Handler(object):

def __init__(self, client, **kwargs):
self.client = client
Expand All @@ -24,14 +21,15 @@ def __init__(self, client, **kwargs):
def __repr__(self):
return "file"

def get_digest(self) -> str:
def get_digest(self):
return None

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
log("handle(..) password_file=%s", self.password_file)
def handle(self, packet):
if not self.password_file:
return None
return False
filename = os.path.expanduser(self.password_file)
data = load_binary_file(filename)
log("loaded password data from %s: %s", filename, bool(data))
return data
if not data:
return False
self.client.send_challenge_reply(packet, data)
return True
29 changes: 14 additions & 15 deletions xpra/client/auth/gss_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand All @@ -12,7 +12,7 @@
log = Logger("auth")


class Handler:
class Handler(object):

def __init__(self, client, **_kwargs):
self.client = client
Expand All @@ -21,32 +21,30 @@ def __init__(self, client, **_kwargs):
def __repr__(self):
return "gss"

def get_digest(self) -> str:
def get_digest(self):
return "gss"

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
def handle(self, packet):
digest = bytestostr(packet[3])
if not digest.startswith("gss:"):
#not a gss challenge
log("%s is not a gss challenge", digest)
return None
return False
try:
#pylint: disable=import-outside-toplevel
import gssapi #@UnresolvedImport
self.gssapi = gssapi
if OSX:
#this is a workaround for py2app,
#to ensure it includes all the modules we need:
from gssapi.raw import cython_converters, cython_types, oids # @UnresolvedImport
if OSX and False:
from gssapi.raw import (cython_converters, cython_types, oids) # @UnresolvedImport
assert cython_converters and cython_types and oids
except ImportError as e:
log.warn("Warning: cannot use gss authentication handler")
log.warn(" %s", e)
return None
return False
service = bytestostr(digest.split(b":", 1)[1])
if service not in self.services and "*" not in self.services:
log.warn("Warning: invalid GSS request for service '%s'", service)
log.warn(" services supported: %s", csv(self.services))
return None
return False
log("gss service=%s", service)
service_name = self.gssapi.Name(service)
try:
Expand All @@ -59,7 +57,8 @@ def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-a
for x in str(e).split(":", 2):
log.error(" %s", x.lstrip(" "))
except Exception:
log.estr(e)
return None
log.error(" %s", e)
return False
log("gss token=%s", repr(token))
return token
self.client.send_challenge_reply(packet, token)
return True
29 changes: 14 additions & 15 deletions xpra/client/auth/kerberos_handler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import os

from xpra.util import csv
from xpra.os_util import WIN32
from xpra.os_util import bytestostr, WIN32
from xpra.log import Logger

log = Logger("auth")
Expand All @@ -23,9 +23,9 @@ def log_kerberos_exception(e):
pass
log.error(" %s", x)
except Exception:
log.estr(e)
log.error(" %s", e)

class Handler:
class Handler(object):

def __init__(self, client, **_kwargs):
self.client = client
Expand All @@ -34,16 +34,16 @@ def __init__(self, client, **_kwargs):
def __repr__(self):
return "kerberos"

def get_digest(self) -> str:
def get_digest(self):
return "kerberos"

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
def handle(self, packet):
digest = bytestostr(packet[3])
if not digest.startswith("kerberos:"):
log("%s is not a kerberos challenge", digest)
#not a kerberos challenge
return None
return False
try:
# pylint: disable=import-outside-toplevel
if WIN32:
import winkerberos as kerberos
else:
Expand All @@ -56,25 +56,24 @@ def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-a
if service not in self.services and "*" not in self.services:
log.warn("Warning: invalid kerberos request for service '%s'", service)
log.warn(" services supported: %s", csv(self.services))
return None
return False
log("kerberos service=%s", service)
try:
r, ctx = kerberos.authGSSClientInit(service)
if r!=1:
log("kerberos.authGSSClientInit failed and returned %s", r)
return None
assert r==1, "return code %s" % r
except Exception as e:
log("kerberos.authGSSClientInit(%s)", service, exc_info=True)
log.error("Error: cannot initialize kerberos client:")
log_kerberos_exception(e)
return None
return False
try:
kerberos.authGSSClientStep(ctx, "")
except Exception as e:
log("kerberos.authGSSClientStep", exc_info=True)
log.error("Error: kerberos client authentication failure:")
log_kerberos_exception(e)
return None
return False
token = kerberos.authGSSClientResponse(ctx)
log("kerberos token=%s", token)
return token
self.client.send_challenge_reply(packet, token)
return True
22 changes: 14 additions & 8 deletions xpra/client/auth/prompt_handler.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

from xpra.util import std
from xpra.os_util import bytestostr

class Handler:

class Handler(object):

def __init__(self, client, **_kwargs):
self.client = client

def __repr__(self):
return "prompt"

def get_digest(self) -> str:
def get_digest(self):
return None

def handle(self, challenge, digest, prompt : str = "password") -> bool: # pylint: disable=unused-argument
digest_type = digest.split(":", 1)[0]
if not prompt and digest_type in ("gss", "kerberos"):
prompt = f"{digest_type} token"
return self.client.do_process_challenge_prompt(prompt)
def handle(self, packet):
prompt = "password"
digest = bytestostr(packet[3])
if digest.startswith("gss:") or digest.startswith("kerberos:"):
prompt = "%s token" % (digest.split(":", 1)[0])
if len(packet)>=6:
prompt = std(bytestostr(packet[5]))
return self.client.do_process_challenge_prompt(packet, prompt)
28 changes: 15 additions & 13 deletions xpra/client/auth/u2f_handler.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,71 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import os
import logging
import binascii

from xpra.os_util import load_binary_file, osexpand
from xpra.os_util import bytestostr, load_binary_file, osexpand
from xpra.log import Logger, is_debug_enabled

log = Logger("auth")


class Handler:
class Handler(object):

def __init__(self, client, **_kwargs):
self.client = client

def __repr__(self):
return "u2f"

def get_digest(self) -> str:
def get_digest(self):
return "u2f"

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
def handle(self, packet):
digest = bytestostr(packet[3])
if not digest.startswith("u2f:"):
log("%s is not a u2f challenge", digest)
return None
return False
try:
#pylint: disable=import-outside-toplevel
from pyu2f import model #@UnresolvedImport
from pyu2f.u2f import GetLocalU2FInterface #@UnresolvedImport
except ImportError as e:
log.warn("Warning: cannot use u2f authentication handler")
log.warn(" %s", e)
return None
return False
if not is_debug_enabled("auth"):
logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
dev = GetLocalU2FInterface()
APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
key_handle = self.get_key_handle()
if not key_handle:
return None
return False
key = model.RegisteredKey(key_handle)
#use server salt as challenge directly
challenge = packet[1]
log.info("activate your U2F device for authentication")
response = dev.Authenticate(APP_ID, challenge, [key])
sig = response.signature_data
client_data = response.client_data
log("process_challenge_u2f client data=%s, signature=%s", client_data, binascii.hexlify(sig))
return bytes(sig), client_data.origin
self.client.do_send_challenge_reply(bytes(sig), client_data.origin)
return True

def get_key_handle(self) -> bytes:
def get_key_handle(self):
key_handle_str = os.environ.get("XPRA_U2F_KEY_HANDLE")
log("process_challenge_u2f XPRA_U2F_KEY_HANDLE=%s", key_handle_str)
if not key_handle_str:
#try to load the key handle from the user conf dir(s):
from xpra.platform.paths import get_user_conf_dirs #pylint: disable=import-outside-toplevel
from xpra.platform.paths import get_user_conf_dirs
info = self.client._protocol.get_info(False)
key_handle_filenames = []
for hostinfo in ("-%s" % info.get("host", ""), ""):
for d in get_user_conf_dirs():
key_handle_filenames.append(os.path.join(d, f"u2f-keyhandle{hostinfo}.hex"))
key_handle_filenames.append(os.path.join(d, "u2f-keyhandle%s.hex" % hostinfo))
for filename in key_handle_filenames:
p = osexpand(filename)
key_handle_str = load_binary_file(p)
Expand Down
13 changes: 8 additions & 5 deletions xpra/client/auth/uri_handler.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
# This file is part of Xpra.
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.


class Handler:
class Handler(object):

def __init__(self, client, **_kwargs):
self.client = client

def __repr__(self):
return "uri"

def get_digest(self) -> str:
def get_digest(self):
return None

def handle(self, challenge, digest, prompt) -> bool: # pylint: disable=unused-argument
return self.client.password
def handle(self, packet):
if not self.client.password:
return False
self.client.send_challenge_reply(packet, self.client.password)
return True
Loading

0 comments on commit 8cc8c83

Please sign in to comment.