
[XMc           @   s   d  Z  d d l m Z d d l m Z d d l 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 m Z d	   Z d
 e f d     YZ d e f d     YZ d S(   s[   
Tests for L{twisted.cred._digest} and the associated bits in
L{twisted.cred.credentials}.
i(   t   verifyObject(   t   TestCase(   t   md5t   sha1(   t   IPv4Address(   t   LoginFailed(   t   calcHA1t   calcHA2t   IUsernameDigestHash(   t   calcResponset   DigestCredentialFactoryc         C   s   |  j  d  j   S(   Nt   base64(   t   encodet   strip(   t   s(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt	   b64encode   s    t   FakeDigestCredentialFactoryc           B   s)   e  Z d  Z d   Z d   Z d   Z RS(   s\   
    A Fake Digest Credential Factory that generates a predictable
    nonce and opaque
    c         O   s&   t  t |   j | |   d |  _ d  S(   Nt   0(   t   superR   t   __init__t
   privateKey(   t   selft   argst   kwargs(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyR      s    c         C   s   d S(   s)   
        Generate a static nonce
        t   178288758716122392881254770685(    (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   _generateNonce   s    c         C   s   d S(   s&   
        Return a stable time
        i    (    (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   _getTime&   s    (   t   __name__t
   __module__t   __doc__R   R   R   (    (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyR      s   		t   DigestAuthTestsc           B   sv  e  Z d  Z d   Z d e d  Z d   Z d   Z d e d  Z d e d  Z	 d   Z
 d	   Z d
   Z d   Z d e d  Z d   Z d   Z d e d  Z d   Z d   Z e d  Z d   Z e d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z  d   Z! d   Z" d    Z# d!   Z$ d"   Z% d#   Z& d$   Z' d%   Z( RS(&   s   
    L{TestCase} mixin class which defines a number of tests for
    L{DigestCredentialFactory}.  Because this mixin defines C{setUp}, it
    must be inherited before L{TestCase}.
    c         C   sy   d |  _  d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ t d d	 d
  |  _ d |  _	 t
 |  j |  j  |  _ d S(   s>   
        Create a DigestCredentialFactory for testing
        t   foobart   bazquuxs
   test realmR   t    29fc54aa1641c6fa0e151419361c8f23t   auths   /write/t   TCPs   10.2.3.4iu  t   GETN(   t   usernamet   passwordt   realmt	   algorithmt   cnoncet   qopt   uriR   t   clientAddresst   methodR
   t   credentialFactory(   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   setUp4   s    								R   c         C   so   d } t  | |  j |  j |  j | |  j  } d |  j |  j |  j f } | |  j   } |  j | |  d S(   s   
        L{calcHA1} accepts the C{'md5'} algorithm and returns an MD5 hash of
        its parameters, excluding the nonce and cnonce.
        t	   abc123xyzs   %s:%s:%sN(   R   R%   R'   R&   R)   t	   hexdigestt   assertEqual(   R   t
   _algorithmt   _hasht   noncet   hashA1t   a1t   expected(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5HashA1E   s    c         C   s   d } t  d |  j |  j |  j | |  j  } d |  j |  j |  j f } t |  j   } d | | |  j f } t |  j   } |  j | |  d S(   s   
        L{calcHA1} accepts the C{'md5-sess'} algorithm and returns an MD5 hash
        of its parameters, including the nonce and cnonce.
        t	   xyz321abcs   md5-sesss   %s:%s:%sN(	   R   R%   R'   R&   R)   R   t   digestR1   R2   (   R   R5   R6   R7   t   ha1R8   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5SessionHashA1R   s    c         C   s   |  j  d t  d S(   s   
        L{calcHA1} accepts the C{'sha'} algorithm and returns a SHA hash of its
        parameters, excluding the nonce and cnonce.
        t   shaN(   R9   R   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_SHAHashA1a   s    c         C   sZ   d } t  | | |  j d d  } d | |  j f } | |  j   } |  j | |  d S(   s   
        L{calcHA2} accepts the C{'md5'} algorithm and returns an MD5 hash of
        its arguments, excluding the entity hash for QOP other than
        C{'auth-int'}.
        R$   R"   s   %s:%sN(   R   R+   t   NoneR1   R2   (   R   R3   R4   R-   t   hashA2t   a2R8   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5HashA2Authi   s
    c         C   sc   d } d } t  | | |  j d |  } d | |  j | f } | |  j   } |  j | |  d S(   s   
        L{calcHA2} accepts the C{'md5'} algorithm and returns an MD5 hash of
        its arguments, including the entity hash for QOP of C{'auth-int'}.
        R$   t	   foobarbazs   auth-ints   %s:%s:%sN(   R   R+   R1   R2   (   R   R3   R4   R-   t   hentityRA   RB   R8   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5HashA2AuthIntv   s    c         C   s   |  j  d  d S(   s   
        L{calcHA2} accepts the C{'md5-sess'} algorithm and QOP of C{'auth'} and
        returns the same value as it does for the C{'md5'} algorithm.
        s   md5-sessN(   RC   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5SessHashA2Auth   s    c         C   s   |  j  d  d S(   s   
        L{calcHA2} accepts the C{'md5-sess'} algorithm and QOP of C{'auth-int'}
        and returns the same value as it does for the C{'md5'} algorithm.
        s   md5-sessN(   RF   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5SessHashA2AuthInt   s    c         C   s   |  j  d t  d S(   s   
        L{calcHA2} accepts the C{'sha'} algorithm and returns a SHA hash of
        its arguments, excluding the entity hash for QOP other than
        C{'auth-int'}.
        R>   N(   RC   R   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_SHAHashA2Auth   s    c         C   s   |  j  d t  d S(   s   
        L{calcHA2} accepts the C{'sha'} algorithm and returns a SHA hash of
        its arguments, including the entity hash for QOP of C{'auth-int'}.
        R>   N(   RF   R   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_SHAHashA2AuthInt   s    c   	      C   si   d } d } d } d | | | f } | |  j    } t | | | | d d d  } |  j | |  d S(   s   
        L{calcResponse} accepts the C{'md5'} algorithm and returns an MD5 hash
        of its parameters, excluding the nonce count, client nonce, and QoP
        value if the nonce count and client nonce are C{None}
        t   abc123t   789xyzt   lmnopqs   %s:%s:%sN(   R1   R	   R@   R2   (	   R   R3   R4   R6   RA   R5   t   responseR8   R;   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5HashResponse   s    	c         C   s   |  j  d  d S(   s   
        L{calcResponse} accepts the C{'md5-sess'} algorithm and returns an MD5
        hash of its parameters, excluding the nonce count, client nonce, and
        QoP value if the nonce count and client nonce are C{None}
        s   md5-sessN(   RO   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5SessionHashResponse   s    c         C   s   |  j  d t  d S(   s   
        L{calcResponse} accepts the C{'sha'} algorithm and returns a SHA hash
        of its parameters, excluding the nonce count, client nonce, and QoP
        value if the nonce count and client nonce are C{None}
        R>   N(   RO   R   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_SHAHashResponse   s    c         C   s   d } d } d } d } d } d } d | | | | | | f }	 | |	  j    }
 t | | | | | | |  } |  j |
 |  d S(	   s   
        L{calcResponse} accepts the C{'md5'} algorithm and returns an MD5 hash
        of its parameters, including the nonce count, client nonce, and QoP
        value if they are specified.
        RK   RL   RM   t   00000004t	   abcxyz123R"   s   %s:%s:%s:%s:%s:%sN(   R1   R	   R2   (   R   R3   R4   R6   RA   R5   t
   nonceCountt   clientNonceR*   RN   R8   R;   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_MD5HashResponseExtra   s    c         C   s   |  j  d  d S(   s   
        L{calcResponse} accepts the C{'md5-sess'} algorithm and returns an MD5
        hash of its parameters, including the nonce count, client nonce, and
        QoP value if they are specified.
        s   md5-sessN(   RV   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt    test_MD5SessionHashResponseExtra   s    c         C   s   |  j  d t  d S(   s   
        L{calcResponse} accepts the C{'sha'} algorithm and returns a SHA hash
        of its parameters, including the nonce count, client nonce, and QoP
        value if they are specified.
        R>   N(   RV   R   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_SHAHashResponseExtra   s    c         K   s  d | k r |  j  | d <n  d | k r8 |  j | d <n  d | k rT |  j | d <n  d | k rp |  j | d <n  d | k r |  j | d <n  d | k r |  j | d <n  | r d } n d } d	 j g  | j   D]. \ } } | d k	 r d
 | | | | f ^ q  S(   s  
        Format all given keyword arguments and their values suitably for use as
        the value of an HTTP header.

        @types quotes: C{bool}
        @param quotes: A flag indicating whether to quote the values of each
            field in the response.

        @param **kw: Keywords and C{str} values which will be treated as field
            name/value pairs to include in the result.

        @rtype: C{str}
        @return: The given fields formatted for use as an HTTP header value.
        R%   R'   R(   R*   R)   R+   t   "t    s   , s	   %s=%s%s%sN(	   R%   R'   R(   R*   R)   R+   t   joint	   iteritemsR@   (   R   t   quotest   kwt   quotet   kt   v(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   formatResponse   s&    	c   	      C   s   | j  d  } | j  d  j   } | j  d  } t | |  j |  j |  j | |  j  } t | d |  j | d  } t
 | | | | | |  j |  } | S(   s@   
        Calculate the response for the given challenge
        R5   R(   R*   R$   N(   t   gett   lowerR   R%   R'   R&   R)   R   R+   R@   R	   (	   R   t	   challenget   ncountR5   t   algoR*   R<   t   ha2R8   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   getDigestResponse  s    $!c         C   s   |  j  j |  j j  } d } |  j d | d | d d |  j | |  d | d | d  } |  j  j | |  j |  j j  } |  j | j	 |  j
   |  j | j	 |  j
 d   d S(	   s   
        L{DigestCredentialFactory.decode} accepts a digest challenge response
        and parses it into an L{IUsernameHashedPassword} provider.
        t   00000001R]   R5   RN   t   nct   opaquet   wrongN(   R.   t   getChallengeR,   t   hostRb   Ri   t   decodeR-   t
   assertTruet   checkPasswordR&   t   assertFalse(   R   R]   Re   Rk   t   clientResponset   creds(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_response%  s    	
	c         C   s   |  j  t  d S(   s  
        L{DigestCredentialFactory.decode} accepts a digest challenge response
        which does not quote the values of its fields and parses it into an
        L{IUsernameHashedPassword} provider in the same way it would a
        response which included quoted field values.
        N(   Rv   t   False(   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_responseWithoutQuotes9  s    c         C   s   d |  _  |  j   d S(   ss   
        The case of the algorithm value in the response is ignored when
        checking the credentials.
        t   MD5N(   R(   Rv   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_caseInsensitiveAlgorithmC  s    	c         C   s   d |  _ |  j   d S(   sV   
        The algorithm defaults to MD5 if it is not supplied in the response.
        N(   R@   R(   Rv   (   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_md5DefaultAlgorithmL  s    	c      
   C   s   |  j  j d  } d } |  j d | d d |  j | |  d | d | d  } |  j  j | |  j d  } |  j | j |  j	   |  j
 | j |  j	 d   d S(   s   
        L{DigestCredentialFactory.decode} accepts a digest challenge response
        even if the client address it is passed is C{None}.
        Rj   R5   RN   Rk   Rl   Rm   N(   R.   Rn   R@   Rb   Ri   Rp   R-   Rq   Rr   R&   Rs   (   R   Re   Rk   Rt   Ru   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_responseWithoutClientIPT  s    	
c      
   C   sF  |  j  j |  j j  } d } |  j d | d d |  j | |  d | d | d  } |  j  j | |  j |  j j  } |  j | j	 |  j
   |  j | j	 |  j
 d   d } |  j d | d d |  j | |  d | d | d  } |  j  j | |  j |  j j  } |  j | j	 |  j
   |  j | j	 |  j
 d   d S(	   sm   
        L{DigestCredentialFactory.decode} handles multiple responses to a
        single challenge.
        Rj   R5   RN   Rk   Rl   Rm   t   00000002N(   R.   Rn   R,   Ro   Rb   Ri   Rp   R-   Rq   Rr   R&   Rs   (   R   Re   Rk   Rt   Ru   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_multiResponsef  s*    	
	
c      
   C   s   |  j  j |  j j  } d } |  j d | d d |  j | |  d | d | d  } |  j  j | d |  j j  } |  j | j |  j	   |  j | j |  j	 d   d S(	   s&  
        L{DigestCredentialFactory.decode} returns an L{IUsernameHashedPassword}
        provider which rejects a correct password for the given user if the
        challenge response request is made using a different HTTP method than
        was used to request the initial challenge.
        Rj   R5   RN   Rk   Rl   t   POSTRm   N(
   R.   Rn   R,   Ro   Rb   Ri   Rp   Rs   Rr   R&   (   R   Re   Rk   Rt   Ru   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_failsWithDifferentMethod  s    	
c         C   s   |  j  t |  j j |  j d d  |  j |  j j  } |  j	 t
 |  d  |  j  t |  j j |  j d d  |  j |  j j  } |  j	 t
 |  d  d S(   s   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} if the response
        has no username field or if the username field is empty.
        R%   s$   Invalid response, no username given.RZ   N(   t   assertRaisesR   R.   Rp   Rb   R@   R-   R,   Ro   R2   t   str(   R   t   e(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_noUsername  s    		c         C   sP   |  j  t |  j j |  j d d  |  j |  j j  } |  j t	 |  d  d S(   so   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} if the response
        has no nonce.
        Rl   RK   s!   Invalid response, no nonce given.N(
   R   R   R.   Rp   Rb   R-   R,   Ro   R2   R   (   R   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_noNonce  s    	c         C   sJ   |  j  t |  j j |  j   |  j |  j j  } |  j t	 |  d  d S(   sp   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} if the response
        has no opaque.
        s"   Invalid response, no opaque given.N(
   R   R   R.   Rp   Rb   R-   R,   Ro   R2   R   (   R   R   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_noOpaque  s    		c      
   C   s   |  j  j |  j j  } d } |  j d | d d |  j | |  d | d | d  } |  j  j | |  j |  j j  } |  j t	 t
 |   d |  j |  j |  j f } t |  } |  j | j | j     | j d  |  j | j | j     d S(	   s   
        L{DigestCredentialFactory.decode} returns an L{IUsernameDigestHash}
        provider which can verify a hash of the form 'username:realm:password'.
        Rj   R5   RN   Rk   Rl   s   %s:%s:%sRm   N(   R.   Rn   R,   Ro   Rb   Ri   Rp   R-   Rq   R    R   R%   R'   R&   R   t	   checkHashR1   t   updateRs   (   R   Re   Rk   Rt   Ru   t	   cleartextt   hash(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_checkHash  s    	
c         C   sZ  t  |  j |  j  } | j |  j j  } |  j t | j d | d |  j j  } |  j	 t
 |  d  d t d  } |  j t | j | | d |  j j  } |  j	 t
 |  d  |  j t | j d | d |  j j  } |  j	 t
 |  d  d t d | d |  j j f  } |  j t | j | | d |  j j  } |  j	 t
 |  d  d	 S(
   s   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} when the opaque
        value does not contain all the required parts.
        t	   badOpaqueR5   s&   Invalid response, invalid opaque values   foo-s   nonce,clientipRZ   s   %s,%s,foobars,   Invalid response, invalid opaque/time valuesN(   R   R(   R'   Rn   R,   Ro   R   R   t   _verifyOpaqueR2   R   R   (   R   R.   Re   t   excR   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_invalidOpaque  sH    		c         C   s   t  |  j |  j  } | j |  j j  } | j d |  j j  } |  j t | j	 | | d |  j j  } |  j
 t |  d  |  j t | j	 | d |  j j  } |  j
 t |  d  d S(   s   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} when the given
        nonce from the response does not match the nonce encoded in the opaque.
        t
   1234567890R5   s2   Invalid response, incompatible opaque/nonce valuesRZ   N(   R   R(   R'   Rn   R,   Ro   t   _generateOpaqueR   R   R   R2   R   (   R   R.   Re   t   badNonceOpaqueR   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_incompatibleNonce  s.    		c         C   s   t  |  j |  j  } | j |  j j  } d } |  j |  j j |  | j | d |  } |  j t	 | j
 | | d |  j j  d S(   s   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} when the
        request comes from a client IP other than what is encoded in the
        opaque.
        s   10.0.0.1R5   N(   R   R(   R'   Rn   R,   Ro   t   assertNotEqualR   R   R   R   (   R   R.   Re   t
   badAddressR   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_incompatibleClientIP6  s    c         C   s   t  |  j |  j  } | j |  j j  } d | d |  j j d f } t | | j  j   } t	 |  } d | | j
 d  f } |  j t | j | | d |  j j  d S(   s   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} when the given
        opaque is older than C{DigestCredentialFactory.CHALLENGE_LIFETIME_SECS}
        s   %s,%s,%sR5   s
   -137876876s   %s-%ss   
N(   R   R(   R'   Rn   R,   Ro   R   R   R1   R   R   R   R   R   (   R   R.   Re   t   keyR;   t   ekeyt   oldNonceOpaque(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_oldNonceN  s    	
	
c         C   s   t  |  j |  j  } | j |  j j  } d | d |  j j d f } t | d  j   } d | t |  f } |  j	 t
 | j | | d |  j j  d S(   s~   
        L{DigestCredentialFactory.decode} raises L{LoginFailed} when the opaque
        checksum fails verification.
        s   %s,%s,%sR5   R   s   this is not the right pkeys   %s-%sN(   R   R(   R'   Rn   R,   Ro   R   R1   R   R   R   R   (   R   R.   Re   R   R;   t   badChecksum(    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_mismatchedOpaqueChecksumg  s    	
	
c         C   sX   d	 d
 d f } xB | D]: \ } } } } |  j t t d | | | d d d | q Wd S(   s   
        L{calcHA1} raises L{TypeError} when any of the pszUsername, pszRealm,
        or pszPassword arguments are specified with the preHA1 keyword
        argument.
        t   userR'   R&   t   preHA1R   R5   R)   N(   s   users   realms   passwords   preHA1(   Ns   realmNs   preHA1(   NNs   passwords   preHA1(   R@   R   t	   TypeErrorR   (   R   t	   argumentst   pszUsernamet   pszRealmt   pszPasswordR   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_incompatibleCalcHA1Options  s    	c         C   s-   |  j  j d d d  } |  j d |  d S(   s   
        L{DigestCredentialFactory._generateOpaque} returns a value without
        newlines, regardless of the length of the nonce.
        s   long nonce i
   s   
N(   R.   R   R@   t   assertNotIn(   R   Rl   (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   test_noNewlineOpaque  s    	()   R   R   R   R/   R   R9   R=   R?   RC   RF   RG   RH   RI   RJ   RO   RP   RQ   RV   RW   RX   t   TrueRb   Ri   Rv   Rx   Rz   R{   R|   R~   R   R   R   R   R   R   R   R   R   R   R   R   (    (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyR   .   sJ   																&		
					 						1	!				N(   R   t   zope.interface.verifyR    t   twisted.trial.unittestR   t   twisted.python.hashlibR   R   t   twisted.internet.addressR   t   twisted.cred.errorR   t   twisted.cred.credentialsR   R   R   R	   R
   R   R   R   (    (    (    s@   /usr/lib/python2.7/dist-packages/twisted/test/test_digestauth.pyt   <module>   s   	