U
    cc	`                     @   s   d Z ddlZ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mZmZ ddlmZ ed	d
\ZZZZZedd\ZZdd ed	d
D \ZZZZZdd eddD \ZZ G dd de!Z"G dd de"Z#G dd de!Z$G dd de!Z%dS )a  
This module provides GSS-API / SSPI Key Exchange as defined in :rfc:`4462`.

.. note:: Credential delegation is not supported in server mode.

.. note::
    `RFC 4462 Section 2.2
    <https://tools.ietf.org/html/rfc4462.html#section-2.2>`_ says we are not
    required to implement GSS-API error messages. Thus, in many methods within
    this module, if an error occurs an exception will be thrown and the
    connection will be terminated.

.. seealso:: :doc:`/api/ssh_gss`

.. versionadded:: 1.15
    N)sha1)DEBUGmax_byte	zero_byte)util)Message)byte_chr	byte_maskbyte_ord)SSHException   #   (   *   c                 C   s   g | ]}t |qS  r   .0cr   r   4/tmp/pip-unpacked-wheel-rglolp_m/paramiko/kex_gss.py
<listcomp>@   s     r   c                 C   s   g | ]}t |qS r   r   r   r   r   r   r   A   s    c                   @   s|   e Zd ZdZdZdZeded  Ze	d Z
dZdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )KexGSSGroup1z
    GSS-API / SSPI Authenticated Diffie-Hellman Key Exchange as defined in `RFC
    4462 Section 2 <https://tools.ietf.org/html/rfc4462.html#section-2>`_
    lE   8{3If?E yZ3V58noPe?a-tBLy3W[<p6m5P&aF!33*w& ARM;L}.c|&A@h\&&#-Dvd             z(gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==c                 C   s,   || _ | j j| _d | _d| _d| _d| _d S )Nr   )	transportkexgss_ctxtkexgssgss_hostxefselfr   r   r   r   __init__S   s    
zKexGSSGroup1.__init__c                 C   s   |    | jjr4t| j| j| j| _| jt	 dS t| j| j| j| _
| jj| _t }|t || jj| jd || j
 | j| | jtttt dS )zU
        Start the GSS-API / SSPI Authenticated Diffie-Hellman Key Exchange.
        Ntarget)_generate_xr   server_modepowGr    Pr"   _expect_packetMSG_KEXGSS_INITr!   r   r   add_bytec_MSG_KEXGSS_INIT
add_stringr   ssh_init_sec_context	add_mpint_send_messageMSG_KEXGSS_HOSTKEYMSG_KEXGSS_CONTINUEMSG_KEXGSS_COMPLETEMSG_KEXGSS_ERRORr$   mr   r   r   	start_kex[   s$    

zKexGSSGroup1.start_kexc                 C   s   | j jr|tkr| |S | j js4|tkr4| |S | j jrN|tkrN| |S | j jsh|tkrh| 	|S |t
krz| |S d}t||dS )
        Parse the next packet.

        :param ptype: The (string) type of the incoming packet
        :param `.Message` m: The paket content
        z.GSS KexGroup1 asked to handle packet type {:d}N)r   r)   r.   _parse_kexgss_initr5   _parse_kexgss_hostkeyr6   _parse_kexgss_continuer7   _parse_kexgss_completer8   _parse_kexgss_errorr   formatr$   ptyper:   msgr   r   r   
parse_nextu   s    




zKexGSSGroup1.parse_nextc                 C   sT   t d}t|d d|dd  }|dd }|| j| jfkr qDq t|| _dS )ap  
        generate an "x" (1 < x < q), where q is (p-1)/2.
        p is a 128-byte (1024-bit) number, where the first 64 bits are 1.
        therefore q can be approximated as a 2^1023.  we drop the subset of
        potential x where the first 63 bits are 1, because some of those will
        be larger than q (but this is a tiny tiny subset of potential x).
           r   r      Nr   )osurandomr	   b7fffffffffffffffb0000000000000000r   inflate_longr    )r$   x_bytesfirstr   r   r   r(      s    	
zKexGSSGroup1._generate_xc                 C   s8   |  }|| j_|  }| j|| | jtt dS )z
        Parse the SSH2_MSG_KEXGSS_HOSTKEY message (client mode).

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_HOSTKEY message
        N
get_stringr   host_keyZ_verify_keyr-   r6   r7   r$   r:   rR   sigr   r   r   r>      s
    z"KexGSSGroup1._parse_kexgss_hostkeyc                 C   sZ   | j jsV| }t }|t || jj| j	|d | j 
| | j ttt n dS )z
        Parse the SSH2_MSG_KEXGSS_CONTINUE message.

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_CONTINUE
            message
        r'   Z
recv_tokenNr   r)   rQ   r   r/   c_MSG_KEXGSS_CONTINUEr1   r   r2   r   send_messager-   r6   r7   r8   r$   r:   	srv_tokenr   r   r   r?      s"    
   z#KexGSSGroup1._parse_kexgss_continuec                 C   s<  | j jdkrt | j _| | _| jdk s:| j| jd krBtd| }| }d}|rb| }t	| j| j
| j}t }|| j j| j j| j j| j j || j j  || j || j || tt| }| j || |dk	r| jj| j|d | j|| n| j|| d| j _| j   dS )z
        Parse the SSH2_MSG_KEXGSS_COMPLETE message (client mode).

        :param `.Message` m: The content of the
            SSH2_MSG_KEXGSS_COMPLETE message
        NrH   Server kex "f" is out of rangerU   T)r   rR   NullHostKey	get_mpintr"   r,   r   rQ   get_booleanr*   r    r   addlocal_versionremote_versionlocal_kex_initremote_kex_initr1   __str__r3   r!   r   strdigest_set_K_Hr   r2   r   ssh_check_micgss_kex_used_activate_outboundr$   r:   	mic_tokenboolrZ   KhmHr   r   r   r@      sB    



 z#KexGSSGroup1._parse_kexgss_completec           	      C   s  |  }| | _| jdk s,| j| jd kr4tdt| j| j| j}t | j_	| jj	
 }t }|| jj| jj| jj| jj || || j || j || t|  }| j|| | j| j|}t }| jjrj| jj| jjdd}|t || j || |dk	r@| d || n
| d | j!| d| j_"| j#  n0|t$ || | j!| | j%t&t't( dS )z
        Parse the SSH2_MSG_KEXGSS_INIT message (server mode).

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_INIT message
        rH   Client kex "e" is out of rangeTZgss_kexNF))rQ   r]   r!   r,   r   r*   r    r\   r   rR   rd   r   r_   ra   r`   rc   rb   r1   r3   r"   r   asbytesrf   rg   r   ssh_accept_sec_contextr   _gss_srv_ctxt_statusssh_get_mic
session_idr/   c_MSG_KEXGSS_COMPLETEadd_booleanr4   ri   rj   rW   r-   r6   r7   r8   	r$   r:   Zclient_tokenrn   keyro   rp   rZ   rl   r   r   r   r=      s`    



 
 






  zKexGSSGroup1._parse_kexgss_initc                 C   s6   |  }|  }| }|  td|||dS )a  
        Parse the SSH2_MSG_KEXGSS_ERROR message (client mode).
        The server may send a GSS-API error message. if it does, we display
        the error by throwing an exception (client mode).

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_ERROR message
        :raise SSHException: Contains GSS-API major and minor status as well as
                             the error message and the language tag of the
                             message
        CGSS-API Error:
Major Status: {}
Minor Status: {}
Error Message: {}
Nget_intrQ   r   rB   r$   r:   Z
maj_statusZ
min_statuserr_msgr   r   r   rA   $  s      z KexGSSGroup1._parse_kexgss_errorN)__name__
__module____qualname____doc__r,   r+   r   r   rK   r   rL   NAMEr%   r;   rF   r(   r>   r?   r@   r=   rA   r   r   r   r   r   F   s   -8r   c                   @   s   e Zd ZdZdZdZdZdS )KexGSSGroup14z
    GSS-API / SSPI Authenticated Diffie-Hellman Group14 Key Exchange as defined
    in `RFC 4462 Section 2
    <https://tools.ietf.org/html/rfc4462.html#section-2>`_
    l   &UG9
tcb0]Q\-:$90.`U_b;YS7x]Ek`:xds!,w<G8qbdR_hddY6KpRT{UjK#Gt|L4S8 FYpw,(.> =HG2Cdc_.K?&j_c}z[\V_1M.D^/1v5I	jV&|/mVlR<6#{n4(EY91T:g8	H	Apcb4BBj~H r   z)gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==N)r   r   r   r   r,   r+   r   r   r   r   r   r   >  s   r   c                   @   sx   e Zd ZdZdZdZdZdZdd Zdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )	KexGSSGexz
    GSS-API / SSPI Authenticated Diffie-Hellman Group Exchange as defined in
    `RFC 4462 Section 2 <https://tools.ietf.org/html/rfc4462.html#section-2>`_
    z%gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==       i   c                 C   sD   || _ | j j| _d | _d | _d | _d | _d | _d | _d | _	d| _
d S )NF)r   r   r   r   pqgr    r!   r"   	old_styler#   r   r   r   r%   U  s    
zKexGSSGex.__init__c                 C   sr   | j jr| j t dS | j j| _t }|t || j	 || j
 || j | j | | j t dS )zV
        Start the GSS-API / SSPI Authenticated Diffie-Hellman Group Exchange
        N)r   r)   r-   MSG_KEXGSS_GROUPREQr   r   r/   c_MSG_KEXGSS_GROUPREQadd_intmin_bitspreferred_bitsmax_bitsr4   MSG_KEXGSS_GROUPr9   r   r   r   r;   a  s    

zKexGSSGex.start_kexc                 C   s   |t kr| |S |tkr$| |S |tkr6| |S |tkrH| |S |tkrZ| 	|S |t
krl| |S |tkr~| |S d}t||dS )r<   z'KexGex asked to handle packet type {:d}N)r   _parse_kexgss_groupreqr   _parse_kexgss_groupr.   _parse_kexgss_gex_initr5   r>   r6   r?   r7   r@   r8   rA   r   rB   rC   r   r   r   rF   t  s     






zKexGSSGex.parse_nextc                 C   s   | j d d }t|d}t|d }t|}d}|d@ sL|dK }|dL }q2t|}t|d ||dd   }t|d}|dkrL||k rLqqL|| _	d S )NrH   r   r      rG   )
r   r   Zdeflate_longr
   lenrI   rJ   r	   rM   r    )r$   r   ZqnormZqhbyteZ
byte_countZqmaskrN   r    r   r   r   r(     s    

zKexGSSGex._generate_xc                 C   s   |  }|  }|  }|| jkr(| j}|| jk r8| j}||krD|}||k rP|}|| _|| _|| _| j }|dkr|td| jtd	||| |
|||\| _| _t }|t || j || j | j| | jt dS )z
        Parse the SSH2_MSG_KEXGSS_GROUPREQ message (server mode).

        :param `.Message` m: The content of the
            SSH2_MSG_KEXGSS_GROUPREQ message
        Nz-Can't do server-side gex with no modulus packzPicking p ({} <= {} <= {} bits))r~   r   r   r   r   Z_get_modulus_packr   _logr   rB   Zget_modulusr   r   r   r/   c_MSG_KEXGSS_GROUPr3   r4   r-   r.   )r$   r:   ZminbitsZpreferredbitsZmaxbitspackr   r   r   r     s@    


  
z KexGSSGex._parse_kexgss_groupreqc                 C   s   |  | _|  | _t| j}|dk s0|dkr>td|| jt	d| | 
  t| j| j| j| _t }|t || jj| jd || j | j| | jtttt dS )z
        Parse the SSH2_MSG_KEXGSS_GROUP message (client mode).

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_GROUP message
        r   r   z<Server-generated gex p (don't ask) is out of range ({} bits)zGot server p ({} bits)r&   N)r]   r   r   r   
bit_lengthr   rB   r   r   r   r(   r*   r    r!   r   r/   r0   r1   r   r2   r   r3   r4   r-   r5   r6   r7   r8   )r$   r:   Zbitlenr   r   r   r     s4    

 
zKexGSSGex._parse_kexgss_groupc           	      C   s  |  }| | _| jdk s,| j| jd kr4td|   t| j| j| j| _	t| j| j| j}t
 | j_| jj }t }|| jj| jj| jj| jj| || j || j || j || j || j || j || j	 || t|  }| j|| | j| j|}t }| jj r| jj!| jj"dd}|#t$ || j	 |%| |dk	r|&d |%| n
|&d | j'| d| j_(| j)  n0|#t* |%| | j'| | j+t,t-t. dS )z
        Parse the SSH2_MSG_KEXGSS_INIT message (server mode).

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_INIT message
        rH   rq   Trr   NF)/rQ   r]   r!   r   r   r(   r*   r   r    r"   r\   r   rR   rd   r   r_   ra   r`   rc   rb   r   r   r   r   r3   r   rs   rf   rg   r   rt   r   ru   rv   rw   r/   rx   r1   ry   r4   ri   rj   rW   r-   r6   r7   r8   rz   r   r   r   r     sn    


 
 






  z KexGSSGex._parse_kexgss_gex_initc                 C   s8   |  }|| j_|  }| j|| | jtt dS )z
        Parse the SSH2_MSG_KEXGSS_HOSTKEY message (client mode).

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_HOSTKEY message
        NrP   rS   r   r   r   r>   +  s
    zKexGSSGex._parse_kexgss_hostkeyc                 C   sZ   | j jsV| }t }|t || jj| j	|d | j 
| | j ttt n dS )z
        Parse the SSH2_MSG_KEXGSS_CONTINUE message.

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_CONTINUE message
        rU   NrV   rY   r   r   r   r?   8  s"    
   z KexGSSGex._parse_kexgss_continuec                 C   s|  | j jdkrt | j _| | _| }| }d}|r@| }| jdk sZ| j| jd krbtdt	| j| j
| j}t }|| j j| j j| j j| j j| j j  | js|| j || j | js|| j || j || j || j || j || t|  }| j || |dk	rX| jj| j |d | j!|| n| j!|| d| j _"| j #  dS )z
        Parse the SSH2_MSG_KEXGSS_COMPLETE message (client mode).

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_COMPLETE message
        NrH   r[   rU   T)$r   rR   r\   r]   r"   rQ   r^   r   r   r*   r    r   r_   r`   ra   rb   rc   rd   r   r   r   r   r   r3   r   r!   r   rs   rf   rg   r   r2   r   rh   ri   rj   rk   r   r   r   r@   N  sP    




 z KexGSSGex._parse_kexgss_completec                 C   s6   |  }|  }| }|  td|||dS )a  
        Parse the SSH2_MSG_KEXGSS_ERROR message (client mode).
        The server may send a GSS-API error message. if it does, we display
        the error by throwing an exception (client mode).

        :param `Message` m:  The content of the SSH2_MSG_KEXGSS_ERROR message
        :raise SSHException: Contains GSS-API major and minor status as well as
                             the error message and the language tag of the
                             message
        r|   Nr}   r   r   r   r   rA     s      zKexGSSGex._parse_kexgss_errorN)r   r   r   r   r   r   r   r   r%   r;   rF   r(   r   r   r   r>   r?   r@   rA   r   r   r   r   r   J  s    ,!>2r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r\   z
    This class represents the Null Host Key for GSS-API Key Exchange as defined
    in `RFC 4462 Section 5
    <https://tools.ietf.org/html/rfc4462.html#section-5>`_
    c                 C   s
   d| _ d S )N r{   r$   r   r   r   r%     s    zNullHostKey.__init__c                 C   s   | j S Nr   r   r   r   r   rd     s    zNullHostKey.__str__c                 C   s   | j S r   r   r   r   r   r   get_name  s    zNullHostKey.get_nameN)r   r   r   r   r%   rd   r   r   r   r   r   r\     s   r\   )&r   rI   hashlibr   Zparamiko.commonr   r   r   Zparamikor   Zparamiko.messager   Zparamiko.py3compatr   r	   r
   Zparamiko.ssh_exceptionr   ranger.   r6   r7   r5   r8   r   r   r0   rW   rx   Zc_MSG_KEXGSS_HOSTKEYZc_MSG_KEXGSS_ERRORr   r   objectr   r   r   r\   r   r   r   r   <module>   s@   	
 y  R