def basic_auth(): auth = request.authorization username = current_app.config['DM_API_ADMIN_USERNAME'] password = current_app.config['DM_API_ADMIN_PASSWORD'] if username is None: return if auth and auth.type == 'basic' and \ streql.equals(auth.username, username) and streql.equals(auth.password, password): return return Response(status=401, headers={'WWW-Authenticate': 'Basic realm="DMP Admin"'})
def on_post(self, req, resp): token = req.headers.get('X-GITLAB-TOKEN') if not token or not equals(token, GITLAB_TOKEN): raise falcon.HTTPBadRequest('Yoyo', '') try: data = ujson.load(req.stream) except: raise falcon.HTTPBadRequest('Bad body', '') logger.debug('Got webhook request: %s', data) if data['object_kind'] != 'pipeline': resp.body = '["meh"]' return commit = data['commit'] attributes = data['object_attributes'] status = attributes['status'] logger.info('Processing pipeline event %s, status: %s, commit: %s, ' 'commit message:\n%s', attributes['id'], status, commit['id'], commit['message']) if status == 'success' or status == 'failed': # build finished, download as many artifacts as possible for build in data['builds']: logger.info('Processing build %s(%s), status: %s...', build['name'], build['id'], build['status']) if build['status'] != 'success': continue build_fetch_queue.put(build) resp.body = '["ok"]'
def decorated(*args, **kwargs): """Check the header.""" token = request.headers.get("x-ersa-auth-token", "") if streql.equals(token, app.config["ERSA_AUTH_TOKEN"]): return func(*args, **kwargs) else: return "", 401
def is_client_digest_valid(client_digest, api_key, window, method, path, body): text = '%s %s %s %s' % (window, method, path, body) HMAC = hmac.new(api_key, text, hashlib.sha512) digest = base64.urlsafe_b64encode(HMAC.digest()) if equals(client_digest, digest): return True return False
def render_POST(self, request): bootstrap_token = os.environ.get("BOOTSTRAP_TOKEN") data = json.loads(request.content.read()) if streql.equals(data["bootstrap_token"].encode("ascii"), bootstrap_token): # authenticated! pass
def verify_tag(ciphertext, key): """Verify the tag on a ciphertext.""" tag_start = len(ciphertext) - __TAG_LEN data = ciphertext[:tag_start] tag = ciphertext[tag_start:] actual_tag = new_tag(data, key) return streql.equals(actual_tag, tag)
def process_request(self, req, resp): # http basic auth if self.config['server'].get('enable_basic_auth'): hdr_auth = req.get_header('AUTHORIZATION') if not hdr_auth: raise falcon.HTTPUnauthorized('Access denied', 'No auth header', []) auth = re.sub('^Basic ', '', hdr_auth) usr, pwd = decodestring(auth).split(':') if not equals(self.basic_auth.get(usr, ''), pwd): logger.warning('basic auth failure: %s', usr) raise falcon.HTTPUnauthorized('Access denied', 'Basic auth failure', []) segments = req.path.strip('/').split('/') if segments[0] == 'api': if len(segments) >= 3: # twilio validation if segments[2] == 'twilio': sig = req.get_header('X_TWILIO_SIGNATURE') if sig is None: logger.warning("no twilio signature found!") raise falcon.HTTPUnauthorized('Access denied', 'No Twilio signature', []) uri = [ req.protocol, '://', req.get_header('HOST'), self.config['server'].get('lb_routing_path', ''), req.path ] if req.query_string: uri.append('?') uri.append(req.query_string) post_body = req.context['body'] expected_sigs = [ compute_signature(t, ''.join(uri), post_body) for t in self.twilio_auth_token ] if sig not in expected_sigs: logger.warning( 'twilio validation failure: %s not in possible sigs: %s', sig, expected_sigs) raise falcon.HTTPUnauthorized('Access denied', 'Twilio auth failure', []) return elif segments[2] == 'gmail' or segments[ 2] == 'gmail-oneclick' or segments[2] == 'slack': return elif len(segments) == 1: if segments[0] == 'health' or segments[0] == 'healthcheck': return elif segments[0] == self.config['gmail'].get('verification_code'): return raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed', [])
def verify_tag(self, data): pkt_data = data[:len(data)-SHA384_LEN] pkt_tag = data[len(data)-SHA384_LEN:] tag = HMAC.new(self.hmac_rxkey, msg=pkt_data, digestmod=SHA384).digest()[:SHA384_LEN] if NOSTREQL == True: return local_streql(pkt_tag, tag) else: return streql.equals(pkt_tag, tag)
def verify_tag(self, data): pkt_data = data[:len(data) - SHA384_LEN] pkt_tag = data[len(data) - SHA384_LEN:] tag = HMAC.new(self.hmac_rxkey, msg=pkt_data, digestmod=SHA384).digest()[:SHA384_LEN] if NOSTREQL == True: return local_streql(pkt_tag, tag) else: return streql.equals(pkt_tag, tag)
def testEqualStrings(self): self.assertTrue(equals(b('foo'), b('foo'))) self.assertTrue(equals(u('foo'), u('foo'))) self.assertTrue(equals(b('foo'), u('foo'))) self.assertTrue(equals(u('foo'), b('foo'))) self.assertTrue(equals('hello'*1000, 'hello'*1000)) if PYTHON3: self.assertTrue(equals(bytes('hello\xa0world', 'utf8'), 'hello\xa0world')) else: self.assertTrue(equals('hello\xc2\xa0world', 'hello\xc2\xa0world'.decode('utf8')))
def testWithEmptyStrings(self): self.assertTrue(equals(b(''), b(''))) self.assertFalse(equals(b('a'), b(''))) self.assertFalse(equals(b(''), b('a'))) self.assertTrue(equals(u(''), u(''))) self.assertFalse(equals(u('a'), u(''))) self.assertFalse(equals(u(''), u('a')))
def does_password_match(self, password): """Checks if the given password matches the given admin user. Agrs: password: The password to check an admin user by. Returns: True if the password matches the admin user and False otherwise. """ hashed = bcrypt.hashpw(password.encode('utf-8'), self.password.encode('utf-8')) # streql is a constant time string comparison tool to prevent timing-based # attacks. See here for more info: https://github.com/PeterScott/streql return streql.equals(hashed, self.password)
def verify_payload(signed_payload, client_secret): """ Given a signed payload (usually passed as parameter in a GET request to the app's load URL) and a client secret, authenticates the payload and returns the user's data, or False on fail. Uses constant-time str comparison to prevent vulnerability to timing attacks. """ encoded_json, encoded_hmac = signed_payload.split('.') dc_json = base64.b64decode(encoded_json) signature = base64.b64decode(encoded_hmac) expected_sig = hmac.new(client_secret.encode(), base64.b64decode(encoded_json), hashlib.sha256).hexdigest() authorised = streql.equals(signature, expected_sig) return json.loads(dc_json.decode()) if authorised else False
def xsrf_protect(): """Verifies that an xsrf token is included for all non-get requests Slight modification of http://flask.pocoo.org/snippets/3/ """ if ufo.app.config['TESTING']: return if flask.request.method == 'GET': return token = flask.session['_xsrf_token'] if not token or not streql.equals(token, flask.request.form.get('_xsrf_token')): flask.abort(403)
def check_api_key(self): """Checks whether the requester client has successfully proved its identity. By default this check consists on comparing the ``X-Backend-Key`` request header value with the key stablished in :py:attr:`api_key` when this object is created. """ try: key = self.request.headers["X-Backend-Key"] except KeyError: raise HTTPError(401, "Missing X-Backend-Key header") if not equals(key, self.api_key): raise HTTPError(401, "Invalid API key")
def validate_password(password, correct_hash): if isinstance(password, six.text_type): password = password.encode('utf-8') params = correct_hash.split(b':') if len(params) != 4: return False algorithm = params[0].decode('utf-8') iterations = int(params[1]) salt = params[2] hash = base64.b64decode(params[3]) computed_hash = hashlib.pbkdf2_hmac( algorithm, password, salt, iterations)[0:len(hash)] return streql.equals(hash, computed_hash)
def on_post(self, req, resp): token = req.headers.get('X-GITLAB-TOKEN') if not token or not equals(token, GITLAB_TOKEN): raise falcon.HTTPBadRequest('Yoyo', '') try: data = ujson.load(req.stream) except: raise falcon.HTTPBadRequest('Bad body', '') logger.debug('Got webhook request: %s', data) if data['object_kind'] != 'pipeline': resp.body = '["meh"]' return commit = data['commit'] attributes = data['object_attributes'] status = attributes['status'] logger.info( 'Processing pipeline event %s, status: %s, commit: %s, ' 'commit message:\n%s', attributes['id'], status, commit['id'], commit['message']) if status == 'success' or status == 'failed': # build finished, download as many artifacts as possible for build in data['builds']: if not build['name'].startswith('build_'): logger.debug( 'Skipping non-build job %s(%s), status: %s...', build['name'], build['id'], build['status']) continue logger.info('Processing build %s(%s), status: %s...', build['name'], build['id'], build['status']) if build['status'] != 'success': continue build_fetch_queue.put(build) resp.body = '["ok"]'
def process_request(self, req, resp): if self.debug: return # CORS Pre-flight if req.method == 'OPTIONS': resp.status = falcon.HTTP_204 return # http basic auth if self.config['server'].get('enable_basic_auth'): hdr_auth = req.get_header('AUTHORIZATION') if not hdr_auth: raise falcon.HTTPUnauthorized('Access denied', 'No auth header', []) auth = re.sub('^Basic ', '', hdr_auth) usr, pwd = decodestring(auth).split(':') if not equals(self.basic_auth.get(usr, ''), pwd): logger.warning('basic auth failure: %s', usr) raise falcon.HTTPUnauthorized('Access denied', 'Basic auth failure', []) segments = req.path.strip('/').split('/') if segments[0] == 'api': if len(segments) >= 3: # twilio validation if segments[2] == 'twilio': sig = req.get_header('X_TWILIO_SIGNATURE') if sig is None: logger.warning("no twilio signature found!") raise falcon.HTTPUnauthorized('Access denied', 'No Twilio signature', []) uri = [ req.protocol, '://', req.get_header('HOST'), self.config['server'].get('lb_routing_path', ''), req.path ] if req.query_string: uri.append('?') uri.append(req.query_string) post_body = req.context['body'] expected_sigs = [ compute_signature(t, ''.join(uri), post_body) for t in self.twilio_auth_token ] sig = sig.encode('utf8') if sig not in expected_sigs: logger.warning( 'twilio validation failure: %s not in possible sigs: %s', sig, expected_sigs) raise falcon.HTTPUnauthorized('Access denied', 'Twilio auth failure', []) return elif self.mobile and (segments[2] == 'mobile' or segments[2] == 'oncall'): # Only allow refresh tokens for /refresh, only access for all else table = 'refresh_token' if segments[ 3] == 'refresh' else 'access_token' key_query = '''SELECT `key`, `target`.`name` FROM `%s` JOIN `target` ON `user_id` = `target`.`id` WHERE `%s`.`id` = %%s AND `expiration` > %%s''' % (table, table) method = req.method auth = req.get_header('Authorization', required=True) items = urllib2.parse_http_list(auth) parts = urllib2.parse_keqv_list(items) if 'signature' not in parts or 'keyId' not in parts or 'timestamp' not in parts: raise falcon.HTTPUnauthorized( 'Authentication failure: invalid header') try: window = int(parts['timestamp']) time_diff = abs(time.time() - window) except ValueError: raise falcon.HTTPUnauthorized( 'Authentication failure: invalid header') client_digest = parts['signature'] key_id = parts['keyId'] body = req.context['body'].decode('utf8') path = req.env['PATH_INFO'] qs = req.env['QUERY_STRING'] if qs: path = path + '?' + qs text = '%s %s %s %s' % (window, method, path, body) text = text.encode('utf8') conn = db.connect() cursor = conn.cursor() cursor.execute(key_query, (key_id, time.time())) row = cursor.fetchone() conn.close() # make sure that there exists a row for the corresponding username if row is None: raise falcon.HTTPUnauthorized( 'Authentication failure: server') key = self.fernet.decrypt(str(row[0]).encode('utf8')) key = key req.context['user'] = row[1] HMAC = hmac.new(key, text, hashlib.sha512) digest = urlsafe_b64encode(HMAC.digest()) if hmac.compare_digest( client_digest.encode('utf8'), digest) and time_diff < self.time_window: return else: raise falcon.HTTPUnauthorized( 'Authentication failure: server') elif segments[2] == 'gmail' or segments[ 2] == 'gmail-oneclick' or segments[ 2] == 'slack' or segments[2] == 'ical': return elif len(segments) == 1: if segments[0] == 'health' or segments[0] == 'healthcheck': return elif segments[0] == self.config.get('gmail', {}).get('verification_code'): return elif segments[0] == 'saml': return raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed', [])
def valid_token(self, token): return equals(self.verification_token, token)
def testUnequalStrings(self): self.assertFalse(equals(b('foo'), b('bar'))) self.assertFalse(equals(u('foo'), u('bar'))) self.assertFalse(equals(b('hello, world!'), b('hello, world.'))) self.assertFalse(equals(b('aaa'), b('aa'))) self.assertFalse(equals(u('aaa'), u('aa')))
def sig_verify(self, plaintext, signature): ''' Verify a signature, by comparing it against a new signature of the same source data. ''' return streql.equals(signature.export(), self.sign(plaintext).export())
def verify_tag(self, data): pkt_data = data[:len(data)-SHA384_LEN] pkt_tag = data[len(data)-SHA384_LEN:] tag = HMAC.new(self.key, msg=pkt_data, digestmod=SHA384).digest()[:SHA384_LEN] return streql.equals(pkt_tag, tag)