def check_request_cookie_for_admin_access(): session = auth_service.get_session(None, request.cookies.get("session", ""), "cookie", env) if not session: return False privs = get_mail_user_privileges(session["email"], env) if not isinstance(privs, list): return False if "admin" not in privs: return False return True
def check_imap_login(self, email, pw, env): # Validate a user's credentials. # Sanity check. if email == "" or pw == "": return "Enter an email address and password." # Authenticate. try: # Use doveadm to check credentials. doveadm will return # a non-zero exit status if the credentials are no good, # and check_call will raise an exception in that case. utils.shell('check_call', [ "/usr/bin/doveadm", "auth", "test", email, pw ]) except: # Login failed. return "Invalid email address or password." # Authorize. # (This call should never fail on a valid user.) privs = get_mail_user_privileges(email, env) if isinstance(privs, tuple): raise Exception("Error getting privileges.") if "admin" not in privs: return "You are not an administrator for this system." return "OK"
def check_imap_login(self, email, pw, env): # Validate a user's credentials. # Sanity check. if email == "" or pw == "": return "Enter an email address and password." # Authenticate. try: # Use doveadm to check credentials. doveadm will return # a non-zero exit status if the credentials are no good, # and check_call will raise an exception in that case. utils.shell('check_call', ["/usr/bin/doveadm", "auth", "test", email, pw]) except: # Login failed. return "Invalid email address or password." # Authorize. # (This call should never fail on a valid user.) privs = get_mail_user_privileges(email, env) if isinstance(privs, tuple): raise Exception("Error getting privileges.") if "admin" not in privs: return "You are not an administrator for this system." return "OK"
def check_user_auth(self, email, pw, request, env): # Validate a user's login email address and password. If MFA is enabled, # check the MFA token in the X-Auth-Token header. # # On success returns a list of privileges (e.g. [] or ['admin']). On login # failure, raises a ValueError with a login error message. # Sanity check. if email == "" or pw == "": raise ValueError("Enter an email address and password.") # The password might be a user-specific API key. create_user_key raises # a ValueError if the user does not exist. if hmac.compare_digest(self.create_user_key(email, env), pw): # OK. pass else: # Get the hashed password of the user. Raise a ValueError if the # email address does not correspond to a user. pw_hash = get_mail_password(email, env) # Authenticate. try: # Use 'doveadm pw' to check credentials. doveadm will return # a non-zero exit status if the credentials are no good, # and check_call will raise an exception in that case. utils.shell('check_call', [ "/usr/bin/doveadm", "pw", "-p", pw, "-t", pw_hash, ]) except: # Login failed. raise ValueError("Invalid password.") # If MFA is enabled, check that MFA passes. status, hints = validate_auth_mfa(email, request, env) if not status: # Login valid. Hints may have more info. raise ValueError(",".join(hints)) # Get privileges for authorization. This call should never fail because by this # point we know the email address is a valid user. But on error the call will # return a tuple of an error message and an HTTP status code. privs = get_mail_user_privileges(email, env) if isinstance(privs, tuple): raise ValueError(privs[0]) # Return a list of privileges. return privs
def get_user_credentials(self, email, pw, env): # Validate a user's credentials. On success returns a list of # privileges (e.g. [] or ['admin']). On failure raises a ValueError # with a login error message. # Sanity check. if email == "" or pw == "": raise ValueError("Enter an email address and password.") # The password might be a user-specific API key. if hmac.compare_digest(self.create_user_key(email), pw): # OK. pass else: # Get the hashed password of the user. Raise a ValueError if the # email address does not correspond to a user. pw_hash = get_mail_password(email, env) # Authenticate. try: # Use 'doveadm pw' to check credentials. doveadm will return # a non-zero exit status if the credentials are no good, # and check_call will raise an exception in that case. utils.shell('check_call', [ "/usr/bin/doveadm", "pw", "-p", pw, "-t", pw_hash, ]) except: # Login failed. raise ValueError("Invalid password.") # Get privileges for authorization. # (This call should never fail on a valid user. But if it did fail, it would # return a tuple of an error message and an HTTP status code.) privs = get_mail_user_privileges(email, env) if isinstance(privs, tuple): raise Exception("Error getting privileges.") # Return a list of privileges. return privs
def mail_user_privs(): privs = get_mail_user_privileges(request.args.get('email', ''), env) if isinstance(privs, tuple): return privs # error return "\n".join(privs)
def authenticate(self, request, env, login_only=False, logout=False): """Test if the HTTP Authorization header's username matches the system key, a session key, or if the username/password passed in the header matches a local user. Returns a tuple of the user's email address and list of user privileges (e.g. ('my@email', []) or ('my@email', ['admin']); raises a ValueError on login failure. If the user used the system API key, the user's email is returned as None since this key is not associated with a user.""" def parse_http_authorization_basic(header): def decode(s): return base64.b64decode(s.encode('ascii')).decode('ascii') if " " not in header: return None, None scheme, credentials = header.split(maxsplit=1) if scheme != 'Basic': return None, None credentials = decode(credentials) if ":" not in credentials: return None, None username, password = credentials.split(':', maxsplit=1) return username, password username, password = parse_http_authorization_basic( request.headers.get('Authorization', '')) if username in (None, ""): raise ValueError("Authorization header invalid.") if username.strip() == "" and password.strip() == "": raise ValueError( "No email address, password, session key, or API key provided." ) # If user passed the system API key, grant administrative privs. This key # is not associated with a user. if username == self.key and not login_only: return (None, ["admin"]) # If the password corresponds with a session token for the user, grant access for that user. if self.get_session(username, password, "login", env) and not login_only: sessionid = password session = self.sessions[sessionid] if logout: # Clear the session. del self.sessions[sessionid] else: # Re-up the session so that it does not expire. self.sessions[sessionid] = session # If no password was given, but a username was given, we're missing some information. elif password.strip() == "": raise ValueError("Enter a password.") else: # The user is trying to log in with a username and a password # (and possibly a MFA token). On failure, an exception is raised. self.check_user_auth(username, password, request, env) # Get privileges for authorization. This call should never fail because by this # point we know the email address is a valid user --- unless the user has been # deleted after the session was granted. On error the call will return a tuple # of an error message and an HTTP status code. privs = get_mail_user_privileges(username, env) if isinstance(privs, tuple): raise ValueError(privs[0]) # Return the authorization information. return (username, privs)