<s> __all__ = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> from u2flib_server . jsapi import MetadataObject <EOL> from u2flib_server . attestation . data import YUBICO <EOL> from u2flib_server . utils import verify_cert_signature <EOL> from u2flib_server . yubicommon . compat import string_types , text_type <EOL> import os <EOL> import json <EOL> from cryptography import x509 <EOL> from cryptography . exceptions import InvalidSignature <EOL> from cryptography . hazmat . backends import default_backend <EOL> from cryptography . x509 . oid import NameOID <EOL> class MetadataResolver ( object ) : <EOL> def __init__ ( self ) : <EOL> self . _identifiers = { } <EOL> self . _certs = { } <EOL> self . _metadata = { } <EOL> def add_metadata ( self , metadata ) : <EOL> metadata = MetadataObject . wrap ( metadata ) <EOL> if metadata . identifier in self . _identifiers : <EOL> existing = self . _identifiers [ metadata . identifier ] <EOL> if metadata . version <= existing . version : <EOL> return <EOL> else : <EOL> self . _identifiers [ metadata . identifier ] = metadata <EOL> self . _certs . clear ( ) <EOL> self . _metadata . clear ( ) <EOL> for metadata in self . _identifiers . values ( ) : <EOL> self . _index ( metadata ) <EOL> else : <EOL> self . _identifiers [ metadata . identifier ] = metadata <EOL> self . _index ( metadata ) <EOL> def _index ( self , metadata ) : <EOL> for cert_pem in metadata . trustedCertificates : <EOL> if isinstance ( cert_pem , text_type ) : <EOL> cert_pem = cert_pem . encode ( '<STR_LIT:ascii>' ) <EOL> cert = x509 . load_pem_x509_certificate ( cert_pem , default_backend ( ) ) <EOL> subject = cert . subject . get_attributes_for_oid ( NameOID . COMMON_NAME ) [ <NUM_LIT:0> ] . value <EOL> if subject not in self . _certs : <EOL> self . _certs [ subject ] = [ ] <EOL> self . _certs [ subject ] . append ( cert ) <EOL> self . _metadata [ cert ] = metadata <EOL> def _verify_cert ( self , cert , key ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> verify_cert_signature ( cert , key ) <EOL> return True <EOL> except InvalidSignature : <EOL> return False <EOL> def resolve ( self , cert ) : <EOL> issuer = cert . issuer . get_attributes_for_oid ( NameOID . COMMON_NAME ) [ <NUM_LIT:0> ] . value <EOL> for issuer in self . _certs . get ( issuer , [ ] ) : <EOL> if self . _verify_cert ( cert , issuer . public_key ( ) ) : <EOL> return self . _metadata [ issuer ] <EOL> return None <EOL> def _load_from_file ( fname ) : <EOL> with open ( fname , '<STR_LIT:r>' ) as f : <EOL> return json . load ( f ) <EOL> def _load_from_dir ( dname ) : <EOL> json_fnames = [ os . path . join ( dname , d ) for d in os . listdir ( dname ) <EOL> if d . endswith ( '<STR_LIT>' ) ] <EOL> return [ _load_from_file ( fname ) for fname in json_fnames ] <EOL> def _add_data ( resolver , data ) : <EOL> if isinstance ( data , list ) : <EOL> for d in data : <EOL> _add_data ( resolver , d ) <EOL> return <EOL> elif isinstance ( data , string_types ) : <EOL> if os . path . isdir ( data ) : <EOL> data = _load_from_dir ( data ) <EOL> elif os . path . isfile ( data ) : <EOL> data = _load_from_file ( data ) <EOL> return _add_data ( resolver , data ) <EOL> if data is not None : <EOL> resolver . add_metadata ( data ) <EOL> def create_resolver ( data = None ) : <EOL> resolver = MetadataResolver ( ) <EOL> if data is None : <EOL> data = YUBICO <EOL> _add_data ( resolver , data ) <EOL> return resolver </s>
