def authenticate(self, options): """ options can have the following * checkNonceFn - A callback to validate if a given nonce is valid * timestampSkewSec - Allows for clock skew in seconds. Defaults to 60. * localtimeOffsetMsec - Offset for client time. Defaults to 0. * options.payload - Required """ now = math.floor(time.time()) self._check_options(options) attributes = util.parse_authorization_header( self.req['headers']['authorization']) artifacts = self._prepare_artifacts(attributes) log.debug('artifacts=%s' % pprint.pformat(artifacts)) credentials = self.credentials_fn(attributes['id']) mac = self._calculate_mac(credentials, artifacts) if not util.compare(mac, attributes['mac']): log.info("Ours [" + mac + "] Theirs [" + attributes['mac'] + "]") raise BadMac if 'payload' in options: if 'hash' not in attributes: log.info("Missing required payload hash") raise BadRequest p_hash = hcrypto.calculate_payload_hash(options['payload'], credentials['algorithm'], self.req['contentType']) log.debug('payload=%s' % options['payload']) log.debug('algorithm=%s, contentType=%s' % (credentials['algorithm'], self.req['contentType'])) if not util.compare(p_hash, attributes['hash']): log.info("Bad payload hash") raise BadRequest if 'check_nonce_fn' in options: if not options['check_nonce_fn'](attributes['nonce'], attributes['ts']): raise BadRequest skew = int(options['timestampSkewSec']) if math.fabs(int(attributes['ts']) - now) > skew: log.info("Expired request") raise BadRequest return artifacts
def authenticate_bewit(self, options): """Authenticate bewit one time requests. Compatibility Note: HAWK exposes this as hawk.uri.authenticate :param options: A dict which may contain the 'hostHeaderName' and 'localtimeOffsetMsec' keys. """ if not valid_bewit_args(self.req, options): return False now = time.time() + int(options['localtime_offset_msec']) url = urlparse(self.req['url']) qs = parse_qs(url.query) if not 'bewit' in qs or len(qs['bewit']) != 1 or \ len(qs['bewit'][0]) == 0: log.info("No bewit query string parameter") return False bewit = hcrypto.explode_bewit(qs['bewit'][0]) original_url = normalize_url_without_bewit(self.req['url'], qs['bewit'][0]) if bewit['exp'] < now: raise BewitExpired options['ts'] = bewit['exp'] artifacts = { 'ts': bewit['exp'], 'nonce': '', 'method': 'GET', 'resource': original_url, 'host': self.req['host'], 'port': self.req['port'], 'ext': bewit['ext'] } credentials = self.credentials_fn(bewit['id']) mac = hcrypto.calculate_mac('bewit', credentials, artifacts, True) if not util.compare(mac, bewit['mac']): log.info("bewit " + mac + " didn't match " + bewit['mac']) raise BadRequest return True
def authenticate_bewit(self, options): """Authenticate bewit one time requests. Compatibility Note: HAWK exposes this as hawk.uri.authenticate :param options: A dict which may contain the 'hostHeaderName' and 'localtimeOffsetMsec' keys. """ if not valid_bewit_args(self.req, options): return False now = time.time() + int(options["localtime_offset_msec"]) url = urlparse(self.req["url"]) qs = parse_qs(url.query) if not "bewit" in qs or len(qs["bewit"]) != 1 or len(qs["bewit"][0]) == 0: log.info("No bewit query string parameter") return False bewit = hcrypto.explode_bewit(qs["bewit"][0]) original_url = normalize_url_without_bewit(self.req["url"], qs["bewit"][0]) if bewit["exp"] < now: raise BewitExpired options["ts"] = bewit["exp"] artifacts = { "ts": bewit["exp"], "nonce": "", "method": "GET", "resource": original_url, "host": self.req["host"], "port": self.req["port"], "ext": bewit["ext"], } credentials = self.credentials_fn(bewit["id"]) mac = hcrypto.calculate_mac("bewit", credentials, artifacts, True) if not util.compare(mac, bewit["mac"]): log.info("bewit " + mac + " didn't match " + bewit["mac"]) raise BadRequest return True
def authenticate(response, credentials, artifacts, options=None): """Validate server response. :param response: dictionary with server response :param artifacts: object recieved from header().artifacts :param options: { payload: optional payload received required: specifies if a Server-Authorization header is required. Defaults to 'false' } """ if not isinstance(response, dict) or 'headers' not in response: return False if 'content-type' not in response['headers']: log.warn("response lacked content-type") response['headers']['content-type'] = 'text/plain' if options is None: options = {} if 'required' not in options: options['required'] = False if 'www-authenticate' in response['headers']: www_auth_attrs = util.parse_authorization_header( response['headers']['www-authenticate'], ['ts', 'tsm', 'error']) if 'ts' in www_auth_attrs: ts_mac = hcrypto.calculate_ts_mac(www_auth_attrs['ts'], credentials) if not util.compare(ts_mac, www_auth_attrs['ts']): log.info(ts_mac + " didn't match " + www_auth_attrs['ts']) return False if 'server-authorization' not in response['headers'] and \ False == options['required']: return True if 'server-authorization' not in response['headers']: log.info("Unable to verify, no server-authorization header") return False s_auth_attrs = util.parse_authorization_header( response['headers']['server-authorization'], ['mac', 'ext', 'hash']) if 'ext' in s_auth_attrs: artifacts['ext'] = s_auth_attrs['ext'] else: artifacts['ext'] = '' artifacts['hash'] = s_auth_attrs['hash'] mac = hcrypto.calculate_mac('response', credentials, artifacts) if not util.compare(mac, s_auth_attrs['mac']): log.info("server mac mismatch " + mac + " != " + s_auth_attrs['mac']) return False if 'payload' not in options: return True if 'hash' not in s_auth_attrs: return False content_type = response['headers']['content-type'] p_mac = hcrypto.calculate_payload_hash(options['payload'], credentials['algorithm'], content_type) if not util.compare(p_mac, s_auth_attrs['hash']): log.info("p_mac " + p_mac + " != " + s_auth_attrs['hash']) return util.compare(p_mac, s_auth_attrs['hash'])
def authenticate(response, credentials, artifacts, options=None): """Validate server response. :param response: dictionary with server response :param artifacts: object recieved from header().artifacts :param options: { payload: optional payload received required: specifies if a Server-Authorization header is required. Defaults to 'false' } """ if not isinstance(response, dict) or 'headers' not in response: return False if 'content-type' not in response['headers']: print "WARNING response lacked content-type" response['headers']['content-type'] = 'text/plain' if options is None: options = {} if 'required' not in options: options['required'] = False if 'www-authenticate' in response['headers']: www_auth_attrs = util.parse_authorization_header( response['headers']['www-authenticate'], ['ts', 'tsm', 'error']) if 'ts' in www_auth_attrs: ts_mac = hcrypto.calculate_ts_mac(www_auth_attrs['ts'], credentials) if not util.compare(ts_mac, www_auth_attrs['ts']): print ts_mac + " didn't match " + www_auth_attrs['ts'] return False if 'server-authorization' not in response['headers'] and \ False == options['required']: return True if 'server-authorization' not in response['headers']: print "Unable to verify, no server-authorization header" return False s_auth_attrs = util.parse_authorization_header( response['headers']['server-authorization'], ['mac', 'ext', 'hash']) if 'ext' in s_auth_attrs: artifacts['ext'] = s_auth_attrs['ext'] else: artifacts['ext'] = '' artifacts['hash'] = s_auth_attrs['hash'] mac = hcrypto.calculate_mac('response', credentials, artifacts) if not util.compare(mac, s_auth_attrs['mac']): print "server mac mismatch " + mac + " != " + s_auth_attrs['mac'] return False if 'payload' in options: return True if 'hash' not in s_auth_attrs: return False content_type = response['headers']['content-type'] p_mac = hcrypto.calculate_payload_hash(options['payload'], credentials['algorithm'], content_type) if not util.compare(p_mac, s_auth_attrs['hash']): print "p_mac " + p_mac + " != " + s_auth_attrs['hash'] return util.compare(p_mac, s_auth_attrs['hash'])