???<!-- GIF89;a -->
123123123123
.....................................................................................................................................???<!-- GIF89;a -->
123123123123
.....................................................................................................................................3
ft`;,                 @   s   d dl mZ d dl mZ d dl mZ d dlmZ d dlZd dlZd dlZd dl	Z	d dl
mZ d dlZd dlZejdZdZG d	d
 d
ejjZdddZG dd deZG dd dZG dd dZG dd dZdd Zdd ZG dd dZdS )    )print_function)absolute_import)unicode_literals)EnumN)_dnf=   c               @   s   e Zd ZdZdd ZdS )DnssecErrorz-
    Exception used in the dnssec module
    c             C   s   dj | jd k	r| jndS )Nz<DnssecError, value='{}'>zNot specified)formatvalue)self r   /usr/lib/python3.6/dnssec.py__repr__-   s    zDnssecError.__repr__N)__name__
__module____qualname____doc__r   r   r   r   r   r	   )   s   r	   _openpgpkeyc             C   s~   | j d}t|dkr"d}t||d }|d }tj }|j|jd tj|j	 dd j
dj }|d | d | S )	z
    Implements RFC 7929, section 3
    https://tools.ietf.org/html/rfc7929#section-3
    :param email_address:
    :param tag:
    :return:
    @   z0Email address must contain exactly one '@' sign.r      zutf-8   .)splitlenr	   hashlibZsha256updateencodebase64Z	b16encodedigestdecodelower)Zemail_addresstagr   msgZlocalZdomainhashr    r   r   r   email2location2   s    	

r&   c               @   s(   e Zd ZdZdZdZdZdZdZdZ	dS )	Validityz
    Output of the verification algorithm.
    TODO: this type might be simplified in order to less reflect the underlying DNS layer.
    TODO: more specifically the variants from 3 to 5 should have more understandable names
    r   r            	   N)
r   r   r   r   VALIDREVOKEDPROVEN_NONEXISTENCERESULT_NOT_SECUREBOGUS_RESULTERRORr   r   r   r   r'   J   s   r'   c               @   s   e Zd ZdZdS )NoKeyz
    This class represents an absence of a key in the cache. It is an expression of non-existence
    using the Python's type system.
    N)r   r   r   r   r   r   r   r   r2   X   s   r2   c               @   s&   e Zd ZdZdddZedd ZdS )KeyInfozv
    Wrapper class for email and associated verification key, where both are represented in
    form of a string.
    Nc             C   s   || _ || _d S )N)emailkey)r   r4   r5   r   r   r   __init__e   s    zKeyInfo.__init__c       	      C   s   t jd| }|dkrt|jd}|jdjd}d}d}x6tdt|D ]$}|| dkr^|}|| dkrJ|}qJW d	j||d
 |d  j	d}t
||S )z
        Since dnf uses different format of the key than the one used in DNS RR, I need to convert
        the former one into the new one.
        z	<(.*@.*)>Nr   ascii
r   z$-----BEGIN PGP PUBLIC KEY BLOCK-----z"-----END PGP PUBLIC KEY BLOCK----- r   )researchr	   groupr!   r   ranger   joinr   r3   )	ZuseridZraw_keyZinput_emailr4   r5   startstopiZcat_keyr   r   r   from_rpm_key_objecti   s    
 zKeyInfo.from_rpm_key_object)NN)r   r   r   r   r6   staticmethodrB   r   r   r   r   r3   `   s   
r3   c               @   s8   e Zd ZdZi Zedd Zedd Zedd ZdS )	DNSSECKeyVerificationz
    The main class when it comes to verification itself. It wraps Unbound context and a cache with
    already obtained results.
    c             C   sZ   | |krt jd tjS | tkr0t jd tjS t jdj|  t jdj| tjS dS )zD
        Compare the key in case it was found in the cache.
        zCache hit, valid keyzCache hit, proven non-existencezKey in cache: {}zInput key   : {}N)loggerdebugr'   r,   r2   r.   r
   r-   )	key_unionZinput_key_stringr   r   r   
_cache_hit   s    

z DNSSECKeyVerification._cache_hitc       	      C   s  yddl }W n< tk
rH } z tdj|}tjj|W Y dd}~X nX |j }|jdddkrlt	j
d |jdddkrt	j
d	 |j dkrt	j
d
 |jddkrt	j
d |jt| jt|j\}}|dkrt	j
d tjS |jrt	j
d tjS |jst	j
d tjS |jr,t	j
d tjS |jsDt	j
d tjS |jj d }tj|}|| jkrntj S t	j
dj| t	j
dj| j tj!S dS )zz
        In case the key was not found in the cache, create an Unbound context and contact the DNS
        system
        r   NzLConfiguration option 'gpgkey_dns_verification' requires python3-unbound ({})z
verbosity:0z(Unbound context: Failed to set verbosityzqname-minimisation:yesz1Unbound context: Failed to set qname minimisationz+Unbound context: Failed to read resolv.confz/var/lib/unbound/root.keyz0Unbound context: Failed to add trust anchor filez%Communication with DNS servers failedzDNSSEC signatures are wrongz!Result is not secured with DNSSECz1Non-existence of this record was proven by DNSSECz"Unknown error in DNS communicationzKey from DNS: {}zInput key   : {})"unboundImportErrorr   r
   r   
exceptionsErrorZub_ctxZ
set_optionrE   rF   Z
resolvconfZadd_ta_fileZresolver&   r4   RR_TYPE_OPENPGPKEYZRR_CLASS_INr'   r1   Zbogusr0   Zsecurer/   Znxdomainr.   ZhavedatadataZas_raw_datar   Z	b64encoder5   r,   r-   )		input_keyrK   er$   ZctxZstatusresultrP   Zdns_data_b64r   r   r   _cache_miss   sN    









z!DNSSECKeyVerification._cache_missc             C   sz   t jdj| j tjj| j}|dk	r6tj|| jS tj	| }|t
jkrZ| jtj| j< n|t
jkrrt tj| j< |S dS )zI
        Public API. Use this method to verify a KeyInfo object.
        z(Running verification for key with id: {}N)rE   rF   r
   r4   rD   _cachegetrH   r5   rT   r'   r,   r.   r2   )rQ   rG   rS   r   r   r   verify   s    


zDNSSECKeyVerification.verifyN)	r   r   r   r   rU   rC   rH   rT   rW   r   r   r   r   rD      s
   9rD   c             C   s8   t d| j d }|tjkr(|t d S |t d S dS )zE
    Inform the user about key validity in a human readable way.
    zDNSSEC extension: Key for user  z	is valid.zhas unknown status.N)r   r4   r'   r,   )Zkivprefixr   r   r   nice_user_msg   s    
r[   c             C   s   t d|  S )z;
    Label any given message with DNSSEC extension tag
    zDNSSEC extension: )r   )mr   r   r   any_msg   s    r]   c               @   s(   e Zd ZdZedd Zedd ZdS )RpmImportedKeysaQ  
    Wrapper around keys, that are imported in the RPM database.

    The keys are stored in packages with name gpg-pubkey, where the version and
    release is different for each of them. The key content itself is stored as
    an ASCII armored string in the package description, so it needs to be parsed
    before it can be used.
    c        	      C   s   t jjj } | jdd}g }xl|D ]d}t jj|d}tjd|jd}t jj|d}|j	ddd }d	j
|}|t||jd
g7 }q"W |S )Nnamez
gpg-pubkeypackagerz	<(.*@.*)>r   descriptionr8   r(   r9   r7   )r   ZrpmZtransactionZTransactionWrapperZdbMatchZ	getheaderr:   r;   r<   r   r>   r3   r   )	Ztransaction_setZpackagesZreturn_listZpkgr`   r4   ra   Z	key_linesZkey_strr   r   r   _query_db_for_gpg_keys  s    

z&RpmImportedKeys._query_db_for_gpg_keysc              C   s  t j } tjttd x| D ]}ytj|}W n: tk
rl } ztj	dj
|j|j w W Y d d }~X nX |tjkrtjtdj
|j q |tjkrtjtdj
|j q |tjkrtjtdj
|j q |tjkrtjtdj
|j q tjtdj
|j q W d S )Nz1Testing already imported keys for their validity.z%DNSSEC extension error (email={}): {}zGPG Key {} is validz,GPG Key {} does not support DNS verificationzGPG Key {} could not be verified, because DNSSEC signatures are bogus. Possible causes: wrong configuration of the DNS server, MITM attackz=GPG Key {} has been revoked and should be removed immediatelyzGPG Key {} could not be tested)r^   rc   rE   infor]   r   rD   rW   r	   Zwarningr
   r4   r   r'   r,   rF   r.   r0   r-   )keysr5   rS   rR   r   r   r   check_imported_keys_validity  s,    







z,RpmImportedKeys.check_imported_keys_validityN)r   r   r   r   rC   rc   rf   r   r   r   r   r^      s   r^   )r   )Z
__future__r   r   r   enumr   r   r   Zloggingr:   Zdnf.i18nr   Zdnf.rpmr   Zdnf.exceptionsZ	getLoggerrE   rO   rM   rN   r	   r&   r'   r2   r3   rD   r[   r]   r^   r   r   r   r   <module>   s*   
	
#g