ó
L]c           @   s¢   d  Z  d d l Z d d l Z d d l m Z d d l m Z m Z m Z m	 Z	 d d l
 m Z d d l m Z d Z d	 Z d
 e f d „  ƒ  YZ d
 d g Z d S(   s*   Base implementation of 0MQ authentication.iÿÿÿÿN(   t   z85(   t   bytest   unicodet   bt   u(   t   _check_versioni   (   t   load_certificatest   *s   1.0t   Authenticatorc           B   s¹   e  Z d  Z d d d d „ Z d „  Z d „  Z d „  Z d „  Z d d d „ Z	 d d d	 „ Z
 d d d
 „ Z d „  Z d d d „ Z d „  Z d „  Z d „  Z d „  Z d d „ Z RS(   sÉ  Implementation of ZAP authentication for zmq connections.

    Note:

    - libzmq provides four levels of security: default NULL (which the Authenticator does
      not see), and authenticated NULL, PLAIN, CURVE, and GSSAPI, which the Authenticator can see.
    - until you add policies, all incoming NULL connections are allowed.
      (classic ZeroMQ behavior), and all PLAIN and CURVE connections are denied.
    - GSSAPI requires no configuration.
    s   utf-8c         C   s   t  d d ƒ | p t j j ƒ  |  _ | |  _ t |  _ i  |  _ d  |  _
 t ƒ  |  _ t ƒ  |  _ i  |  _ i  |  _ | p… t j d ƒ |  _ d  S(   Ni   i    t   securitys   zmq.auth(   i   i    (   R   t   zmqt   Contextt   instancet   contextt   encodingt   Falset	   allow_anyt   credentials_providerst   Nonet
   zap_sockett   sett	   whitelistt	   blacklistt	   passwordst   certst   loggingt	   getLoggert   log(   t   selfR   R   R   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   __init__   s    						c         C   sH   |  j  j t j ƒ |  _ d |  j _ |  j j d ƒ |  j j d ƒ d S(   s   Create and bind the ZAP socketi   s   inproc://zeromq.zap.01t   StartingN(	   R   t   socketR
   t   REPR   t   lingert   bindR   t   debug(   R   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   start0   s    c         C   s&   |  j  r |  j  j ƒ  n  d |  _  d S(   s   Close the ZAP socketN(   R   t   closeR   (   R   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   stop7   s    	c         G   sH   |  j  r t d ƒ ‚ n  |  j j d d j | ƒ ƒ |  j j | ƒ d S(   sa  Allow (whitelist) IP address(es).
        
        Connections from addresses not in the whitelist will be rejected.
        
        - For NULL, all clients from this address will be accepted.
        - For real auth setups, they will be allowed to continue with authentication.
        
        whitelist is mutually exclusive with blacklist.
        s-   Only use a whitelist or a blacklist, not boths   Allowing %st   ,N(   R   t
   ValueErrorR   R#   t   joinR   t   update(   R   t	   addresses(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   allow=   s    
	c         G   sH   |  j  r t d ƒ ‚ n  |  j j d d j | ƒ ƒ |  j j | ƒ d S(   sË   Deny (blacklist) IP address(es).
        
        Addresses not in the blacklist will be allowed to continue with authentication.
        
        Blacklist is mutually exclusive with whitelist.
        s-   Only use a whitelist or a blacklist, not boths
   Denying %sR'   N(   R   R(   R   R#   R)   R   R*   (   R   R+   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   denyL   s    	R   c         C   s-   | r | |  j  | <n  |  j j d | ƒ d S(   sý   Configure PLAIN authentication for a given domain.
        
        PLAIN authentication uses a plain-text password file.
        To cover all domains, use "*".
        You can modify the password file at any time; it is reloaded automatically.
        s   Configure plain: %sN(   R   R   R#   (   R   t   domainR   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   configure_plainX   s    c         C   s~   |  j  j d | | ƒ | t k r. t |  _ nL t |  _ y t | ƒ |  j | <Wn) t k
 ry } |  j  j	 d | | ƒ n Xd S(   s+  Configure CURVE authentication for a given domain.
        
        CURVE authentication uses a directory that holds all public client certificates,
        i.e. their public keys.
        
        To cover all domains, use "*".
        
        You can add and remove certificates in that directory at any time. configure_curve must be called 
        every time certificates are added or removed, in order to update the Authenticator's state 
        
        To allow all client keys without checking, specify CURVE_ALLOW_ANY for the location.
        s   Configure curve: %s[%s]s&   Failed to load CURVE certs from %s: %sN(
   R   R#   t   CURVE_ALLOW_ANYt   TrueR   R   R   R   t	   Exceptiont   error(   R   R.   t   locationt   e(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   configure_curvec   s    	c         C   s<   t  |  _ | d k	 r% | |  j | <n |  j j d | ƒ d S(   s  Configure CURVE authentication for a given domain.

        CURVE authentication using a callback function validating
        the client public key according to a custom mechanism, e.g. checking the
        key against records in a db. credentials_provider is an object of a class which
        implements a callback method accepting two parameters (domain and key), e.g.::

            class CredentialsProvider(object):

                def __init__(self):
                    ...e.g. db connection

                def callback(self, domain, key):
                    valid = ...lookup key and/or domain in db
                    if valid:
                        logging.info('Autorizing: {0}, {1}'.format(domain, key))
                        return True
                    else:
                        logging.warning('NOT Autorizing: {0}, {1}'.format(domain, key))
                        return False

        To cover all domains, use "*".

        To allow all client keys without checking, specify CURVE_ALLOW_ANY for the location.
        s0   None credentials_provider provided for domain:%sN(   R   R   R   R   R   R3   (   R   R.   t   credentials_provider(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   configure_curve_callback|   s    	c         C   s   t  j | ƒ j d ƒ S(   s  Return the User-Id corresponding to a CURVE client's public key
        
        Default implementation uses the z85-encoding of the public key.
        
        Override to define a custom mapping of public key : user-id
        
        This is only called on successful authentication.
        
        Parameters
        ----------
        client_public_key: bytes
            The client public key used for the given message
        
        Returns
        -------
        user_id: unicode
            The user ID as text
        t   ascii(   R    t   encodet   decode(   R   t   client_public_key(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   curve_user_idž   s    c         C   s   d S(   s†   Configure GSSAPI authentication
        
        Currently this is a no-op because there is nothing to configure with GSSAPI.
        N(    (   R   R.   R4   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   configure_gssapi³   s    c         C   sÌ  t  | ƒ d k  re |  j j d | ƒ t  | ƒ d k  rJ |  j j d ƒ n |  j | d d d ƒ d S| d  \ } } } } } } | d } t | |  j d	 ƒ } t | |  j d	 ƒ } | t k rë |  j j d
 | ƒ |  j | d d ƒ d S|  j j d | | | | | | ƒ t }	 t }
 d } |  j	 ru| |  j	 k rSt
 }	 |  j j d | ƒ qËt
 }
 d } |  j j d | ƒ nV |  j rË| |  j k r¯t
 }
 d } |  j j d | ƒ qËt
 }	 |  j j d | ƒ n  t d ƒ } |
 s–| d k r	|	 r	|  j j d ƒ t
 }	 q–| d k rt  | ƒ d k rQ|  j j d | ƒ |  j | d d ƒ d Sg  | D] } t | |  j d	 ƒ ^ qX\ } } |  j | | | ƒ \ }	 } q–| d k r"t  | ƒ d k rå|  j j d | ƒ |  j | d d ƒ d S| d } |  j | | ƒ \ }	 } |	 r“|  j | ƒ } q“q–| d k r–t  | ƒ d k rj|  j j d | ƒ |  j | d d ƒ d S| d } } |  j | | ƒ \ }	 } q–n  |	 rµ|  j | d d  | ƒ n |  j | d | ƒ d S(!   s   Perform ZAP authenticationi   s*   Invalid ZAP message, not enough frames: %ri   s   Not enough information to replyi   t   400s   Not enough framesNt   replaces   Invalid ZAP version: %rs   Invalid versionsQ   version: %r, request_id: %r, domain: %r, address: %r, identity: %r, mechanism: %rs	   NO ACCESSs   PASSED (whitelist) address=%ss   Address not in whitelists$   DENIED (not in whitelist) address=%ss   Address is blacklisteds   DENIED (blacklist) address=%ss$   PASSED (not in blacklist) address=%st	   anonymoust   NULLs   ALLOWED (NULL)t   PLAINs   Invalid PLAIN credentials: %rs   Invalid credentialst   CURVEs   Invalid CURVE credentials: %ri    t   GSSAPIs   Invalid GSSAPI credentials: %rt   200t   OK(   t   lenR   R3   t   _send_zap_replyR   R   t   VERSIONR#   R   R   R1   R   t   _authenticate_plaint   _authenticate_curveR=   t   _authenticate_gssapi(   R   t   msgt   versiont
   request_idR.   t   addresst   identityt	   mechanismt   credentialst   allowedt   deniedt   reasont   usernamet   ct   passwordt   keyt	   principal(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   handle_zap_messageº   s‚    
				.
c         C   sÙ   t  } d } |  j r¶ | s$ d } n  | |  j k rx | |  j | k ro | |  j | | k rf t } qu d } q~ d } n d } | r  |  j j d | | | ƒ qÏ |  j j d | ƒ n d } |  j j d	 | ƒ | | f S(
   s   PLAIN ZAP authenticationt    R   s   Invalid passwords   Invalid usernames   Invalid domains1   ALLOWED (PLAIN) domain=%s username=%s password=%ss	   DENIED %ss   No passwords defineds   DENIED (PLAIN) %s(   R   R   R1   R   R#   (   R   R.   RX   RZ   RU   RW   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyRK     s&    					c         C   sk  t  } d } |  j r4 t } d } |  j j d ƒ n-|  j i  k rÕ | sR d } n  | |  j k rÌ t j | ƒ } |  j | j | | ƒ r˜ t } d } n d } | rª d n d } |  j j d | | | ƒ qad	 } nŒ | sä d } n  | |  j	 k r[t j | ƒ } |  j	 | j
 | ƒ r't } d } n d } | r9d n d } |  j j d
 | | | ƒ n d	 } | | f S(   s   CURVE ZAP authenticationR^   RG   s    ALLOWED (CURVE allow any client)R   s   Unknown keyt   ALLOWEDt   DENIEDs0   %s (CURVE auth_callback) domain=%s client_key=%ss   Unknown domains"   %s (CURVE) domain=%s client_key=%s(   R   R   R1   R   R#   R   R    R:   t   callbackR   t   get(   R   R.   t
   client_keyRU   RW   t   z85_client_keyt   status(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyRL   9  s@    						c         C   s    |  j  j d | | ƒ t d f S(   sP   Nothing to do for GSSAPI, which has already been handled by an external service.s'   ALLOWED (GSSAPI) domain=%s principal=%sRG   (   R   R#   R1   (   R   R.   R\   (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyRM   l  s    RA   c         C   s‡   | d k r | n d } t  | t ƒ r? | j |  j d ƒ } n  d } |  j j d | | ƒ t | | | | | g } |  j j | ƒ d S(   s.   Send a ZAP reply to finish the authentication.RF   R^   R@   s   ZAP reply code=%s text=%sN(	   t
   isinstanceR   R:   R   R   R#   RJ   R   t   send_multipart(   R   RP   t   status_codet   status_textt   user_idt   metadatat   reply(    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyRI   q  s    N(   t   __name__t
   __module__t   __doc__R   R   R$   R&   R,   R-   R/   R6   R8   R=   R>   R]   RK   RL   RM   RI   (    (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyR      s    
				"		^	!	3	R0   (   Ro   R   R
   t	   zmq.utilsR    t   zmq.utils.strtypesR   R   R   R   t	   zmq.errorR   R   R   R0   RJ   t   objectR   t   __all__(    (    (    s,   lib/python2.7/site-packages/zmq/auth/base.pyt   <module>   s   "ÿ i