U
    ;g/                     @   s   d dl Z d dlmZ d dlmZmZmZmZmZ d dl	m
Z
mZ ddlmZ ddlmZmZmZmZ ddlmZmZ ed	d
G dd dZeeje
jf ZG dd dZdS )    N)	dataclass)	FrozenSetIterableIteratorOptionalUnion)cmsx509   )
AAControls)	AuthorityAuthorityWithCertCertTrustAnchorTrustAnchor)get_ac_extension_valueget_issuer_dnT)frozenc                   @   s&   e Zd ZU eed< eed< eed< dS )QualifiedPolicyZissuer_domain_policy_idZuser_domain_policy_idZ
qualifiersN)__name__
__module____qualname__str__annotations__	frozenset r   r   >/tmp/pip-unpacked-wheel-hgp_x7fx/pyhanko_certvalidator/path.pyr      s   
r   c                   @   s  e Zd ZU dZdZeee  ed< dZ	e
eej ee dddZee
ddd	Zed
d Zeee dddZee dddZeej dddZeejdddZee dddZedddZejedddZejdddZedddZd dd d!Zd"d# Zeee  dd$d%Z e!j"e#d&d'd(Z$ed)d* Z%d+d, Z&d-d. Z'e#e(ej d/d0d1Z)d2d3 Z*d4d5 Z+dS )6ValidationPathza
    Represents a path going towards an end-entity certificate or attribute
    certificate.
    N_qualified_policiestrust_anchorintermleafc                 C   s*   |r|st dt|| _|| _|| _d S )Nz-Leafless paths cannot have intermediate certs)
ValueErrorlist_interm_root_leaf)selfr   r    r!   r   r   r   __init__1   s
    
zValidationPath.__init__)returnc                 C   s   | j S N)r%   r'   r   r   r   r   =   s    zValidationPath.trust_anchorc                 C   s@   | j j}t|tr|jS | jr(| jd S t| jtjr<| jS dS )a  
        Returns the current beginning of the path - for a path to be complete,
        this certificate should be a trust root

        .. warning::
            This is a compatibility property, and will return the first non-root
            certificate if the trust root is not provisioned as a certificate.
            If you want the trust root itself (even when it doesn't have a
            certificate), use :attr:`trust_anchor`.

        :return:
            The first asn1crypto.x509.Certificate object in the path
        r   N)	r%   	authority
isinstancer   certificater$   r&   r	   Certificate)r'   rootr   r   r   firstA   s    

zValidationPath.firstc                 C   s.   | j dk	r| j S | js*t| jtr*| jjS dS )a<  
        Returns the current leaf certificate (AC or public-key).
        The trust root's certificate will be returned if there is one and
        there are no other certificates in the path.

        If the trust root is certificate-less and there are no certificates,
        the result will be ``None``.
        N)r&   r$   r-   r%   r   r.   r+   r   r   r   r!   X   s
    

zValidationPath.leafc                 C   s2   | j }t|tjr|jjS t|tjr*dS d S d S )Nz<Attribute certificate>)r!   r-   r	   r/   subjectZhuman_friendlyr   AttributeCertificateV2r'   r!   r   r   r   describe_leafi   s    zValidationPath.describe_leafc                 C   s   | j }t|tjr|S dS dS )z
        Returns the current leaf certificate if it is an X.509 public-key
        certificate, and ``None`` otherwise.
        :return:
        N)r!   r-   r	   r/   r4   r   r   r   get_ee_cert_safer   s    zValidationPath.get_ee_cert_safec                 C   s   |   }|r|S tdS )z
        Returns the last certificate in the path if it is an X.509 public-key
        certificate, and throws an error otherwise.

        :return:
            The last asn1crypto.x509.Certificate object in the path
        N)r6   LookupErrorr'   certr   r   r   last   s    	zValidationPath.lastc                 c   s$   | j jV  | jD ]}t|V  qdS )zU
        Iterate over all authorities in the path, including the trust root.
        N)r%   r,   r$   r   r8   r   r   r   iter_authorities   s    

zValidationPath.iter_authorities)r9   c                 C   s|   t |}t|tjr|j}nt|d}|r4|d jnd}|  D ].}|j|kr@|j	}|rf|rf||krfq@|  S q@t
ddS )aK  
        Return the issuer of the cert specified, as defined by this path

        :param cert:
            A certificate to get the issuer of

        :raises:
            LookupError - when the issuer of the certificate could not be found

        :return:
            An asn1crypto.x509.Certificate object of the issuer
        authority_key_identifierkey_identifierN6Unable to find the issuer of the certificate specified)r   r-   r	   r/   r<   r   Znativer;   namekey_idr7   )r'   r9   issuer_nameZakiZaki_extr,   Zkeyidr   r   r   find_issuing_authority   s    


z%ValidationPath.find_issuing_authority)r9   new_leafc                 C   s   t | jtr,| jjj|jkr,t| jg |dS | j}d}t|D ]\}}|j|jkr>|} q\q>|dkrltdt| j|d|d  |dS )a  
        Remove all certificates in the path after the cert specified and return
        them in a new path.

        Internal API.

        :param cert:
            An asn1crypto.x509.Certificate object to find

        :param new_leaf:
            A new leaf certificate to append.

        :raises:
            LookupError - when the certificate could not be found

        :return:
            The current ValidationPath object, for chaining
        r    r!   Nz(Unable to find the certificate specifiedr
   )	r-   r%   r   r.   Zissuer_serialr   r$   	enumerater7   )r'   r9   rC   certsZ
cert_indexindexentryr   r   r   truncate_to_and_append   s       z%ValidationPath.truncate_to_and_appendc                 C   s   d}| j j|r<|jdkr,t| jg ddS t| jg |dS | j}t|D ]>\}}|j|j	krJ|j
r|jr|j
|jkr|} qqJ|} qqJ|dkrtdt| j|d|d  |dS )a  
        Remove all certificates in the path after the issuer of the cert
        specified, as defined by this path, and append a new one.

        Internal API.

        :param cert:
            A new leaf certificate to append.

        :raises:
            LookupError - when the issuer of the certificate could not be found

        :return:
            The current ValidationPath object, for chaining
        NmayberD   r>   r
   )r!   )r   r,   Zis_potential_issuer_ofZself_signedr   r%   r$   rE   r2   issuerr=   r<   r7   )r'   r9   Zissuer_indexrF   rG   rH   r   r   r   truncate_to_issuer_and_append   s&    
z,ValidationPath.truncate_to_issuer_and_appendc                 C   s0   | j d d  }| jr || j t| j||dS )Nr   )r$   r&   appendr   r%   )r'   r9   Z	new_certsr   r   r   copy_and_append  s      zValidationPath.copy_and_appendc                 C   s<   t | jdkrt| jdd | jd  }}t| j||dS )z
        Drop the leaf cert from this path and return a new path with the
        last intermediate certificate set as the leaf.
        r   Nr   )lenr$   
IndexErrorr   r%   )r'   Z
new_intermrC   r   r   r   copy_and_drop_leaf  s      z!ValidationPath.copy_and_drop_leafc                 C   s
   || _ d S r*   r   )r'   policiesr   r   r   _set_qualified_policies!  s    z&ValidationPath._set_qualified_policiesc                 C   s   | j S r*   rS   r+   r   r   r   qualified_policies$  s    z!ValidationPath.qualified_policies)attr_idr)   c                    sB   dd | D }t dd |D }|s(dS t fdd|D S d S )Nc                 S   s   g | ]}t |qS r   )r   Zread_extension_value).0r9   r   r   r   
<listcomp>(  s    z3ValidationPath.aa_attr_in_scope.<locals>.<listcomp>c                 s   s   | ]}|d k	V  qd S r*   r   )rX   xr   r   r   	<genexpr>+  s     z2ValidationPath.aa_attr_in_scope.<locals>.<genexpr>Tc                 3   s    | ]}|d k	r|  V  qd S r*   )accept)rX   ZctrlrW   r   r   r[   5  s   )anyall)r'   rW   Zaa_controls_extensionsZaa_controls_usedr   r]   r   aa_attr_in_scope'  s    zValidationPath.aa_attr_in_scopec                 C   s   t | j| jrdnd S )Nr
   r   )rP   r$   r&   r+   r   r   r   pkix_len=  s    zValidationPath.pkix_lenc                 C   s
   d| j  S )Nr
   )ra   r+   r   r   r   __len__A  s    zValidationPath.__len__c                 C   s\   |dkr<t | jd }||kr.| jd k	r.| jS | j|d  S t| jtrP| jjS tdd S )Nr   r
   zRoot has no certificate)rP   r$   r&   r-   r%   r   r.   r7   )r'   keyZleaf_ixr   r   r   __getitem__E  s    zValidationPath.__getitem__)include_rootr)   c                 C   sN   | j j}|rt|tr|jfnd}| j}t|tjr:|fnd}t	|| j
|S )z
        Iterate over the certificates in the path.

        :param include_root:
            Include the root (if it is supplied as a certificate)
        :return:
            An iterator.
        r   )r%   r,   r-   r   r.   r&   r	   r/   	itertoolschainr$   )r'   re   r0   Z	from_rootr!   Z	from_leafr   r   r   
iter_certsT  s    	
zValidationPath.iter_certsc                 C   s   | j ddS )NT)re   )rh   r+   r   r   r   __iter__g  s    zValidationPath.__iter__c                 C   s2   t |tsdS | j|jko0| j|jko0| j|jkS )NF)r-   r   r   r$   r&   )r'   otherr   r   r   __eq__l  s    


zValidationPath.__eq__),r   r   r   __doc__r   r   r   r   r   Z_path_aa_controlsr   r   r	   r/   Leafr(   propertyr   r1   r!   r   r5   r6   r:   r   r;   rB   rI   rL   rN   rR   rU   rV   r   ZAttCertAttributeTypeboolr`   ra   rb   rd   r   rh   ri   rk   r   r   r   r   r   '   sB   

	 &0
r   )rf   dataclassesr   typingr   r   r   r   r   Z
asn1cryptor   r	   Z
asn1_typesr   r,   r   r   r   r   utilr   r   r   r/   r3   rm   r   r   r   r   r   <module>   s   