o
    ¯b"  ã                   @   s¦   d 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mZm	Z	m
Z
 ddlmZ G dd„ de	ƒZe
eƒG dd	„ d	ƒƒZe
eƒG d
d„ dƒƒZe
eƒG dd„ dƒƒZdS )zF
Protocol agnostic implementations of SASL authentication mechanisms.
é    N)Úmd5)Ú	AttributeÚ	InterfaceÚimplementer)ÚnetworkStringc                   @   s$   e Zd ZedƒZdd„ Zdd„ ZdS )ÚISASLMechanismz#Common name for the SASL Mechanism.c                   C   ó   dS )z›
        Get the initial client response, if defined for this mechanism.

        @return: initial client response string.
        @rtype: C{str}.
        N© r	   r	   r	   úP/usr/lib/python3/dist-packages/twisted/words/protocols/jabber/sasl_mechanisms.pyÚgetInitialResponse   ó    z!ISASLMechanism.getInitialResponsec                 C   r   )zÁ
        Get the response to a server challenge.

        @param challenge: server challenge.
        @type challenge: C{str}.
        @return: client response.
        @rtype: C{str}.
        Nr	   )Ú	challenger	   r	   r
   ÚgetResponse!   r   zISASLMechanism.getResponseN)Ú__name__Ú
__module__Ú__qualname__r   Únamer   r   r	   r	   r	   r
   r      s    r   c                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )Ú	Anonymouszm
    Implements the ANONYMOUS SASL authentication mechanism.

    This mechanism is defined in RFC 2245.
    Ú	ANONYMOUSc                 C   ó   d S ©Nr	   ©Úselfr	   r	   r
   r   6   ó   zAnonymous.getInitialResponsec                 C   r   r   r	   ©r   r   r	   r	   r
   r   9   ó   zAnonymous.getResponseN)r   r   r   Ú__doc__r   r   r   r	   r	   r	   r
   r   ,   s
    r   c                   @   s,   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	S )
ÚPlainz‚
    Implements the PLAIN SASL authentication mechanism.

    The PLAIN SASL authentication mechanism is defined in RFC 2595.
    ÚPLAINc                 C   s"   |pd| _ |pd| _|pd| _dS )a  
        @param authzid: The authorization identity.
        @type authzid: L{unicode}

        @param authcid: The authentication identity.
        @type authcid: L{unicode}

        @param password: The plain-text password.
        @type password: L{unicode}
        Ú N)ÚauthzidÚauthcidÚpassword)r   r    r!   r"   r	   r	   r
   Ú__init__H   s   

zPlain.__init__c                 C   s,   | j  d¡d | j d¡ d | j d¡ S )Nzutf-8ó    )r    Úencoder!   r"   r   r	   r	   r
   r   X   s   
ÿ
þý
üÿzPlain.getInitialResponsec                 C   r   r   r	   r   r	   r	   r
   r   a   r   zPlain.getResponseN)r   r   r   r   r   r#   r   r   r	   r	   r	   r
   r   >   s    	r   c                   @   sT   e 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S )Ú	DigestMD5zŒ
    Implements the DIGEST-MD5 SASL authentication mechanism.

    The DIGEST-MD5 SASL authentication mechanism is defined in RFC 2831.
    z
DIGEST-MD5c                 C   sF   || _ || _|| _|› d|› �| _|dur!|  jd|› �7  _dS dS )aé  
        @param serv_type: An indication of what kind of server authentication
            is being attempted against.  For example, C{u"xmpp"}.
        @type serv_type: C{unicode}

        @param host: The authentication hostname.  Also known as the realm.
            This is used as a scope to help select the right credentials.
        @type host: C{unicode}

        @param serv_name: An additional identifier for the server.
        @type serv_name: C{unicode}

        @param username: The authentication username to use to respond to a
            challenge.
        @type username: C{unicode}

        @param password: The authentication password to use to respond to a
            challenge.
        @type password: C{unicode}
        ú/N)Úusernamer"   ÚdefaultRealmÚ
digest_uri)r   Ú	serv_typeÚhostÚ	serv_namer(   r"   r	   r	   r
   r#   p   s   ÿzDigestMD5.__init__c                 C   r   r   r	   r   r	   r	   r
   r   �   r   zDigestMD5.getInitialResponsec                 C   sb   |   |¡}d|v rdS |d  d¡}z|d }W n ty'   | j |¡}Y nw |  |||d ¡S )Ns   rspauthó    ó   charsetÚasciió   realmó   nonce)Ú_parseÚdecodeÚKeyErrorr)   r%   Ú_genResponse)r   r   Ú
directivesÚcharsetÚrealmr	   r	   r
   r   �   s   
ÿzDigestMD5.getResponsec                 C   s   |}i }d}d}|rl|  d|¡}|||…  ¡ }|d7 }|||d … dkrE|d7 }|  d|¡}|||… }	| d|¡d }|dkrDd}n!| d|¡}|dkrZ||d	…  ¡ }	d}n|||…  ¡ }	|d }|	||< |s
d
D ]}
|
|v r}||
  d¡||
< qn|S )zß
        Parses the server challenge.

        Splits the challenge into a dictionary of directives with values.

        @return: challenge directives and their values.
        @rtype: C{dict} of C{str} to C{str}.
        r   Tó   =é   ó   "ó   ,FéÿÿÿÿN)ó   qopó   cipher)ÚindexÚlstripÚfindÚrstripÚsplit)r   r   ÚsÚ	paramDictÚcurÚremainingParamsÚmiddler   ÚendÚvalueÚparamr	   r	   r
   r3   ¡   s:   	€é€zDigestMD5._parsec                 C   sL   g }|  ¡ D ]\}}|dv r|d | }n|d | }| |¡ qd |¡S )af  
        Create message string from directives.

        @param directives: dictionary of directives (names to their values).
                           For certain directives, extra quotes are added, as
                           needed.
        @type directives: C{dict} of C{str} to C{str}
        @return: message string.
        @rtype: C{str}.
        )ó   usernamer1   ó   cnoncer2   ó
   digest-uris   authzidr@   r:   r=   )ÚitemsÚappendÚjoin)r   r7   Údirective_listr   rL   Ú	directiver	   r	   r
   Ú_unparseÍ   s   	
zDigestMD5._unparsec                    sŽ   dd„ ‰ dd„ }‡ fdd„}	ˆ |d | d | ƒd | d | }
d| }||	|ˆ |
ƒƒ|d | d | d d	 d |ˆ |ƒƒ ƒƒ}|S )
zÒ
        Calculates response with given encoded parameters.

        @return: The I{response} field of a response to a Digest-MD5 challenge
            of the given parameters.
        @rtype: L{bytes}
        c                 S   s   t | ƒ ¡ S r   )r   Údigest)rF   r	   r	   r
   ÚHõ   s   z'DigestMD5._calculateResponse.<locals>.Hc                 S   s
   t  | ¡S r   )ÚbinasciiÚb2a_hex)Únr	   r	   r
   ÚHEXø   s   
z)DigestMD5._calculateResponse.<locals>.HEXc                    s   ˆ | d | ƒS )Nó   :r	   )ÚkrF   ©rX   r	   r
   ÚKDû   s   z(DigestMD5._calculateResponse.<locals>.KDr]   s   AUTHENTICATE:ó   authr	   )r   ÚcnonceÚncÚnoncer(   r"   r9   Úurir\   r`   Úa1Úa2Úresponser	   r_   r
   Ú_calculateResponseì   s   	(
*þÿzDigestMD5._calculateResponsec                 C   s�   z| j  |¡}| j |¡}| j |¡}W n ty   ‚ w tdd›ƒ}|  ¡ }d}	|  |||||||¡}
||||||	||
| d¡dœ	}|  |¡S )zÙ
        Generate response-value.

        Creates a response to a challenge according to section 2.1.2.1 of
        RFC 2831 using the C{charset}, C{realm} and C{nonce} directives
        from the challenge.
        r;   Ú08xra   r0   )	rN   r1   r2   rO   s   ncr?   rP   s   responser/   )	r(   r%   r"   r*   ÚUnicodeErrorr   Ú
_gen_nonceri   rV   )r   r8   r9   rd   r(   r"   r*   rc   rb   Úqoprh   r7   r	   r	   r
   r6   	  s0   þÿ÷
zDigestMD5._genResponsec                 C   s4   dt   ¡ t ¡ t ¡ f }t|ƒ}t|ƒ ¡  d¡S )Nz%f:%f:%dr0   )ÚrandomÚtimeÚosÚgetpidr   r   Ú	hexdigestr%   )r   ÚnonceStringÚ
nonceBytesr	   r	   r
   rl   0  s   zDigestMD5._gen_nonceN)r   r   r   r   r   r#   r   r   r3   rV   ri   r6   rl   r	   r	   r	   r
   r&   f   s    ,'r&   )r   rY   rp   rn   ro   Úhashlibr   Úzope.interfacer   r   r   Útwisted.python.compatr   r   r   r   r&   r	   r	   r	   r
   Ú<module>   s   '