def testDigest(self): self.getPage('/digest/') self.assertStatus(401) value = None for k, v in self.headers: if k.lower() == 'www-authenticate': if v.startswith('Digest'): value = v break if value is None: self._handlewebError( 'Digest authentification scheme was not found') value = value[7:] items = value.split(', ') tokens = {} for item in items: key, value = item.split('=') tokens[key.lower()] = value missing_msg = '%s is missing' bad_value_msg = "'%s' was expecting '%s' but found '%s'" nonce = None if 'realm' not in tokens: self._handlewebError(missing_msg % 'realm') elif tokens['realm'] != '"localhost"': self._handlewebError(bad_value_msg % ('realm', '"localhost"', tokens['realm'])) if 'nonce' not in tokens: self._handlewebError(missing_msg % 'nonce') else: nonce = tokens['nonce'].strip('"') if 'algorithm' not in tokens: self._handlewebError(missing_msg % 'algorithm') elif tokens['algorithm'] != '"MD5"': self._handlewebError(bad_value_msg % ('algorithm', '"MD5"', tokens['algorithm'])) if 'qop' not in tokens: self._handlewebError(missing_msg % 'qop') elif tokens['qop'] != '"auth"': self._handlewebError(bad_value_msg % ('qop', '"auth"', tokens['qop'])) base_auth = 'Digest username="******", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' auth = base_auth % (nonce, '', '00000001') params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, 'test') auth = base_auth % (nonce, response, '00000001') self.getPage('/digest/', [('Authorization', auth)]) self.assertStatus(401) base_auth = 'Digest username="******", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' auth = base_auth % (nonce, '', '00000001') params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, 'test') auth = base_auth % (nonce, response, '00000001') self.getPage('/digest/', [('Authorization', auth)]) self.assertStatus('200 OK') self.assertBody("Hello test, you've been authorized.")
def testDigest(self): self.getPage('/digest/') self.assertStatus(401) value = None for k, v in self.headers: if k.lower() == 'www-authenticate': if v.startswith('Digest'): value = v break if value is None: self._handlewebError('Digest authentification scheme was not found') value = value[7:] items = value.split(', ') tokens = {} for item in items: key, value = item.split('=') tokens[key.lower()] = value missing_msg = '%s is missing' bad_value_msg = "'%s' was expecting '%s' but found '%s'" nonce = None if 'realm' not in tokens: self._handlewebError(missing_msg % 'realm') elif tokens['realm'] != '"localhost"': self._handlewebError(bad_value_msg % ('realm', '"localhost"', tokens['realm'])) if 'nonce' not in tokens: self._handlewebError(missing_msg % 'nonce') else: nonce = tokens['nonce'].strip('"') if 'algorithm' not in tokens: self._handlewebError(missing_msg % 'algorithm') elif tokens['algorithm'] != '"MD5"': self._handlewebError(bad_value_msg % ('algorithm', '"MD5"', tokens['algorithm'])) if 'qop' not in tokens: self._handlewebError(missing_msg % 'qop') elif tokens['qop'] != '"auth"': self._handlewebError(bad_value_msg % ('qop', '"auth"', tokens['qop'])) base_auth = 'Digest username="******", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' auth = base_auth % (nonce, '', '00000001') params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, 'test') auth = base_auth % (nonce, response, '00000001') self.getPage('/digest/', [('Authorization', auth)]) self.assertStatus(401) base_auth = 'Digest username="******", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"' auth = base_auth % (nonce, '', '00000001') params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, 'test') auth = base_auth % (nonce, response, '00000001') self.getPage('/digest/', [('Authorization', auth)]) self.assertStatus('200 OK') self.assertBody("Hello test, you've been authorized.")
def check_auth(users, encrypt=None): """If an authorization header contains credentials, return True, else False.""" if 'authorization' in cherrypy.request.headers: # make sure the provided credentials are correctly set ah = httpauth.parseAuthorization(cherrypy.request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if callable(users): users = users() # expect it to return a dictionary if not isinstance(users, dict): raise ValueError, "Authentication users must be a dictionary" # fetch the user password password = users.get(ah["username"], None) # validate the authorization by re-computing it here # and compare it with what the user-agent provided if httpauth.checkResponse(ah, password, method=cherrypy.request.method, encrypt=encrypt): return True return False
def check_auth(users, encrypt=None, realm=None): """If an authorization header contains credentials, return True, else False.""" request = cherrypy.serving.request if 'authorization' in request.headers: ah = httpauth.parseAuthorization(request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if hasattr(users, '__call__'): try: users = users() if not isinstance(users, dict): raise ValueError( 'Authentication users must be a dictionary') password = users.get(ah['username'], None) except TypeError: password = users(ah['username']) else: if not isinstance(users, dict): raise ValueError('Authentication users must be a dictionary') password = users.get(ah['username'], None) if httpauth.checkResponse(ah, password, method=request.method, encrypt=encrypt, realm=realm): request.login = ah['username'] return True request.login = False return False
def check_auth(users, encrypt = None, realm = None): request = cherrypy.serving.request if 'authorization' in request.headers: ah = httpauth.parseAuthorization(request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if hasattr(users, '__call__'): try: users = users() if not isinstance(users, dict): raise ValueError('Authentication users must be a dictionary') password = users.get(ah['username'], None) except TypeError: password = users(ah['username']) else: if not isinstance(users, dict): raise ValueError('Authentication users must be a dictionary') password = users.get(ah['username'], None) if httpauth.checkResponse(ah, password, method=request.method, encrypt=encrypt, realm=realm): request.login = ah['username'] return True request.login = False return False
def login(self): """Validate user credentials""" if cherrypy.request.method != "POST": return {'_status': 'ERR', '_issues': ['You must only POST on this endpoint.']} username = cherrypy.request.json.get('username', None) password = cherrypy.request.json.get('password', None) # Get HTTP authentication authorization = cherrypy.request.headers.get('Authorization', None) if authorization: ah = httpauth.parseAuthorization(authorization) username = ah['username'] password = ah['password'] else: if cherrypy.request and not cherrypy.request.json: return {'_status': 'ERR', '_issues': ['You must POST parameters on this endpoint.']} if username is None: return {'_status': 'ERR', '_issues': ['Missing username parameter.']} token = self.app.backend_token(username, password) if not token: return {'_status': 'ERR', '_issues': ['Access denied.']} cherrypy.session[SESSION_KEY] = cherrypy.request.login = token return {'_status': 'OK', '_result': [token]}
def check_password(): """If the supplied username and password are valid, returns False, indicating that the request has not been handled, and other request handlers should be allowed to execute. If the supplied username and password are not valid, returns True, indicating that the request has been handled, and other request handlers should not be allowed to execute. An HTTP 401/403 error will also be thrown in this case. The password argument is first treated as a session token. If this check fails, then it is treated as a password. If either test passes, the cherrypy.request.authorized member is set to True and the cherrypy.request.user member is set to the authenticated user.""" db = DatabaseWrapper() session = db.get_session() if 'authorization' in cherrypy.request.headers: auth = httpauth.parseAuthorization(cherrypy.request.headers['authorization']) if auth is None: raise cherrypy.HTTPError(400, 'Invalid Authorization Header.') username = auth['username'] password = auth['password'] user = None # try to treat username as a session token if username is not None: user = session.query(User).filter(User.username == username and User.token == password and User.token_expires > datetime.datetime.utcnow()).first() if user is not None: user.update_token_expiry() session.commit() cherrypy.request.user = user # try to look up username and password in the database if user is None and username is not None and password is not None: user = session.query(User).filter(User.username == username).first() if user is not None and user.passhash == user.password_hash(username, password): cherrypy.request.user = user if user is not None: cherrypy.request.authorized = True # if the user was authorized, allow other page handlers to run return False else: cherrypy.request.authorized = False if cherrypy.request.headers['X-Requested-With'] == 'XMLHttpRequest': # if the request came from a browser, don't send a 401 because that will # trigger a shitty looking popup. Use a 403 instead. raise cherrypy.HTTPError(403, 'Invalid Credentials.') else: raise cherrypy.HTTPError(401, 'Invalid Credentials.') # the user was not authorized, suppress other page handlers from running return True else: raise cherrypy.HTTPError(400, 'Missing Authorization Header.')
def parseBasicAuthorizationHeaders(cls): try: username = None password = None authorization = cherrypy.request.headers['authorization'] authorizationHeader = httpauth.parseAuthorization(authorization) if authorizationHeader['auth_scheme'] == 'basic': username = authorizationHeader['username'] password = authorizationHeader['password'] if username and password: return (username, password) else: raise AuthorizationError( 'Username and/or password not supplied.') except Exception as ex: errorMsg = 'Could not extract username/password from authorization header: %s' % ex raise AuthorizationError(errorMsg)
def check_auth(users, encrypt=None, realm=None): """If an authorization header contains credentials, return True or False. """ request = cherrypy.serving.request if 'authorization' in request.headers: # make sure the provided credentials are correctly set ah = httpauth.parseAuthorization(request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if hasattr(users, '__call__'): try: # backward compatibility users = users() # expect it to return a dictionary if not isinstance(users, dict): raise ValueError( 'Authentication users must be a dictionary') # fetch the user password password = users.get(ah['username'], None) except TypeError: # returns a password (encrypted or clear text) password = users(ah['username']) else: if not isinstance(users, dict): raise ValueError('Authentication users must be a dictionary') # fetch the user password password = users.get(ah['username'], None) # validate the authorization by re-computing it here # and compare it with what the user-agent provided if httpauth.checkResponse(ah, password, method=request.method, encrypt=encrypt, realm=realm): request.login = ah['username'] return True request.login = False return False
def login(self, username=None, password=None, fromPage='/'): \ # pylint: disable=unused-argument if int(cherrypy.request.headers['Content-Length']): postdata = cherrypy.request.json else: postdata = {} username = postdata['username'] if 'username' in postdata else None password = postdata['password'] if 'password' in postdata else None if username is None or password is None: logger = logging.getLogger('tortuga.login') logger.addHandler(logging.NullHandler()) logger.debug('Going for Basic Authentication') authorization = cherrypy.request.headers['Authorization'] logger.debug('Authorization: %s' % (authorization)) ah = httpauth.parseAuthorization(authorization) if ah['auth_scheme'] == 'basic': username = ah['username'] password = ah['password'] if username is None or password is None: logger.debug('Either username and/or password unspecified') return '' errorMsg = checkCredentials(username, password) if errorMsg: self.addTortugaResponseHeaders( tortugaStatus.TORTUGA_USER_NOT_AUTHORIZED_ERROR, errorMsg) cherrypy.response.status = 401 return '' cherrypy.session[SESSION_KEY] = cherrypy.request.login = username self.addTortugaResponseHeaders(tortugaStatus.TORTUGA_OK)
def checkAuth(*args): # pylint: disable=unused-argument """ A tool that looks in config for 'auth.require'. If found and it is not None, a login is required and the entry is evaluated as a list of conditions that the user must fulfill. """ logger = logging.getLogger('tortuga.checkAuth') logger.addHandler(logging.NullHandler()) conditions = cherrypy.request.config.get('auth.require', None) if conditions is not None: username = cherrypy.session.get(SESSION_KEY) if username: cherrypy.request.login = username for condition in conditions: # A condition is just a callable that returns true or false if not condition(): # Send old page as fromPage parameter logger.debug('Authorization failed for: %s ' % (username)) raise TortugaHTTPAuthError() else: username = None password = None if 'authorization' not in cherrypy.request.headers: raise TortugaHTTPAuthError() authorization = cherrypy.request.headers['authorization'] ah = httpauth.parseAuthorization(authorization) if ah['auth_scheme'] == 'basic': username = ah['username'] password = ah['password'] if username and password and \ not checkCredentials(username, password): return raise TortugaHTTPAuthError()
def check_auth(users, encrypt=None, realm=None): """If an authorization header contains credentials, return True or False. """ request = cherrypy.serving.request if 'authorization' in request.headers: # make sure the provided credentials are correctly set ah = httpauth.parseAuthorization(request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if hasattr(users, '__call__'): try: # backward compatibility users = users() # expect it to return a dictionary if not isinstance(users, dict): raise ValueError( "Authentication users must be a dictionary") # fetch the user password password = users.get(ah["username"], None) except TypeError: # returns a password (encrypted or clear text) password = users(ah["username"]) else: if not isinstance(users, dict): raise ValueError("Authentication users must be a dictionary") # fetch the user password password = users.get(ah["username"], None) # validate the authorization by re-computing it here # and compare it with what the user-agent provided if httpauth.checkResponse(ah, password, method=request.method, encrypt=encrypt, realm=realm): request.login = ah["username"] return True request.login = False return False
def check_auth(users, encrypt=None, realm=None): """If an authorization header contains credentials, return True, else False.""" if 'authorization' in cherrypy.request.headers: # make sure the provided credentials are correctly set ah = httpauth.parseAuthorization(cherrypy.request.headers['authorization']) if ah is None: raise cherrypy.HTTPError(400, 'Bad Request') if not encrypt: encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5] if callable(users): try: # backward compatibility users = users() # expect it to return a dictionary if not isinstance(users, dict): raise ValueError, "Authentication users must be a dictionary" # fetch the user password password = users.get(ah["username"], None) except TypeError: # returns a password (encrypted or clear text) password = users(ah["username"]) else: if not isinstance(users, dict): raise ValueError, "Authentication users must be a dictionary" # fetch the user password password = users.get(ah["username"], None) # validate the authorization by re-computing it here # and compare it with what the user-agent provided if httpauth.checkResponse(ah, password, method=cherrypy.request.method, encrypt=encrypt, realm=realm): cherrypy.request.login = ah["username"] return True if ah.get('username') or ah.get('password'): logging.info('Attempt to login with wrong credentials from %s', cherrypy.request.headers['Remote-Addr']) cherrypy.request.login = False return False
def parseBasicAuthorizationHeaders(): try: logger = loggingManager.getLogger('parseBasicAuthorizationHeader') username = None password = None authorization = cherrypy.request.headers['authorization'] authorizationHeader = httpauth.parseAuthorization(authorization) logger.debug('Authorization header: %s' % authorizationHeader) if authorizationHeader['auth_scheme'] == 'basic': username = authorizationHeader['username'] password = authorizationHeader['password'] logger.debug('Got username/password from headers: %s/%s' % (username, password)) if username and password: return (username, password) else: raise AuthorizationError('Username and/or password not supplied.') except Exception, ex: errorMsg = 'Could not extract username/password from authorization header: %s' % ex raise AuthorizationError(errorMsg)
def protect(*args, **kwargs): # pylint: disable=unused-argument """ Check user credentials from HTTP Authorization request header """ authenticated = False # A condition is just a callable that returns true or false conditions = cherrypy.request.config.get('auth.require', None) if conditions is not None: app = cherrypy.request.app.root.app try: logger.debug("Checking session: %s", SESSION_KEY) cherrypy.log("Checking session: %s" % SESSION_KEY) # check if there is an active session # sessions are turned on so we just have to know if there is # something inside of cherrypy.session[SESSION_KEY]: session_token = cherrypy.session[SESSION_KEY] logger.debug("Session: %s", session_token) cherrypy.log("Session: %s" % session_token) # Not sure if I need to do this myself or what cherrypy.session.regenerate() cherrypy.request.login = cherrypy.session[SESSION_KEY] authenticated = True except KeyError: # If the session isn't set, it either was not existing or valid. # Now check if the request includes HTTP Authorization? authorization = cherrypy.request.headers.get('Authorization') if authorization: logger.debug("Got authorization header: %s", authorization) ah = httpauth.parseAuthorization(authorization) # Get module application from cherrypy request logger.debug("Requesting login for %s@%s...", ah['username'], cherrypy.request.remote.ip) cherrypy.log("Requesting login for %s@%s..." % (ah['username'], cherrypy.request.remote.ip)) token = app.backend_token(username=ah['username'], password=ah['password']) if token: cherrypy.session.regenerate() # This line of code is discussed in doc/sessions-and-auth.markdown cherrypy.session[SESSION_KEY] = token authenticated = True logger.debug("Authenticated with backend") cherrypy.log("Authenticated with backend") else: logger.warning("Failed attempt to log in with authorization header for %s..", cherrypy.request.remote.ip) cherrypy.session[SESSION_KEY] = '' else: logger.debug("No authorization header for %s.", cherrypy.request.remote.ip) cherrypy.session[SESSION_KEY] = '' except Exception as exp: # pylint: disable=bare-except cherrypy.log("Exception: %s" % exp) cherrypy.log("Back trace of the error:\n%s" % traceback.format_exc()) logger.warning("Client %s has no valid session and did not provided " "HTTP Authorization credentials.", cherrypy.request.remote.ip) cherrypy.log("Client %s has no valid session and did not provided " "HTTP Authorization credentials." % cherrypy.request.remote.ip) cherrypy.session[SESSION_KEY] = '' if authenticated: for condition in conditions: if not condition(): logger.warning("Authentication succeeded but authorization failed.") raise cherrypy.HTTPError("403 Forbidden") else: raise cherrypy.HTTPError("401 Unauthorized")
def testDigest(self): self.getPage("/digest/") self.assertStatus(401) value = None for k, v in self.headers: if k.lower() == "www-authenticate": if v.startswith("Digest"): value = v break if value is None: self._handlewebError("Digest authentification scheme was not found") value = value[7:] items = value.split(", ") tokens = {} for item in items: key, value = item.split("=") tokens[key.lower()] = value missing_msg = "%s is missing" bad_value_msg = "'%s' was expecting '%s' but found '%s'" nonce = None if "realm" not in tokens: self._handlewebError(missing_msg % "realm") elif tokens["realm"] != '"localhost"': self._handlewebError(bad_value_msg % ("realm", '"localhost"', tokens["realm"])) if "nonce" not in tokens: self._handlewebError(missing_msg % "nonce") else: nonce = tokens["nonce"].strip('"') if "algorithm" not in tokens: self._handlewebError(missing_msg % "algorithm") elif tokens["algorithm"] != '"MD5"': self._handlewebError(bad_value_msg % ("algorithm", '"MD5"', tokens["algorithm"])) if "qop" not in tokens: self._handlewebError(missing_msg % "qop") elif tokens["qop"] != '"auth"': self._handlewebError(bad_value_msg % ("qop", '"auth"', tokens["qop"])) # Test a wrong 'realm' value base_auth = ( "Digest " 'username="******", ' 'realm="wrong realm", ' 'nonce="%s", ' 'uri="/digest/", ' "algorithm=MD5, " 'response="%s", ' "qop=auth, " "nc=%s, " 'cnonce="1522e61005789929"' ) auth = base_auth % (nonce, "", "00000001") params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, "test") auth = base_auth % (nonce, response, "00000001") self.getPage("/digest/", [("Authorization", auth)]) self.assertStatus(401) # Test that must pass base_auth = ( "Digest " 'username="******", ' 'realm="localhost", ' 'nonce="%s", ' 'uri="/digest/", ' "algorithm=MD5, " 'response="%s", ' "qop=auth, " "nc=%s, " 'cnonce="1522e61005789929"' ) auth = base_auth % (nonce, "", "00000001") params = httpauth.parseAuthorization(auth) response = httpauth._computeDigestResponse(params, "test") auth = base_auth % (nonce, response, "00000001") self.getPage("/digest/", [("Authorization", auth)]) self.assertStatus("200 OK") self.assertBody("Hello test, you've been authorized.")