Beispiel #1
0
    def verify_chain(self, trusted_certs = None):
        # do the normal certificate verification stuff
        trusted_root = Certificate.verify_chain(self, trusted_certs)        

        if self.parent:
            # make sure the parent's hrn is a prefix of the child's hrn
            if not hrn_authfor_hrn(self.parent.get_hrn(), self.get_hrn()):
                raise GidParentHrn("This cert HRN %s isn't in the namespace for parent HRN %s" % (self.get_hrn(), self.parent.get_hrn()))

            # Parent must also be an authority (of some type) to sign a GID
            # There are multiple types of authority - accept them all here
            if not self.parent.get_type().find('authority') == 0:
                raise GidInvalidParentHrn("This cert %s's parent %s is not an authority (is a %s)" % (self.get_hrn(), self.parent.get_hrn(), self.parent.get_type()))

            # Then recurse up the chain - ensure the parent is a trusted
            # root or is in the namespace of a trusted root
            self.parent.verify_chain(trusted_certs)
        else:
            # make sure that the trusted root's hrn is a prefix of the child's
            trusted_gid = GID(string=trusted_root.save_to_string())
            trusted_type = trusted_gid.get_type()
            trusted_hrn = trusted_gid.get_hrn()
            #if trusted_type == 'authority':
            #    trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')]
            cur_hrn = self.get_hrn()
            if not hrn_authfor_hrn(trusted_hrn, cur_hrn):
                raise GidParentHrn("Trusted root with HRN %s isn't a namespace authority for this cert: %s" % (trusted_hrn, cur_hrn))

            # There are multiple types of authority - accept them all here
            if not trusted_type.find('authority') == 0:
                raise GidInvalidParentHrn("This cert %s's trusted root signer %s is not an authority (is a %s)" % (self.get_hrn(), trusted_hrn, trusted_type))

        return
Beispiel #2
0
    def verify_issuer(self, trusted_gids):
        root_cred = self.get_credential_list()[-1]
        root_target_gid = root_cred.get_gid_object()
        if root_cred.get_signature() is None:
            # malformed
            raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred has no signature" % (self.gidCaller.get_urn(), self.gidObject.get_urn()))

        root_cred_signer = root_cred.get_signature().get_issuer_gid()

        # Case 1:
        # Allow non authority to sign target and cred about target.
        #
        # Why do we need to allow non authorities to sign?
        # If in the target gid validation step we correctly
        # checked that the target is only signed by an authority,
        # then this is just a special case of case 3.
        # This short-circuit is the common case currently -
        # and cause GID validation doesn't check 'authority',
        # this allows users to generate valid slice credentials.
        if root_target_gid.is_signed_by_cert(root_cred_signer):
            # cred signer matches target signer, return success
            return

        # Case 2:
        # Allow someone to sign credential about themeselves. Used?
        # If not, remove this.
        #root_target_gid_str = root_target_gid.save_to_string()
        #root_cred_signer_str = root_cred_signer.save_to_string()
        #if root_target_gid_str == root_cred_signer_str:
        #    # cred signer is target, return success
        #    return

        # Case 3:

        # root_cred_signer is not the target_gid
        # So this is a different gid that we have not verified.
        # xmlsec1 verified the cert chain on this already, but
        # it hasn't verified that the gid meets the HRN namespace
        # requirements.
        # Below we'll ensure that it is an authority.
        # But we haven't verified that it is _signed by_ an authority
        # We also don't know if xmlsec1 requires that cert signers
        # are marked as CAs.

        # Note that if verify() gave us no trusted_gids then this
        # call will fail. So skip it if we have no trusted_gids
        if trusted_gids and len(trusted_gids) > 0:
            root_cred_signer.verify_chain(trusted_gids)
        else:
            pass
        # See if the signer is an authority over the domain of the target.
        # There are multiple types of authority - accept them all here
        # Maybe should be (hrn, type) = urn_to_hrn(root_cred_signer.get_urn())
        root_cred_signer_type = root_cred_signer.get_type()
        if (root_cred_signer_type.find('authority') == 0):
            #logger.debug('Cred signer is an authority')
            # signer is an authority, see if target is in authority's domain
            signerhrn = root_cred_signer.get_hrn()
            if hrn_authfor_hrn(signerhrn, root_target_gid.get_hrn()):
                return

        # We've required that the credential be signed by an authority
        # for that domain. Reasonable and probably correct.
        # A looser model would also allow the signer to be an authority
        # in my control framework - eg My CA or CH. Even if it is not
        # the CH that issued these, eg, user credentials.

        # Give up, credential does not pass issuer verification

        raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
Beispiel #3
0
def create_credential(caller_gid, object_gid, expiration, typename, issuer_keyfile, issuer_certfile, trusted_roots, delegatable=False):
    '''Create and Return a Credential object issued by given key/cert for the given caller
    and object GID objects, given life in seconds, and given type.
    Privileges are determined by type per sfa/trust/rights.py
    Privileges are delegatable if requested.'''
    # FIXME: Validate args: my gids, >0 life,
    # type of cred one I can issue
    # and readable key and cert files
    if caller_gid is None:
        raise ValueError("Missing Caller GID")
    if object_gid is None:
        raise ValueError("Missing Object GID")
    if expiration is None:
        raise ValueError("Missing expiration")
    naive_expiration = naiveUTC(expiration)
    duration = naive_expiration - datetime.datetime.utcnow()
    life_secs = duration.seconds + duration.days * 24 * 3600
    if life_secs < 1:
        raise ValueError("Credential expiration is in the past")
    if trusted_roots is None:
        raise ValueError("Missing list of trusted roots")

    if typename is None or typename.strip() == '':
        raise ValueError("Missing credential type")
    typename = typename.strip().lower()
    if typename not in ("user", "sa", "ma", "authority", "slice", "component"):
        raise ValueError("Unknown credential type %s" % typename)

    if not os.path.isfile(issuer_keyfile):
        raise ValueError("Cant read issuer key file %s" % issuer_keyfile)

    if not os.path.isfile(issuer_certfile):
        raise ValueError("Cant read issuer cert file %s" % issuer_certfile)

    issuer_gid = gid.GID(filename=issuer_certfile)
    
    if not (object_gid.get_urn() == issuer_gid.get_urn() or 
        (issuer_gid.get_type().find('authority') == 0 and
         hrn_authfor_hrn(issuer_gid.get_hrn(), object_gid.get_hrn()))):
        raise ValueError("Issuer not authorized to issue credential: Issuer=%s  Target=%s" % (issuer_gid.get_urn(), object_gid.get_urn()))
    


    ucred = cred.Credential()
    # FIXME: Validate the caller_gid and object_gid
    # are my user and slice
    # Do get_issuer and compare to the issuer cert?
    # Or do gid.is_signed_by_cert(issuer_certfile)?
    ucred.set_gid_caller(caller_gid)
    ucred.set_gid_object(object_gid)
    ucred.set_expiration(expiration)
    # Use sfa/trust/rights.py to figure out what privileges
    # the credential should have.
    # user means refresh, resolve, info
    # per the privilege_table that lets users do
    # remove, update, resolve, list, getcredential,
    # listslices, listnodes, getpolicy
    # Note that it does not allow manipulating slivers

    # And every right is delegatable if any are delegatable (default False)
    privileges = rights.determine_rights(typename, None)
    privileges.delegate_all_privileges(delegatable)
    ucred.set_privileges(privileges)
    ucred.encode()
    ucred.set_issuer_keys(issuer_keyfile, issuer_certfile)
    ucred.sign()
    
    try:
        ucred.verify(trusted_roots)
    except Exception, exc:
        raise Exception("Create Credential failed to verify new credential from trusted roots: %s" % exc)