U
    ;g*                     @   s   d dl mZ d dlmZmZmZ d dlmZ ddlm	Z	 ddl
mZ deeed dd	d
Zdd Zeej e	dddZeedddZed dddZG dd dZG dd deZdS )    )defaultdict)IterableOptionalSet)x509   )ValProcState)PathValidationErrorPolicyTreeRoot)valid_policy_treedepthany_policy_uninhibitedreturnc                 C   s   d}t  }| D ]}|d j}|dkr*|}q|| |d }d}	d}
||d D ]2}|jdkrd|}
||jkrpqRd}	||||h qR|	s|
r|
|||h q|r|r||d D ],}|jD ] }||kr|||d |h qqt||d }|S )zO
    Internal method to update the policy tree during RFC 5280 validation.
    Npolicy_identifier
any_policypolicy_qualifiersFr   T)setnativeaddat_depthvalid_policyexpected_policy_set	add_child_prune_policy_tree)Zcertificate_policiesr   r   r   cert_any_policyZcert_policy_identifierspolicyr   r   Zpolicy_id_matchZparent_any_policynodeZexpected_policy_identifier r   E/tmp/pip-unpacked-wheel-hgp_x7fx/pyhanko_certvalidator/policy_tree.pyupdate_policy_tree
   sN    




    
r   c                 C   s0   |  |D ]}|js
|j| q
| js,d } | S N)walk_upchildrenparentremove_child)r   r   r   r   r   r   r   G   s    r   )mappings
proc_statec                 C   s`   t t}| D ]N}|d j}|d j}|| | |dksB|dkrtd|  d|q|S )z
    Internal function to process policy mapping extension values into
    a Python dictionary mapping issuer domain policies to the corresponding
    policies in the subject policy domain.
    issuer_domain_policysubject_domain_policyr   z(The path could not be validated because z/ contains a policy mapping for the "any policy")r   r   r   r   r	   Z
from_stateZdescribe_cert)r%   r&   
policy_mapmappingr'   r(   r   r   r   enumerate_policy_mappingsP   s    

r+   )r   policy_mapping_uninhibitedc           	      C   s   |   D ]\}}|rjd}d}||D ]&}|jdkr8|}|j|kr&d}||_q&|s|r|j||j| q||D ]}|j|krt|j| qtt||d }q|S )z
    Internal function to apply the policy mapping to the current policy tree
    in accordance with the algorithm in RFC 5280.
    FNr   Tr   )	itemsr   r   r   r#   r   qualifier_setr$   r   )	r)   r   r   r,   r'   Zsubject_domain_policiesZissuer_domain_policy_matchr   r   r   r   r   apply_policy_mappingn   s*    


r/   r   c           	         s   t |  fdd}t | }z\tdd || D }|j}|d k	sPt|j} | D ]}||||h q^|| W n t	k
r   Y nX t
|| d S )Nc                  3   s8   D ].} | j }|dks| kr&|V  q| j|  qd S )Nr   )r   r#   r$   )policy_nodeZ	policy_idacceptable_policiesZvalid_policy_node_setr   r   _filter_acceptable   s
    z7prune_unacceptable_policies.<locals>._filter_acceptablec                 s   s   | ]}|j d kr|V  qdS )r   N)r   ).0r1   r   r   r   	<genexpr>   s   
z.prune_unacceptable_policies.<locals>.<genexpr>r   )r   nodes_in_current_domainnextr   r#   AssertionErrorr.   r   r$   StopIterationr   )	path_lengthr   r3   r4   Zvalid_and_acceptableZfinal_any_policyZwildcard_parentZwildcard_qualsZacceptable_policyr   r2   r   prune_unacceptable_policies   s(    	
  r<   c                   @   s`   e Zd ZdZedd Zdd Zdd Zdd	 Ze	d
 dddZ
dd Ze	d
 dddZdS )r
   zH
    A generic policy tree node, used for the root node in the tree
    c                 C   s   t  }|||| |S )aq  
        Accepts values for a PolicyTreeNode that will be created at depth 0

        :param valid_policy:
            A unicode string of a policy name or OID

        :param qualifier_set:
            An instance of asn1crypto.x509.PolicyQualifierInfos

        :param expected_policy_set:
            A set of unicode strings containing policy names or OIDs
        )r
   r   )clsr   r.   r   rootr   r   r   init_policy_tree   s    zPolicyTreeRoot.init_policy_treec                 C   s   d | _ g | _d S r    )r#   r"   )selfr   r   r   __init__   s    zPolicyTreeRoot.__init__c                 C   s"   t |||}| |_| j| dS )ab  
        Creates a new PolicyTreeNode as a child of this node

        :param valid_policy:
            A unicode string of a policy name or OID

        :param qualifier_set:
            An instance of asn1crypto.x509.PolicyQualifierInfos

        :param expected_policy_set:
            A set of unicode strings containing policy names or OIDs
        N)PolicyTreeNoder#   r"   append)r@   r   r.   r   childr   r   r   r      s    zPolicyTreeRoot.add_childc                 C   s   | j | dS )zq
        Removes a child from this node

        :param child:
            An instance of PolicyTreeNode
        N)r"   remover@   rD   r   r   r   r$      s    zPolicyTreeRoot.remove_childrB   r0   c                 c   s>   t | jD ].}|dkr|V  q
||d D ]
}|V  q,q
dS )z
        Returns a generator yielding all nodes in the tree at a specific depth

        :param depth:
            An integer >= 0 of the depth of nodes to yield

        :return:
            A generator yielding PolicyTreeNode objects
        r   r   N)listr"   r   r@   r   rD   Z
grandchildr   r   r   r      s
    zPolicyTreeRoot.at_depthc                 c   s<   t | jD ],}|dkr0||d D ]
}|V  q$|V  q
dS )aW  
        Returns a generator yielding all nodes in the tree at a specific depth,
        or above. Yields nodes starting with leaves and traversing up to the
        root.

        :param depth:
            An integer >= 0 of the depth of nodes to walk up from

        :return:
            A generator yielding PolicyTreeNode objects
        r   r   N)rG   r"   r!   rH   r   r   r   r!     s
    zPolicyTreeRoot.walk_upc                 c   s.   | j D ]"}|V  |jdkr| E dH  qdS )zy
        Returns a generator yielding all nodes in the tree that are children
        of an ``any_policy`` node.
        r   N)r"   r   r7   rF   r   r   r   r7   !  s    

z&PolicyTreeRoot.nodes_in_current_domainN)__name__
__module____qualname____doc__classmethodr?   rA   r   r$   r   r   r!   r7   r   r   r   r   r
      s   

c                       s8   e Zd ZdZeejee d fddZdd Z	  Z
S )rB   zD
    A policy tree node that is used for all nodes but the root
    )r   r.   r   c                    s    t    || _|| _|| _dS )a$  
        :param valid_policy:
            A unicode string of a policy name or OID

        :param qualifier_set:
            An instance of asn1crypto.x509.PolicyQualifierInfos

        :param expected_policy_set:
            A set of unicode strings containing policy names or OIDs
        N)superrA   r   r.   r   )r@   r   r.   r   	__class__r   r   rA   2  s    
zPolicyTreeNode.__init__c                 c   s   | }|d k	r|V  |j }qd S r    )r#   )r@   r   r   r   r   path_to_rootH  s    zPolicyTreeNode.path_to_root)rI   rJ   rK   rL   strr   ZPolicyQualifierInfosr   rA   rQ   __classcell__r   r   rO   r   rB   -  s   rB   N)collectionsr   typingr   r   r   Z
asn1cryptor   _stater   errorsr	   intboolr   r   ZPolicyMappingr+   r/   r<   r
   rB   r   r   r   r   <module>   s(   =
  '2h