ó
Xé?_c           @   sû   d  Z  d Z d Z d d l Z d d l m Z d d l m Z m Z d d l	 Z	 d d l m
 Z
 d „  Z d	 Z d
 Z e e f Z d Z d „  Z d „  Z d „  Z d „  Z d d „ Z d „  Z d e f d „  ƒ  YZ d d e e d „ Z e d „ Z d S(   sz  An implementation of the server-side of HTTP Digest Access
Authentication, which is described in :rfc:`2617`.

Example usage, using the built-in get_ha1_dict_plain function which uses a dict
of plaintext passwords as the credentials store::

    userpassdict = {'alice' : '4x5istwelve'}
    get_ha1 = cherrypy.lib.auth_digest.get_ha1_dict_plain(userpassdict)
    digest_auth = {'tools.auth_digest.on': True,
                   'tools.auth_digest.realm': 'wonderland',
                   'tools.auth_digest.get_ha1': get_ha1,
                   'tools.auth_digest.key': 'a565c27146791cfb',
    }
    app_config = { '/' : digest_auth }
t   visteyas
   April 2009iÿÿÿÿN(   t   md5(   t   parse_http_listt   parse_keqv_list(   t   ntobc         C   s   t  t |  ƒ ƒ j ƒ  S(   N(   R   R   t	   hexdigest(   t   s(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   <lambda>   s    t   auths   auth-intt   MD5s   MD5-sessc         C   s   t  j |  d d ƒd  S(   Nt   contexts   TOOLS.AUTH_DIGEST(   t   cherrypyt   log(   t   msg(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   TRACE(   s    c            s   ‡  f d †  } | S(   sA  Returns a get_ha1 function which obtains a plaintext password from a
    dictionary of the form: {username : password}.

    If you want a simple dictionary-based authentication scheme, with plaintext
    passwords, use get_ha1_dict_plain(my_userpass_dict) as the value for the
    get_ha1 argument to digest_auth().
    c            s0   ˆ  j  | ƒ } | r, t d | |  | f ƒ Sd  S(   Ns   %s:%s:%s(   t   gett   md5_hext   None(   t   realmt   usernamet   password(   t   user_password_dict(    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   get_ha17   s    (    (   R   R   (    (   R   s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   get_ha1_dict_plain/   s    c            s   ‡  f d †  } | S(   sY  Returns a get_ha1 function which obtains a HA1 password hash from a
    dictionary of the form: {username : HA1}.

    If you want a dictionary-based authentication scheme, but with
    pre-computed HA1 hashes instead of plain-text passwords, use
    get_ha1_dict(my_userha1_dict) as the value for the get_ha1
    argument to digest_auth().
    c            s   ˆ  j  | ƒ S(   N(   R   (   R   R   (   t   user_ha1_dict(    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyR   I   s    (    (   R   R   (    (   R   s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   get_ha1_dict@   s    	c            s   ‡  f d †  } | S(   sm  Returns a get_ha1 function which obtains a HA1 password hash from a
    flat file with lines of the same format as that produced by the Apache
    htdigest utility. For example, for realm 'wonderland', username 'alice',
    and password '4x5istwelve', the htdigest line would be::

        alice:wonderland:3238cdfe91a8b2ed8e39646921a02d4c

    If you want to use an Apache htdigest file as the credentials store,
    then use get_ha1_file_htdigest(my_htdigest_file) as the value for the
    get_ha1 argument to digest_auth().  It is recommended that the filename
    argument be an absolute path, to avoid problems.
    c            st   d  } t ˆ  d ƒ } xN | D]F } | j ƒ  j d ƒ \ } } } | | k r | |  k r | } Pq q W| j ƒ  | S(   Nt   rt   :(   R   t   opent   rstript   splitt   close(   R   R   t   resultt   ft   linet   uR   t   ha1(   t   filename(    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyR   \   s    
(    (   R%   R   (    (   R%   s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   get_ha1_file_htdigestO   s    c         C   sN   | d k r! t t j ƒ  ƒ } n  t d | |  | f ƒ } d | | f } | S(   s†  Synthesize a nonce value which resists spoofing and can be checked
    for staleness. Returns a string suitable as the value for 'nonce' in
    the www-authenticate header.

    s
        A string related to the resource, such as the hostname of the server.

    key
        A secret string known only to the server.

    timestamp
        An integer seconds-since-the-epoch timestamp

    s   %s:%s:%ss   %s:%sN(   R   t   intt   timeR   (   R   t   keyt	   timestampt   ht   nonce(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   synthesize_noncej   s
    c         C   s
   t  |  ƒ S(   s   The hash function H(   R   (   R   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   H€   s    t   HttpDigestAuthorizationc           B   sY   e  Z d  Z d „  Z e d „ Z d „  Z d „  Z d d „ Z d d „ Z	 d d	 „ Z
 RS(
   s_   Class to parse a Digest Authorization header and perform re-calculation
    of the digest.
    c         C   s   d | S(   Ns   Digest Authorization header: %s(    (   t   selfR   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   errmsg‹   s    c   	      C   sR  | |  _  | |  _ | j d d ƒ \ } } | j ƒ  |  _ |  j d k rW t d ƒ ‚ n  | |  _ t | ƒ } t | ƒ } | j	 d ƒ |  _
 | j	 d ƒ |  _ | j	 d ƒ |  _ | j	 d ƒ |  _ | j	 d	 ƒ |  _ | j	 d
 ƒ |  _ | j	 d d ƒ j ƒ  |  _ | j	 d ƒ |  _ | j	 d ƒ |  _ | j	 d ƒ |  _ | j	 d ƒ |  _ |  j t k rut |  j d |  j ƒ ƒ ‚ n  |  j oŸ|  j
 oŸ|  j oŸ|  j oŸ|  j } | sÀt |  j d ƒ ƒ ‚ n  |  j r$|  j t k r÷t |  j d |  j ƒ ƒ ‚ n  |  j o|  j sNt |  j d ƒ ƒ ‚ qNn* |  j s6|  j rNt |  j d ƒ ƒ ‚ n  d  S(   Nt    i   t   digests$   Authorization scheme is not "Digest"R   R   R,   t   urit   methodt   responset	   algorithmR	   t   cnoncet   opaquet   qopt   ncs%   Unsupported value for algorithm: '%s's(   Not all required parameters are present.s   Unsupported value for qop: '%s's1   If qop is sent then cnonce and nc MUST be presents8   If qop is not sent, neither cnonce nor nc can be present(   t   http_methodt   debugR   t   lowert   schemet
   ValueErrort   auth_headerR   R   R   R   R   R,   R4   R5   R6   t   upperR7   R8   R9   R:   R;   t   valid_algorithmsR1   t
   valid_qops(	   R0   RA   R<   R=   R?   t   paramst   itemst   paramsdt   has_reqd(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   __init__Ž   sT    										c         C   s   d |  j  S(   Ns   authorization : %s(   RA   (   R0   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   __str__Ç   s    c         C   s…   ym |  j  j d d ƒ \ } } t | | | ƒ j d d ƒ \ } } | | k } |  j rh t d | ƒ n  | SWn t k
 r€ n Xt S(   sÃ  Validate the nonce.
        Returns True if nonce was generated by synthesize_nonce() and the
        timestamp is not spoofed, else returns False.

        s
            A string related to the resource, such as the hostname of
            the server.

        key
            A secret string known only to the server.

        Both s and key must be the same values which were used to synthesize
        the nonce we are trying to validate.
        R   i   s   validate_nonce: %s(   R,   R   R-   R=   R   R@   t   False(   R0   R   R)   R*   t   hashpartt   s_timestampt
   s_hashpartt   is_valid(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   validate_nonceÊ   s    !	iX  c         C   ss   yE |  j  j d d ƒ \ } } t | ƒ | t t j ƒ  ƒ k rD t SWn t k
 rX n X|  j ro t d ƒ n  t S(   s÷   Returns True if a validated nonce is stale. The nonce contains a
        timestamp in plaintext and also a secure hash of the timestamp.
        You should first validate the nonce to ensure the plaintext
        timestamp is not spoofed.
        R   i   s   nonce is stale(	   R,   R   R'   R(   RK   R@   R=   R   t   True(   R0   t   max_age_secondsR*   RL   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   is_nonce_staleå   s    "	t    c         C   s‡   |  j  d k s |  j  d k r7 d |  j |  j f } nF |  j  d k rh d |  j |  j t | ƒ f } n t |  j d ƒ ƒ ‚ t | ƒ S(   s:   Returns the H(A2) string. See :rfc:`2617` section 3.2.2.3.R   s   %s:%ss   auth-ints   %s:%s:%ss   Unrecognized value for qop!N(   R:   R   R<   R4   R.   R@   R1   (   R0   t   entity_bodyt   a2(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   HA2õ   s    	"c         C   sž   |  j  | ƒ } |  j r@ d |  j |  j |  j |  j | f } n d |  j | f } |  j d k r„ t d | |  j |  j f ƒ } n  t d | | f ƒ } | S(   sN  Calculates the Request-Digest. See :rfc:`2617` section 3.2.2.1.

        ha1
            The HA1 string obtained from the credentials store.

        entity_body
            If 'qop' is set to 'auth-int', then A2 includes a hash
            of the "entity body".  The entity body is the part of the
            message which follows the HTTP headers. See :rfc:`2617` section
            4.3.  This refers to the entity the user agent sent in the
            request which has the Authorization header. Typically GET
            requests don't have an entity, and POST requests do.

        s   %s:%s:%s:%s:%ss   %s:%ss   MD5-sesss   %s:%s:%s(   RW   R:   R,   R;   R8   R7   R.   (   R0   R$   RU   t   ha2t   reqR3   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   request_digest  s    	%"(   t   __name__t
   __module__t   __doc__R1   RK   RI   RJ   RP   RS   RW   RZ   (    (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyR/   …   s   	9		c         C   s‰   | t  k r t d | ƒ ‚ n  | t k r> t d | ƒ ‚ n  | d k r\ t |  | ƒ } n  d |  | | | f } | r… | d 7} n  | S(   s?   Constructs a WWW-Authenticate header for Digest authentication.s   Unsupported value for qop: '%s's%   Unsupported value for algorithm: '%s's7   Digest realm="%s", nonce="%s", algorithm="%s", qop="%s"s   , stale="true"N(   RD   R@   RC   R   R-   (   R   R)   R7   R,   R:   t   staleR   (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   www_authenticate1  s    c         C   s”  t  j j } | j j d ƒ } t } | d
 k	 rCy t | | j d | ƒ} Wn# t	 k
 rq t  j
 d d ƒ ‚ n X| r‹ t t | ƒ ƒ n  | j |  | ƒ rC| |  | j ƒ } | d
 k	 r@| j | d | j ƒ}	 |	 | j k r=| rõ t d ƒ n  | j d d ƒ } | s:| j | _ | r3t d	 | j ƒ n  d
 Sq=q@qCn  t |  | d | ƒ}
 | rkt |
 ƒ n  |
 t  j j j d <t  j
 d d ƒ ‚ d
 S(   s.  A CherryPy tool which hooks at before_handler to perform
    HTTP Digest Access Authentication, as specified in :rfc:`2617`.

    If the request has an 'authorization' header with a 'Digest' scheme,
    this tool authenticates the credentials supplied in that header.
    If the request has no 'authorization' header, or if it does but the
    scheme is not "Digest", or if authentication fails, the tool sends
    a 401 response with a 'WWW-Authenticate' Digest header.

    realm
        A string containing the authentication realm.

    get_ha1
        A callable which looks up a username in a credentials store
        and returns the HA1 string, which is defined in the RFC to be
        MD5(username : realm : password).  The function's signature is:
        ``get_ha1(realm, username)``
        where username is obtained from the request's 'authorization' header.
        If username is not found in the credentials store, get_ha1() returns
        None.

    key
        A secret string known only to the server, used in the synthesis
        of nonces.

    t   authorizationR=   i  s-   The Authorization header could not be parsed.RU   s   digest matches auth.responseRR   iX  s   authentication of %s successfulNR^   s   WWW-Authenticatei‘  s.   You are not authorized to access that resource(   R   t   servingt   requestt   headersR   RK   R   R/   R5   R@   t	   HTTPErrorR   t   strRP   R   RZ   t   bodyR6   RS   t   loginR_   (   R   R   R)   R=   Rb   RA   t   nonce_is_staleR   R$   R3   t   header(    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   digest_authB  s@    (   s   MD5s   MD5-sess(   R]   t
   __author__t   __date__R(   t   hashlibR   t   cherrypy._cpcompatR   R   R   R   R   t   qop_autht   qop_auth_intRD   RC   R   R   R   R&   R   R-   R.   t   objectR/   RK   R_   Rj   (    (    (    s   /local/mnt/workspace/CRMBuilds/Saipan.LA.2.0-00145-STD.PROD-1_20200821_083004/b/common/sectools/ext/cherrypy/lib/auth_digest.pyt   <module>   s,   						¬	