Esempio n. 1
0
 def check(self, password):
     log("check(%s)", obsc(password))
     def emsg(e):
         try:
             log.warn(" LDAP Error: %s", e.message["desc"])
             if "info" in e.message:
                 log.warn("  %s", e.message["info"])
         except:
             #python3: no way to get to the message dict?
             log.warn(" %s", e)
     try:
         import ldap
     except ImportError as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: cannot use ldap authentication:")
         log.warn(" %s", e)
         return False
     try:
         assert self.username and password
         if self.tls:
             protocol = "ldaps"
         else:
             protocol = "ldap"
         server = "%s://%s:%i" % (protocol, self.host, self.port)
         conn = ldap.initialize(server, trace_level=LDAP_TRACE_LEVEL or is_debug_enabled("auth"))
         conn.protocol_version = LDAP_PROTOCOL_VERSION
         conn.set_option(ldap.OPT_REFERRALS, LDAP_REFERRALS)
         if self.cacert:
             conn.set_option(ldap.OPT_X_TLS_CACERTFILE, self.cacert)
         log("ldap.open(%s)=%s", server, conn)
         try:
             domain = socket.getfqdn().split(".", 1)[1]
         except:
             domain = "localdomain"
         user = self.username_format.replace("%username", self.username).replace("%domain", domain)
         log("user=%s", user)
         try:
             #password should be the result of a digest function,
             #ie: xor will return bytes..
             p = bytestostr(password)
             password = p.encode(self.encoding)
             log("ldap encoded password as %s", self.encoding)
         except:
             pass
         v = conn.simple_bind_s(user, password)
         log("simple_bind_s(%s, %s)=%s", user, obsc(password), v)
         return True
     except ldap.INVALID_CREDENTIALS:
         log("check(..)", exc_info=True)
         return False
     except ldap.SERVER_DOWN as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: LDAP %sserver at %s:%i is unreachable", ["", "TLS "][self.tls], self.host, self.port)
         emsg(e)
     except ldap.LDAPError as e:
         log("check(..)", exc_info=True)
         log.warn("Error: ldap authentication failed:")
         emsg(e)
         return False
Esempio n. 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
        encryption = self.get_encryption()
        if 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 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]
        if actual_digest=="des":
            salt = client_salt = server_salt
        else:
            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, obsc(password), repr(salt), obsc(challenge_response))
        self.do_send_challenge_reply(challenge_response, client_salt)
Esempio n. 3
0
 def do_process_challenge_prompt(self, packet, prompt="password"):
     authlog("do_process_challenge_prompt() use_tty=%s", use_tty())
     if use_tty():
         import getpass
         authlog("stdin isatty, using password prompt")
         password = getpass.getpass("%s :" %
                                    self.get_challenge_prompt(prompt))
         authlog("password read from tty via getpass: %s", obsc(password))
         self.send_challenge_reply(packet, password)
         return True
     else:
         from xpra.platform.paths import get_nodock_command
         cmd = get_nodock_command() + ["_pass", prompt]
         try:
             from subprocess import Popen, PIPE
             proc = Popen(cmd, stdout=PIPE)
             getChildReaper().add_process(proc, "password-prompt", cmd,
                                          True, True)
             out, err = proc.communicate(None, 60)
             authlog("err(%s)=%s", cmd, err)
             password = out.decode()
             self.send_challenge_reply(packet, password)
             return True
         except Exception:
             log("Error: failed to show GUi for password prompt",
                 exc_info=True)
     return False
Esempio n. 4
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
Esempio n. 5
0
def get_host_info(obfuscate=False) -> dict:
    #this function is for non UI thread info
    info = {
        "pid": os.getpid(),
        "byteorder": sys.byteorder,
        "python": {
            "bits": BITS,
            "full_version": sys.version,
            "version": ".".join(str(x) for x in sys.version_info[:3]),
        },
    }
    try:
        hostname = socket.gethostname()
        if obfuscate and hostname.find(".") > 0:
            parts = hostname.split(".")
            for i, part in enumerate(parts):
                if i > 0:
                    parts[i] = obsc(part)
            hostname = ".".join(parts)
        if hostname:
            info["hostname"] = hostname
    except OSError:
        pass
    if POSIX:
        info.update({
            "uid": os.getuid(),
            "gid": os.getgid(),
        })
    return info
Esempio n. 6
0
 def process_challenge_env(self, packet):
     k = "XPRA_PASSWORD"
     password = os.environ.get(k)
     authlog("process_challenge_env() %s=%s", k, obsc(password))
     if password:
         self.send_challenge_reply(packet, password)
         return True
     return False
Esempio n. 7
0
 def do_process_challenge_prompt(self, packet, prompt="password"):
     authlog("do_process_challenge_prompt() use_tty=%s", use_tty())
     if use_tty():
         import getpass
         authlog("stdin isatty, using password prompt")
         password = getpass.getpass("%s :" % self.get_challenge_prompt(prompt))
         authlog("password read from tty via getpass: %s", obsc(password))
         self.send_challenge_reply(packet, password)
         return True
     return False
Esempio n. 8
0
 def process_challenge_file(self, packet):
     if self.password_index < len(self.password_file):
         password_file = self.password_file[self.password_index]
         self.password_index += 1
         filename = os.path.expanduser(password_file)
         password = load_binary_file(filename)
         authlog("password read from file %i '%s': %s", self.password_index,
                 password_file, obsc(password))
         self.send_challenge_reply(packet, password)
         return True
     return False
Esempio n. 9
0
 def do_process_challenge_prompt(self, packet, prompt="password"):
     authlog("do_process_challenge_prompt() isatty=%s", sys.stdin.isatty())
     if sys.stdin.isatty() and not os.environ.get("MSYSCON"):
         import getpass
         authlog("stdin isatty, using password prompt")
         password = getpass.getpass("%s :" %
                                    self.get_challenge_prompt(prompt))
         authlog("password read from tty via getpass: %s", obsc(password))
         self.send_challenge_reply(packet, password)
         return True
     return False
Esempio n. 10
0
 def check(self, password):
     log("check(%s)", obsc(password))
     try:
         from ldap3 import Server, Connection, Tls, ALL, SIMPLE, SASL, NTLM  #@UnresolvedImport
     except ImportError as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: cannot use ldap3 authentication:")
         log.warn(" %s", e)
         return False
     try:
         MECHANISM = {
             "SIMPLE": SIMPLE,
             "SASL": SASL,
             "NTLM": NTLM,
         }
         authentication = MECHANISM[self.authentication]
         tls = None
         if self.tls:
             tls = Tls(validate=self.tls_validate,
                       version=self.tls_version,
                       ca_certs_file=self.cacert)
             log("TLS=%s", tls)
         server = Server(self.host,
                         port=self.port,
                         tls=tls,
                         use_ssl=self.tls,
                         get_info=ALL)
         log("ldap3 Server(%s)=%s", (self.host, self.port, self.tls),
             server)
         conn = Connection(server,
                           user=self.username,
                           password=password,
                           authentication=authentication,
                           receive_timeout=10)
         log("ldap3 Connection(%s, %s, %s)=%s", server, self.username,
             self.authentication, conn)
         if self.tls:
             conn.start_tls()
         r = conn.bind()
         log("ldap3 %s.bind()=%s", conn, r)
         if not r:
             return False
         if is_debug_enabled("auth"):
             log("ldap3 server info:")
             for l in server.info.splitlines():
                 log(" %s", l)
         log("ldap3 who_am_i()=%s", conn.extend.standard.who_am_i())
         return True
     except Exception as e:
         log("ldap3 check(..)", exc_info=True)
         log.error("Error: ldap3 authentication failed:")
         log.error(" %s", e)
         return False
Esempio n. 11
0
 def authenticate_hmac(self, challenge_response, client_salt=None):
     if not self.salt:
         log.error("Error: illegal challenge response received - salt cleared or unset")
         return None
     salt = self.get_response_salt(client_salt)
     password = self.get_password()
     log("authenticate_hmac() get_password()=%s", obsc(password))
     if not password:
         log.warn("Warning: authentication failed")
         log.warn(" no password for '%s' in '%s'", self.username, self.password_filename)
         return False
     if not verify_digest(self.digest, password, salt, challenge_response):
         log.warn("Warning: %s challenge for '%s' does not match", self.digest, self.username)
         return False
     return True