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
Example #2
0
    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
Example #4
0
    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
Example #5
0
    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'])
Example #7
0
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'])