Пример #1
0
def main(argv):
    #pylint: disable=import-outside-toplevel
    from xpra.platform import program_context
    with program_context("GSS-Auth", "GSS-Authentication"):
        if len(argv) != 3:
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write("usage: %s username token\n" % argv[0])
            return 1
        username = argv[1]
        token = argv[2]
        kwargs = {"username": username}
        a = Authenticator(**kwargs)
        server_salt, digest = a.get_challenge(["gss"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest.startswith("gss:"), "unexpected digest %r" % digest
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        response = gendigest(digest, token, combined_salt)
        caps = typedict({
            "challenge_response": response,
            "challenge_client_salt": client_salt,
        })
        r = a.authenticate(caps)
        print("success: %s" % bool(r))
        return r
Пример #2
0
    def send_challenge_reply(self, packet, password):
        if not password:
            if self.password_file:
                self.auth_error(
                    EXIT_PASSWORD_FILE_ERROR,
                    "failed to load password from file%s %s" %
                    (engs(self.password_file), csv(self.password_file)),
                    "no password available")
            else:
                self.auth_error(
                    EXIT_PASSWORD_REQUIRED,
                    "this server requires authentication and no password is available"
                )
            return
        if self.encryption:
            assert len(
                packet
            ) >= 3, "challenge does not contain encryption details to use for the response"
            server_cipher = typedict(packet[2])
            key = self.get_encryption_key()
            if key is None:
                self.auth_error(EXIT_ENCRYPTION,
                                "the server does not use any encryption",
                                "client requires encryption")
                return
            if not self.set_server_encryption(server_cipher, key):
                return
        #all server versions support a client salt,
        #they also tell us which digest to use:
        server_salt = bytestostr(packet[1])
        digest = bytestostr(packet[3])
        actual_digest = digest.split(":", 1)[0]
        l = len(server_salt)
        salt_digest = "xor"
        if len(packet) >= 5:
            salt_digest = bytestostr(packet[4])
        if salt_digest == "xor":
            #with xor, we have to match the size
            assert l >= 16, "server salt is too short: only %i bytes, minimum is 16" % l
            assert l <= 256, "server salt is too long: %i bytes, maximum is 256" % l
        else:
            #other digest, 32 random bytes is enough:
            l = 32
        client_salt = get_salt(l)
        salt = gendigest(salt_digest, client_salt, server_salt)
        authlog("combined %s salt(%s, %s)=%s", salt_digest,
                hexstr(server_salt), hexstr(client_salt), hexstr(salt))

        challenge_response = gendigest(actual_digest, password, salt)
        if not challenge_response:
            log("invalid digest module '%s': %s", actual_digest)
            self.auth_error(
                EXIT_UNSUPPORTED,
                "server requested '%s' digest but it is not supported" %
                actual_digest, "invalid digest")
            return
        authlog("%s(%s, %s)=%s", actual_digest, repr(password), repr(salt),
                repr(challenge_response))
        self.do_send_challenge_reply(challenge_response, client_salt)
Пример #3
0
def main(argv):
    #pylint: disable=import-outside-toplevel
    from xpra.platform import program_context
    with program_context("Kerberos-Token-Auth",
                         "Kerberos Token Authentication"):
        if len(argv) != 3:
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write("usage: %s username token\n" % argv[0])
            return 1
        username = argv[1]
        token = argv[2]
        kwargs = {"username": username}
        a = Authenticator(**kwargs)
        server_salt, digest = a.get_challenge(["xor"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest == "xor"
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        response = xor(token, combined_salt)
        caps = typedict({
            "challenge_response": response,
            "challenge_client_salt": client_salt,
        })
        a.authenticate(caps)
    return 0
Пример #4
0
def main(argv):
    from xpra.util import xor
    from xpra.net.digest import get_salt, get_digests, gendigest
    from xpra.platform import program_context
    with program_context("LDAP-Password-Auth", "LDAP-Password-Authentication"):
        for x in list(argv):
            if x in ("-v", "--verbose"):
                enable_debug_for("auth")
                argv.remove(x)
        if len(argv) not in (3,4,5,6,7):
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write("usage: %s username password [host] [port] [tls] [username_format]\n" % argv[0])
            return 1
        username = argv[1]
        password = argv[2]
        kwargs = {}
        if len(argv)>=4:
            kwargs["host"] = argv[3]
        if len(argv)>=5:
            kwargs["port"] = argv[4]
        if len(argv)>=6:
            kwargs["tls"] = argv[5]
        if len(argv)>=7:
            kwargs["username_format"] = argv[6]
        a = Authenticator(username, **kwargs)
        server_salt, digest = a.get_challenge(["xor"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest=="xor"
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        response = xor(password, combined_salt)
        r = a.authenticate(response, client_salt)
        print("success: %s" % r)
        return int(not r)
Пример #5
0
 def _test_hmac_auth(self, mod_name, password, **kwargs):
     for test_password in (password, "somethingelse"):
         a = self._init_auth(mod_name, **kwargs)
         assert a.requires_challenge()
         assert a.get_passwords()
         salt, mac = a.get_challenge(
             [x for x in get_digests() if x.startswith("hmac")])
         assert salt
         assert mac.startswith("hmac"), "invalid mac: %s" % mac
         client_salt = strtobytes(uuid.uuid4().hex + uuid.uuid4().hex)
         salt_digest = a.choose_salt_digest(get_digests())
         auth_salt = strtobytes(gendigest(salt_digest, client_salt, salt))
         digestmod = get_digest_module(mac)
         verify = hmac.HMAC(strtobytes(test_password),
                            auth_salt,
                            digestmod=digestmod).hexdigest()
         passed = a.authenticate(verify, client_salt)
         assert passed == (
             test_password == password
         ), "expected authentication to %s with %s vs %s" % ([
             "fail", "succeed"
         ][test_password == password], test_password, password)
         assert not a.authenticate(
             verify, client_salt
         ), "should not be able to athenticate again with the same values"
Пример #6
0
 def authenticate_check(self,
                        challenge_response: str,
                        client_salt: str = None) -> bool:
     if self.salt is None:
         log.error(
             "Error: illegal challenge response received - salt cleared or unset"
         )
         return False
     salt = self.get_response_salt(client_salt)
     password = gendigest("xor", challenge_response, salt)
     log("authenticate_check(%s, %s) response salt=%s",
         obsc(repr(challenge_response)), repr(client_salt), repr(salt))
     #warning: enabling logging here would log the actual system password!
     #log.info("authenticate(%s, %s) password=%s (%s)",
     #    hexstr(challenge_response), hexstr(client_salt), password, hexstr(password))
     #verify login:
     try:
         ret = self.check(password)
         log("authenticate_check(..)=%s", ret)
     except Exception as e:
         log("check(..)", exc_info=True)
         log.error("Error: %s authentication check failed:", self)
         log.error(" %s", e)
         return False
     return ret
Пример #7
0
def main(argv):
    from xpra.platform import program_context
    with program_context("Kerberos-Password-Auth",
                         "Kerberos-Password-Authentication"):
        if len(argv) not in (3, 4, 5):
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write(
                "usage: %s username password [service [realm]]\n" % argv[0])
            return 1
        username = argv[1]
        password = argv[2]
        kwargs = {"username": username}
        if len(argv) >= 4:
            kwargs["service"] = argv[3]
        if len(argv) == 5:
            kwargs["realm"] = argv[4]
        a = Authenticator(**kwargs)
        server_salt, digest = a.get_challenge(["xor"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest == "xor"
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        response = xor(password, combined_salt)
        caps = typedict({
            "challenge_response": response,
            "challenge_client_salt": client_salt,
        })
        a.authenticate(caps)
    return 0
Пример #8
0
 def _test_file_auth(self, mod_name, genauthdata, display_count=0):
     #no file, no go:
     a = self._init_auth(mod_name)
     assert a.requires_challenge()
     p = a.get_passwords()
     assert not p, "got passwords from %s: %s" % (a, p)
     #challenge twice is a fail
     assert a.get_challenge(get_digests())
     assert not a.get_challenge(get_digests())
     assert not a.get_challenge(get_digests())
     for muck in (0, 1):
         with TempFileContext(prefix=mod_name) as context:
             f = context.file
             filename = context.filename
             with f:
                 a = self._init_auth(mod_name, filename=filename)
                 password, filedata = genauthdata(a)
                 #print("saving password file data='%s' to '%s'" % (filedata, filename))
                 f.write(strtobytes(filedata))
                 f.flush()
                 assert a.requires_challenge()
                 salt, mac = a.get_challenge(get_digests())
                 assert salt
                 assert mac in get_digests()
                 assert mac != "xor"
                 password = strtobytes(password)
                 client_salt = strtobytes(uuid.uuid4().hex +
                                          uuid.uuid4().hex)[:len(salt)]
                 salt_digest = a.choose_salt_digest(get_digests())
                 assert salt_digest
                 auth_salt = strtobytes(
                     gendigest(salt_digest, client_salt, salt))
                 if muck == 0:
                     digestmod = get_digest_module(mac)
                     verify = hmac.HMAC(password,
                                        auth_salt,
                                        digestmod=digestmod).hexdigest()
                     assert a.authenticate(
                         verify, client_salt), "%s failed" % a.authenticate
                     if display_count > 0:
                         sessions = a.get_sessions()
                         assert len(sessions) >= 3
                         displays = sessions[2]
                         assert len(
                             displays
                         ) == display_count, "expected %i displays but got %i : %s" % (
                             display_count, len(sessions), sessions)
                     assert not a.authenticate(
                         verify, client_salt), "authenticated twice!"
                     passwords = a.get_passwords()
                     assert len(
                         passwords
                     ) == 1, "expected just one password in file, got %i" % len(
                         passwords)
                     assert password in passwords
                 elif muck == 1:
                     for verify in ("whatever", None, "bad"):
                         assert not a.authenticate(verify, client_salt)
     return a
Пример #9
0
def main(argv):
    #pylint: disable=import-outside-toplevel
    from xpra.net.digest import get_salt, get_digests, gendigest
    from xpra.platform import program_context
    with program_context("LDAP-Password-Auth", "LDAP-Password-Authentication"):
        for x in list(argv):
            if x in ("-v", "--verbose"):
                enable_debug_for("auth")
                argv.remove(x)
        if len(argv) not in (3, 4, 5, 6, 7):
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write(
                "usage: %s username password [host] [port] [tls] [username_format]\n"
                % argv[0])
            return 1
        username = argv[1]
        password = argv[2]
        kwargs = {"username": username}
        if len(argv) >= 4:
            kwargs["host"] = argv[3]
        if len(argv) >= 5:
            kwargs["port"] = argv[4]
        if len(argv) >= 6:
            kwargs["tls"] = argv[5]
        if len(argv) >= 7:
            kwargs["username_format"] = argv[6]
        a = Authenticator(**kwargs)
        server_salt, digest = a.get_challenge(["xor"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest == "xor"
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        assert digest == "xor"
        response = gendigest(digest, password, combined_salt)
        caps = typedict({
            "challenge_response": response,
            "challenge_client_salt": client_salt,
        })
        r = a.authenticate(caps)
        print("success: %s" % bool(r))
        return int(not r)
Пример #10
0
 def get_response_salt(self, client_salt=None):
     server_salt = self.salt
     #make sure it does not get re-used:
     self.salt = None
     if client_salt is None:
         return server_salt
     salt = gendigest(self.salt_digest, client_salt, server_salt)
     if salt in SysAuthenticator.USED_SALT:
         raise Exception("danger: an attempt was made to re-use the same computed salt")
     log("combined salt(%s, %s)=%s", hexstr(server_salt), hexstr(client_salt), hexstr(salt))
     SysAuthenticator.USED_SALT.append(salt)
     return salt
Пример #11
0
 def test_all_digests(self):
     for digest in get_digests():
         if digest.startswith("hmac"):
             m = get_digest_module(digest)
             assert m is not None, "digest module not found for '%s'" % digest
         salt = get_salt(32)
         password = "******"
         d = gendigest(digest, password, salt)
         assert d is not None
         assert not verify_digest(digest, None, salt, d)
         assert not verify_digest(digest, password, None, d)
         assert not verify_digest(digest, password, salt, None)
         assert not verify_digest(digest, password, salt, d[:-1])
         assert verify_digest(digest, password, salt, d)
Пример #12
0
def main(argv):
    from xpra.platform import program_context
    with program_context("GSS-Auth", "GSS-Authentication"):
        if len(argv) != 3:
            sys.stderr.write("%s invalid arguments\n" % argv[0])
            sys.stderr.write("usage: %s username token\n" % argv[0])
            return 1
        username = argv[1]
        token = argv[2]
        kwargs = {}
        a = Authenticator(username, **kwargs)
        server_salt, digest = a.get_challenge(["xor"])
        salt_digest = a.choose_salt_digest(get_digests())
        assert digest == "xor"
        client_salt = get_salt(len(server_salt))
        combined_salt = gendigest(salt_digest, client_salt, server_salt)
        response = xor(token, combined_salt)
        a.authenticate(response, client_salt)
    return 0
Пример #13
0
 def process_server_packet(self, proto, packet):
     packet_type = bytestostr(packet[0])
     log("process_server_packet: %s", packet_type)
     if packet_type == Protocol.CONNECTION_LOST:
         self.stop(proto, "server connection lost")
         return
     if packet_type == "disconnect":
         reason = bytestostr(packet[1])
         log("got disconnect from server: %s", reason)
         if self.exit:
             self.server_protocol.close()
         else:
             self.stop(None, "disconnect from server", reason)
     elif packet_type == "hello":
         c = typedict(packet[1])
         if c.boolget("ping-echo-sourceid"):
             self.schedule_server_ping()
         maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
         caps = self.filter_server_caps(c)
         #add new encryption caps:
         if self.cipher:
             from xpra.net.crypto import crypto_backend_init, new_cipher_caps, DEFAULT_PADDING
             crypto_backend_init()
             padding_options = self.caps.strtupleget(
                 "cipher.padding.options", [DEFAULT_PADDING])
             auth_caps = new_cipher_caps(self.client_protocol, self.cipher,
                                         self.encryption_key,
                                         padding_options)
             caps.update(auth_caps)
         #may need to bump packet size:
         proto.max_packet_size = max(16 * 1024 * 1024, maxw * maxh * 4 * 4)
         file_transfer = self.caps.boolget("file-transfer") and c.boolget(
             "file-transfer")
         file_size_limit = max(self.caps.intget("file-size-limit"),
                               c.intget("file-size-limit"))
         file_max_packet_size = int(file_transfer) * (
             1024 + file_size_limit * 1024 * 1024)
         self.client_protocol.max_packet_size = max(
             self.client_protocol.max_packet_size, file_max_packet_size)
         self.server_protocol.max_packet_size = max(
             self.server_protocol.max_packet_size, file_max_packet_size)
         packet = ("hello", caps)
     elif packet_type == "ping_echo" and self.server_ping_timer and len(
             packet) >= 7 and packet[6] == strtobytes(self.uuid):
         #this is one of our ping packets:
         self.server_last_ping_echo = packet[1]
         self.server_last_ping_latency = 1000 * monotonic_time(
         ) - self.server_last_ping_echo
         log("ping-echo: server latency=%.1fms",
             self.server_last_ping_latency)
         return
     elif packet_type == "info-response":
         #adds proxy info:
         #note: this is only seen by the client application
         #"xpra info" is a new connection, which talks to the proxy server...
         info = packet[1]
         info.update(self.get_proxy_info(proto))
     elif packet_type == "lost-window":
         wid = packet[1]
         #mark it as lost so we can drop any current/pending frames
         self.lost_windows.add(wid)
         #queue it so it gets cleaned safely (for video encoders mostly):
         self.encode_queue.put(packet)
         #and fall through so tell the client immediately
     elif packet_type == "draw":
         #use encoder thread:
         self.encode_queue.put(packet)
         #which will queue the packet itself when done:
         return
     #we do want to reformat cursor packets...
     #as they will have been uncompressed by the network layer already:
     elif packet_type == "cursor":
         #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", "png", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", ""]
         if len(packet) >= 8:
             #hard to distinguish png cursors from normal cursors...
             try:
                 int(packet[1])
                 self._packet_recompress(packet, 8, "cursor")
             except (TypeError, ValueError):
                 self._packet_recompress(packet, 9, "cursor")
     elif packet_type == "window-icon":
         self._packet_recompress(packet, 5, "icon")
     elif packet_type == "send-file":
         if packet[6]:
             packet[6] = Compressed("file-data", packet[6])
     elif packet_type == "send-file-chunk":
         if packet[3]:
             packet[3] = Compressed("file-chunk-data", packet[3])
     elif packet_type == "challenge":
         password = self.disp_desc.get("password",
                                       self.session_options.get("password"))
         log("password from %s / %s = %s", self.disp_desc,
             self.session_options, password)
         if not password:
             if not PASSTHROUGH_AUTH:
                 self.stop(None, "authentication requested by the server,",
                           "but no password is available for this session")
             #otherwise, just forward it to the client
             self.client_challenge_packet = packet
         else:
             from xpra.net.digest import get_salt, gendigest
             #client may have already responded to the challenge,
             #so we have to handle authentication from this end
             server_salt = bytestostr(packet[1])
             l = len(server_salt)
             digest = bytestostr(packet[3])
             salt_digest = "xor"
             if len(packet) >= 5:
                 salt_digest = bytestostr(packet[4])
             if salt_digest in ("xor", "des"):
                 if not LEGACY_SALT_DIGEST:
                     self.stop(
                         None, "server uses legacy salt digest '%s'" %
                         salt_digest)
                     return
                 log.warn(
                     "Warning: server using legacy support for '%s' salt digest",
                     salt_digest)
             if salt_digest == "xor":
                 #with xor, we have to match the size
                 assert l >= 16, "server salt is too short: only %i bytes, minimum is 16" % l
                 assert l <= 256, "server salt is too long: %i bytes, maximum is 256" % l
             else:
                 #other digest, 32 random bytes is enough:
                 l = 32
             client_salt = get_salt(l)
             salt = gendigest(salt_digest, client_salt, server_salt)
             challenge_response = gendigest(digest, password, salt)
             if not challenge_response:
                 log("invalid digest module '%s': %s", digest)
                 self.stop(
                     None,
                     "server requested '%s' digest but it is not supported"
                     % digest)
                 return
             log.info("sending %s challenge response", digest)
             self.send_hello(challenge_response, client_salt)
             return
     self.queue_client_packet(packet)
Пример #14
0
 def test_invalid_digest(self):
     for invalid_digest in (None, "foo", "hmac", "hmac+INVALID_HASH_ALGO"):
         assert get_digest_module(invalid_digest) is None
         assert gendigest(invalid_digest, "bar", "0" * 16) is None