a
    ‚4iŒ  ã                   @   sX   d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZG dd„ de	ƒZ
dS )é    )ÚOrderedDictNc                   @   sl   e Zd ZdZdddddddœZd	d
„ Zdd„ Zddd„Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚrndczRNDC protocol client libraryé   é¡   é¢   é£   é¤   é¥   )Úmd5Zsha1Zsha224Zsha256Zsha384Zsha512c                 C   sb   || _ | ¡ }| d¡r$|dd… }|| _tt|ƒ| _t |¡| _	t
 dd¡| _d| _|  ¡  dS )zþCreates a persistent connection to RNDC and logs in
        host - (ip, port) tuple
        algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512
               (with optional prefix 'hmac-')
        secret - HMAC secret, base64 encodedzhmac-é   Nr   i   )ÚhostÚlowerÚ
startswithÚalgoÚgetattrÚhashlibÚhlalgoÚbase64Ú	b64decodeÚsecretÚrandomZrandintÚserÚnonceÚ_rndc__connect_login)Úselfr   r   r   © r   ú*/usr/lib/python3/dist-packages/isc/rndc.pyÚ__init__'   s    
zrndc.__init__c                 C   s   t | j|dd ƒS )z’Call a RNDC command, all parsing is done on the server side
        cmd - a complete string with a command (eg 'reload zone example.com')
        ©ÚtypeÚ_data)ÚdictÚ_rndc__command)r   Úcmdr   r   r   Úcall8   s    z	rndc.callFc                 C   s  t ƒ }| ¡ D ]ô\}}|r$|dkr$q|t dt|ƒ¡| d¡ 7 }t|ƒtkrp|t ddt|ƒ¡| d¡ 7 }qt|ƒtkr˜|t ddt|ƒ¡| 7 }qt|ƒt krÀ|t ddt|ƒ¡| 7 }qt|ƒt	krò|  
|¡}|t ddt|ƒ¡| 7 }qtdt|ƒ ƒ‚q|S )NÚ_authÚBÚasciiz>BIé   é   z#Cannot serialize element of type %s)Ú	bytearrayÚitemsÚstructÚpackÚlenÚencoder   ÚstrÚbytesr   Ú_rndc__serialize_dictÚNotImplementedError)r   ÚdataÚignore_authÚrvÚkÚvZsdr   r   r   Z__serialize_dict>   s$    "

ÿzrndc.__serialize_dictc           	      O   s0  |  j d7  _ tt ¡ ƒ}t|i |¤Ž}tƒ }tƒ |d< tƒ |d< t| j ƒ|d d< t|ƒ|d d< t|d ƒ|d d< | jd ur| j|d d< ||d	< | j|d
d}t | j	|| j
¡ ¡ }t |¡}| jdkræt d|¡|d d< n"tt d| j| j |¡ƒ|d d< |  |¡}t dt|ƒd d¡| }|S )Nr(   r%   Ú_ctrlZ_serZ_timé<   Z_expÚ_noncer    T©r5   r
   Z22sÚhmd5ZB88sÚhshaú>IIé   )r   ÚintÚtimer   r0   r   r2   ÚhmacÚnewr   r   Údigestr   Z	b64encoder   r,   r-   r*   Ú_rndc__algosr.   )	r   ÚargsÚkwargsZnowr4   ÚdÚmsgÚhashÚbhashr   r   r   Z__prep_messageS   s.    




ÿ
zrndc.__prep_messagec                 C   s°   | j d ur |d d | j kr dS | jdkr8|d d }n|d d dd … }t|ƒtkrb| d	¡}|d
dt|ƒd   7 }t |¡}| j|dd}t	 
| j|| j¡ ¡ }||kS )Nr9   r;   Fr
   r%   r=   r>   r(   r'   ú=r@   Tr<   )r   r   r   r1   Údecoder.   r   r   r2   rC   rD   r   r   rE   )r   rJ   rL   Zremote_hashZmy_msgZmy_hashr   r   r   Z__verify_msgo   s    


zrndc.__verify_msgc           	      O   sÔ   | j |i |¤Ž}| j |¡}|t|ƒkr0tdƒ‚| j d¡}t|ƒdkrPtdƒ‚t d|¡\}}|dkrttd| ƒ‚|d8 }| j |tj	¡}t|ƒ|kr tdƒ‚t
|ƒtkr´t|ƒ}|  |¡}|  |¡sÐtd	ƒ‚|S )
NzCannot send the messageé   zCan't read response headerr?   r(   zWrong message version %dr@   zCan't read response datazAuthentication failure)Ú_rndc__prep_messageÚsocketÚsendr.   ÚIOErrorZrecvr,   Úunpackr3   ZMSG_WAITALLr   r0   r*   Ú_rndc__parse_messageÚ_rndc__verify_msg)	r   rG   rH   rJ   ZsentÚheaderZlengthÚversionr4   r   r   r   Z	__command~   s(    

zrndc.__commandc                 C   s2   t  | j¡| _ d | _| jdd}|d d | _d S )NZnullr   r9   r;   )rQ   Zcreate_connectionr   r   r"   )r   rJ   r   r   r   Z__connect_login›   s    zrndc.__connect_loginc                 C   sê   d}|| }|d7 }|||| …   d¡}||7 }|| }|d7 }t d|||d … ¡d }|d7 }|||| … }||7 }||d … }|dkrœ|||fS |dkrÚtƒ }	t|ƒdkrÐ|  |¡\}
}}||	|
< qª||	|fS td| ƒ‚d S )Nr   r(   r'   z>Ir@   r)   zUnknown element type %d)rN   r,   rT   r   r.   Ú_rndc__parse_elementr3   )r   ÚinputÚposZlabellenÚlabelr   Zdatalenr4   ÚrestrI   ZilabelÚvaluer   r   r   Z__parse_element¡   s*    


zrndc.__parse_elementc                 C   s4   t ƒ }d }t|ƒdkr0|  |¡\}}}|||< q
|S )Nr   )r   r.   rY   )r   rZ   r6   Zhdatar\   r^   r   r   r   Z__parse_message»   s    
zrndc.__parse_messageN)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rF   r   r$   r2   rP   rV   r"   r   rY   rU   r   r   r   r   r      s"   ú	
r   )Úcollectionsr   rB   r,   r   rC   r   r   rQ   Úobjectr   r   r   r   r   Ú<module>   s   