Skip to content

Commit

Permalink
#1920: support authentication modules
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@19951 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jul 23, 2018
1 parent e5aab5b commit 4d2f3e7
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/xpra/net/digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def choose_digest(options):
return "xor"
if "des" in options:
return "des"
raise Exception("no known digest options found in '%s'" % csv(options))
raise ValueError("no known digest options found in '%s'" % csv(options))

def gendigest(digest, password, salt):
assert digest and password and salt
Expand Down
35 changes: 29 additions & 6 deletions src/xpra/server/server_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
from xpra.net.bytestreams import SocketConnection, SSLSocketConnection, log_new_connection, pretty_socket, SOCKET_TIMEOUT
from xpra.net.net_util import get_network_caps, get_info as get_net_info
from xpra.net.protocol import Protocol, sanity_checks
from xpra.net.digest import get_salt, gendigest, choose_digest
from xpra.platform import set_name
from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, platform_name, strtobytes, bytestostr, get_hex_uuid, monotonic_time, get_peercred, hexstr, SIGNAMES, WIN32, POSIX, PYTHON3, BITS
from xpra.os_util import load_binary_file, get_machine_id, get_user_uuid, platform_name, strtobytes, bytestostr, get_hex_uuid, \
getuid, monotonic_time, get_peercred, hexstr, \
SIGNAMES, WIN32, POSIX, PYTHON3, BITS, get_username_for_uid
from xpra.server.background_worker import stop_worker, get_worker
from xpra.make_thread import start_thread
from xpra.util import csv, merge_dicts, typedict, notypedict, flatten_dict, parse_simple_dict, repr_ellipsized, dump_all_frames, nonl, envint, envbool, envfloat, \
Expand Down Expand Up @@ -931,13 +934,34 @@ def handle_ssh_connection(self, conn):
socktype = conn.socktype_wrapped
sshlog("handle_ssh_connection(%s) socktype wrapped=%s", conn, socktype)
def ssh_password_authenticate(username, password):
if POSIX and getuid()!=0:
sysusername = get_username_for_uid(os.getuid())
if sysusername!=username:
sshlog.warn("Warning: ssh password authentication failed")
sshlog.warn(" username does not match: expected '%s', got '%s'", sysusername, username)
return False
auth_modules = self.make_authenticators(socktype, username, conn)
sshlog("ssh_password_authenticate auth_modules(%s, %s)=%s", username, "*"*len(password), auth_modules)
for mod in auth_modules:
r = mod.authenticate(username, password)
sshlog("%s.authenticate(..)=%s", mod, r)
if not r:
for auth in auth_modules:
#mimic a client challenge:
digests = ["xor"]
try:
salt, digest = auth.get_challenge(digests)
salt_digest = auth.choose_salt_digest(digests)
assert digest=="xor" and salt_digest=="xor"
except ValueError as e:
sshlog("authentication with %s", auth, exc_info=True)
sshlog.warn("Warning: ssh transport cannot use %r authentication:", auth)
sshlog.warn(" %s", e)
return False
else:
client_salt = get_salt(len(salt))
combined_salt = gendigest("xor", client_salt, salt)
xored_password = gendigest("xor", password, combined_salt)
r = auth.authenticate(xored_password, client_salt)
sshlog("%s.authenticate(..)=%s", auth, r)
if not r:
return False
return True
return make_ssh_server_connection(conn, ssh_password_authenticate)

Expand Down Expand Up @@ -1446,7 +1470,6 @@ def auth_failed(msg):

def send_fake_challenge():
#fake challenge so the client will send the real hello:
from xpra.net.digest import get_salt, choose_digest
salt = get_salt()
digest = choose_digest(digest_modes)
salt_digest = choose_digest(salt_digest_modes)
Expand Down
2 changes: 1 addition & 1 deletion src/xpra/server/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def get_allowed_auths(self, username):
mods.append("publickey")
if self.password_auth:
mods.append("password")
return csv(mods)
return ",".join(mods)

def check_channel_request(self, kind, chanid):
log("check_channel_request(%s, %s)", kind, chanid)
Expand Down

0 comments on commit 4d2f3e7

Please sign in to comment.