
    XR_?                     0   d Z ddlmZmZ ddlmZ ddlZ ej        e          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mZmZmZmZmZ ddlmc mZ g d	Zd
Z G d dej         ej!                  Z" G d de"          Z# G d dej$                  Z%dS )z1
passlib.handlers.cisco -- Cisco password hashes
    )hexlify	unhexlify)md5N)warn)right_pad_string
to_unicoderepeat_stringto_bytes)h64)unicodeujoin_byte_valuesjoin_byte_elemsiter_byte_valuesuascii_to_str)	cisco_pix	cisco_asacisco_type7s    c                   >    e Zd ZdZd ZdZdZdZdZe	j
        ZdZd ZdS )r   a  
    This class implements the password hash used by older Cisco PIX firewalls,
    and follows the :ref:`password-hash-api`.
    It does a single round of hashing, and relies on the username
    as the salt.

    This class only allows passwords <= 16 bytes, anything larger
    will result in a :exc:`~passlib.exc.PasswordSizeError` if passed to :meth:`~cisco_pix.hash`,
    and be silently rejected if passed to :meth:`~cisco_pix.verify`.

    The :meth:`~passlib.ifc.PasswordHash.hash`,
    :meth:`~passlib.ifc.PasswordHash.genhash`, and
    :meth:`~passlib.ifc.PasswordHash.verify` methods
    all support the following extra keyword:

    :param str user:
        String containing name of user account this password is associated with.

        This is *required* in order to correctly hash passwords associated
        with a user account on the Cisco device, as it is used to salt
        the hash.

        Conversely, this *must* be omitted or set to ``""`` in order to correctly
        hash passwords which don't have an associated user account
        (such as the "enable" password).

    .. versionadded:: 1.6

    .. versionchanged:: 1.7.1

        Passwords > 16 bytes are now rejected / throw error instead of being silently truncated,
        to match Cisco behavior.  A number of :ref:`bugs <passlib-asa96-bug>` were fixed
        which caused prior releases to generate unverifiable hashes in certain cases.
       TFc                    | j         }t          |t                    r|                    d          }d}t	          |          | j        k    rH| j        r7d| j        | j        fz  }t          j	        
                    | j        |          |t          z   }| j        }|rRt          |t                    r|                    d          }|rt	          |          dk     r|t          |d          z  }|rt	          |          dk    rd}nd}t          ||          }|r||z  }t          |                                          }t#          d	 t%          |          D                       }t'          j        |                              d
          S )a7  
        This function implements the "encrypted" hash format used by Cisco
        PIX & ASA. It's behavior has been confirmed for ASA 9.6,
        but is presumed correct for PIX & other ASA releases,
        as it fits with known test vectors, and existing literature.

        While nearly the same, the PIX & ASA hashes have slight differences,
        so this function performs differently based on the _is_asa class flag.
        Noteable changes from PIX to ASA include password size limit
        increased from 16 -> 32, and other internal changes.
        utf-8Nz.Password too long (%s allows at most %d bytes))msg      r       c              3   0   K   | ]\  }}|d z   dz  |V  dS )      N ).0ics      8/usr/lib/python3/dist-packages/passlib/handlers/cisco.py	<genexpr>z+cisco_pix._calc_checksum.<locals>.<genexpr>   s3       P Ptq!QUaK P P P P P P P    ascii)_is_asa
isinstancer   encodelentruncate_sizeuse_defaultsnameuhexcPasswordSizeError_DUMMY_BYTESuserr	   r   r   digestr   	enumerater   encode_bytesdecode)selfsecretasaspoil_digestr   r3   pad_sizer4   s           r$   _calc_checksumzcisco_pix._calc_checksumg   s    l fg&& 	,]]7++F, v;;+++  5Fy$"456f..t/As.KKK  &4. y 	1$(( ,{{7++ 1#f++**-a000  	3v;;##HHH!&(33
  	#l"FV##%% ! P Py/@/@ P P PPP
 ''..w777r&   N)__name__
__module____qualname____doc__r.   r,   truncate_errortruncate_verify_rejectchecksum_sizer/   HASH64_CHARSchecksum_charsr(   r=   r    r&   r$   r   r   $   sa        ! !R DM N!
 M_N G
|8 |8 |8 |8 |8r&   r   c                       e Zd ZdZd ZdZdZdS )r   a  
    This class implements the password hash used by Cisco ASA/PIX 7.0 and newer (2005).
    Aside from a different internal algorithm, it's use and format is identical
    to the older :class:`cisco_pix` class.

    For passwords less than 13 characters, this should be identical to :class:`!cisco_pix`,
    but will generate a different hash for most larger inputs
    (See the `Format & Algorithm`_ section for the details).

    This class only allows passwords <= 32 bytes, anything larger
    will result in a :exc:`~passlib.exc.PasswordSizeError` if passed to :meth:`~cisco_asa.hash`,
    and be silently rejected if passed to :meth:`~cisco_asa.verify`.

    .. versionadded:: 1.7

    .. versionchanged:: 1.7.1

        Passwords > 32 bytes are now rejected / throw error instead of being silently truncated,
        to match Cisco behavior.  A number of :ref:`bugs <passlib-asa96-bug>` were fixed
        which caused prior releases to generate unverifiable hashes in certain cases.
    r   TN)r>   r?   r@   rA   r.   r,   r(   r    r&   r$   r   r      s-         8 D
 M
 GGGr&   r   c                        e Zd ZdZd ZdZej        ZdZ	dZ
ed fd	            Zed             Zd fd	Zedd
            Zed             Zd Zd Zedd            Z ed          Zed             Z xZS )r   a+  
    This class implements the "Type 7" password encoding used by Cisco IOS,
    and follows the :ref:`password-hash-api`.
    It has a simple 4-5 bit salt, but is nonetheless a reversible encoding
    instead of a real hash.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:

    :type salt: int
    :param salt:
        This may be an optional salt integer drawn from ``range(0,16)``.
        If omitted, one will be chosen at random.

    :type relaxed: bool
    :param relaxed:
        By default, providing an invalid value for one of the other
        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
        will be issued instead. Correctable errors include
        ``salt`` values that are out of range.

    Note that while this class outputs digests in upper-case hexadecimal,
    it will accept lower-case as well.

    This class also provides the following additional method:

    .. automethod:: decode
    saltr   4   Nc                      t          t          |           j        di |}A|                    |                    d                    t          fd          |_        |S )Nrelaxed)rM   c                       S Nr    rI   s   r$   <lambda>z#cisco_type7.using.<locals>.<lambda>f  s     r&   r    )superr   using
_norm_saltgetstaticmethod_generate_salt)clsrJ   kwdssubcls	__class__s    `  r$   rR   zcisco_type7.usinga  sk    .{C((.6666$$T488I3F3F$GGD$0$>$>F!r&   c                    t          |dd          }t          |          dk     rt          j                            |           t          |d d                   } | ||dd                                                    S )Nr'   hash   )rJ   checksum)r   r+   r/   r0   InvalidHashErrorintupper)rW   r\   rJ   s      r$   from_stringzcisco_type7.from_stringi  sr    $00t99q==&))#...48}}stABBx~~'7'78888r&   c                 (    t          t          |           j        di | ||                     |          }nQ| j        r;|                                 }|                     |          |k    sJ d|            nt          d          || _        d S )Nzgenerated invalid salt: zno salt specifiedr    )rQ   r   __init__rS   r-   rV   	TypeErrorrJ   )r8   rJ   rX   rZ   s      r$   rd   zcisco_type7.__init__q  s    )k4  )11D111??4((DD 	1&&((D??4((D0000RVRV2X0000/000			r&   Fc                    t          |t                    s!t          j                            |dd          d|cxk    r| j        k    rn n|S d}|r)t          |t          j                   |dk     rdn| j        S t          |          )z
        validate & normalize salt value.
        .. note::
            the salt for this algorithm is an integer 0-52, not a string
        integerrJ   r   z"salt/offset must be in 0..52 range)	r)   r`   r/   r0   ExpectedTypeErrormax_salt_valuer   PasslibHashWarning
ValueError)rW   rJ   rM   r   s       r$   rS   zcisco_type7._norm_salt|  s     $$$ 	D&**4FCCC**********K2 	"b+,,,q11c&88S//!r&   c                  B    t           j                            dd          S )Nr      )r/   rngrandintr    r&   r$   rV   zcisco_type7._generate_salt  s    v~~a$$$r&   c                 >    d| j         t          | j                  fz  S )Nz%02d%s)rJ   r   r^   )r8   s    r$   	to_stringzcisco_type7.to_string  s    49mDM&B&BCCCr&   c                     t          |t                    r|                    d          }t          |                     || j                                                d                                          S )Nr   r'   )r)   r   r*   r   _cipherrJ   r7   ra   )r8   r9   s     r$   r=   zcisco_type7._calc_checksum  s_     fg&& 	,]]7++Ft||FDI6677>>wGGMMOOOr&   r   c                     |                      |          }t          |j                            d                    }|                    ||j                  }|r|                    |          n|S )zdecode hash, returning original password.

        :arg hash: encoded password
        :param encoding: optional encoding to use (defaults to ``UTF-8``).
        :returns: password as unicode
        r'   )rb   r   r^   r*   rs   rJ   r7   )rW   r\   encodingr8   tmpraws         r$   r7   zcisco_type7.decode  sc     t$$,,W5566ll3	**'/8szz(###S8r&   z5dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87c                     | j         t                    t          fdt          t	          |                    D                       S )z1xor static key against data - encrypts & decryptsc              3   Z   K   | ]%\  }}|t          |z   z                     z  V  &d S rO   )ord)r!   idxvaluekeykey_sizerJ   s      r$   r%   z&cisco_type7._cipher.<locals>.<genexpr>  sV        
  
U CTCZ834555 
  
  
  
  
  
r&   )_keyr+   r   r5   r   )rW   datarJ   r}   r~   s     `@@r$   rs   zcisco_type7._cipher  sl     hs88  
  
  
  
  
  
'(8(>(>?? 
  
  
 
 
 	
r&   rO   )F)r   )r>   r?   r@   rA   r.   setting_kwdsr/   UPPER_HEX_CHARSrF   min_salt_valueri   classmethodrR   rb   rd   rS   rU   rV   rq   r=   r7   r   r   rs   __classcell__)rZ   s   @r$   r   r   )  sY        F DL
 'N NN
      [ 9 9 [9	 	 	 	 	 	 " " " ["" % % \%D D DP P P 
9 
9 
9 [
9 1DEED
 
 [
 
 
 
 
r&   r   )&rA   binasciir   r   hashlibr   logging	getLoggerr>   logwarningsr   passlib.utilsr   r   r	   r
   passlib.utils.binaryr   passlib.utils.compatr   r   r   r   r   r   passlib.utils.handlersutilshandlersr/   __all__r2   HasUserContextStaticHandlerr   r   GenericHandlerr   r    r&   r$   <module>r      s    ( ' ' ' ' ' ' '       'g'11       P O O O O O O O O O O O $ $ $ $ $ $> > > > > > > > > > > > > > > > # # # # # # # # #   
8 8 8 8 8!2#3 8 8 8j' ' ' ' '	 ' ' '`K
 K
 K
 K
 K
"# K
 K
 K
 K
 K
r&   