U
    h?                     @   s   d Z ddlmZmZ ddlmZ ddlZe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  mZ d	d
dgZdZG dd	 d	ej ej!Z"G dd
 d
e"Z#G d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                   @   s6   e Zd ZdZd ZdZdZdZdZe	j
ZdZd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                 C   s   | j }t|tr|d}d}t|| jkr^| jrVd| j| jf }tj	j
| j|dn|t }| j}|rt|tr||d}|rt|dk r|t|d7 }|rt|dkrd}nd}t||}|r||7 }t| }td	d
 t|D }t|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                 s   s"   | ]\}}|d  d@ r|V  qdS )      N ).0icr   r   <./venv/lib/python3.8/site-packages/passlib/handlers/cisco.py	<genexpr>   s      z+cisco_pix._calc_checksum.<locals>.<genexpr>ascii)_is_asa
isinstancer   encodelentruncate_sizeuse_defaultsnameuhexcZPasswordSizeError_DUMMY_BYTESuserr   r   r   digestr   	enumerater
   Zencode_bytesdecode)selfsecretZasaZspoil_digestr   r-   Zpad_sizer.   r   r   r    _calc_checksumg   s4    






zcisco_pix._calc_checksumN)__name__
__module____qualname____doc__r)   r'   Ztruncate_errorZtruncate_verify_rejectZchecksum_sizer*   ZHASH64_CHARSchecksum_charsr#   r3   r   r   r   r    r   $   s   )c                   @   s   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)r4   r5   r6   r7   r)   r'   r#   r   r   r   r    r      s   c                       s   e Zd ZdZd ZdZejZdZ	dZ
ed fdd	Zedd	 Zd fd
d	ZedddZedd Zdd Zdd ZedddZedZedd Z  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                    sD   t t| jf |} d k	r@|j |dd t fdd|_|S )Nrelaxed)r<   c                      s    S Nr   r   r9   r   r    <lambda>f      z#cisco_type7.using.<locals>.<lambda>)superr   using
_norm_saltgetstaticmethod_generate_salt)clsr:   kwdssubcls	__class__r9   r    rA   a  s
    zcisco_type7.usingc                 C   sL   t |dd}t|dk r$tj| t|d d }| ||dd   dS )Nr"   hash   )r:   checksum)r   r&   r*   r+   ZInvalidHashErrorintupper)rF   rK   r:   r   r   r    from_stringi  s
    zcisco_type7.from_stringc                    sd   t t| jf | |d k	r&| |}n4| jrR|  }| ||ksZtd|f ntd|| _d S )Nzgenerated invalid salt: %rzno salt specified)	r@   r   __init__rB   r(   rE   AssertionError	TypeErrorr:   )r1   r:   rG   rI   r   r    rQ   q  s    zcisco_type7.__init__Fc                 C   sj   t |tstj|ddd|  kr0| jkr8n n|S d}|r^t|tj |dk rXdS | jS t|dS )z
        validate & normalize salt value.
        .. note::
            the salt for this algorithm is an integer 0-52, not a string
        Zintegerr:   r   z"salt/offset must be in 0..52 rangeN)	r$   rN   r*   r+   ZExpectedTypeErrormax_salt_valuer   ZPasslibHashWarning
ValueError)rF   r:   r<   r   r   r   r    rB   |  s    
zcisco_type7._norm_saltc                   C   s   t jddS )Nr      )r*   rngZrandintr   r   r   r    rE     s    zcisco_type7._generate_saltc                 C   s   d| j t| jf S )Nz%02d%s)r:   r   rM   )r1   r   r   r    	to_string  s    zcisco_type7.to_stringc                 C   s0   t |tr|d}t| || jd S )Nr   r"   )r$   r   r%   r   _cipherr:   r0   rO   )r1   r2   r   r   r    r3     s    

zcisco_type7._calc_checksumr   c                 C   s:   |  |}t|jd}|||j}|r6||S |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"   )rP   r   rM   r%   rY   r:   r0   )rF   rK   encodingr1   Ztmprawr   r   r    r0     s    
zcisco_type7.decodez5dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87c                    s0   | j  t t fddtt|D S )z1xor static key against data - encrypts & decryptsc                 3   s*   | ]"\}}|t  |   A V  qd S r=   )ord)r   idxvaluekeyZkey_sizer:   r   r    r!     s   z&cisco_type7._cipher.<locals>.<genexpr>)_keyr&   r   r/   r   )rF   datar:   r   r_   r    rY     s
    
zcisco_type7._cipher)N)N)F)r   )r4   r5   r6   r7   r)   Zsetting_kwdsr*   ZUPPER_HEX_CHARSr8   Zmin_salt_valuerT   classmethodrA   rP   rQ   rB   rD   rE   rX   r3   r0   r   ra   rY   __classcell__r   r   rI   r    r   )  s,   #

)&r7   Zbinasciir   r   Zhashlibr   ZloggingZ	getLoggerr4   logwarningsr   Zpasslib.utilsr   r   r   r	   Zpasslib.utils.binaryr
   Zpasslib.utils.compatr   r   r   r   r   r   Zpasslib.utils.handlersZutilsZhandlersr*   __all__r,   ZHasUserContextZStaticHandlerr   r   ZGenericHandlerr   r   r   r   r    <module>   s$    
  V0