3
ŠãdeND  ã               @   s  d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	 ddl
mZmZ ddlmZ yddlZW n, ek
r�   dZejdkrŒed	ƒd‚Y nX yddlZddlZW n ek
rÂ   dZdZY nX d
dlmZ ejdkrÞdndZG dd„ deƒZG dd„ deƒZdS )zKerberos Authentication Plugin.é    N)ÚPath)ÚAnyÚOptionalÚTupleé   )ÚInterfaceErrorÚProgrammingError)ÚloggerÚntzwModule gssapi is required for GSSAPI authentication mechanism but was not found. Unable to authenticate with the serveré   )ÚBaseAuthPluginÚMySQLSSPIKerberosAuthPluginÚMySQLKerberosAuthPluginc               @   sÐ   e Zd ZU dZdZedZedZe	e
j eedœdd„ƒZeedœdd	„ƒZee
jjjd
œdd„Zeeeeef dœdd„ƒZde	e e	e dœdd„Ze	e ee	e ef dœdd„Zeedœdd„ZdS )r   z3Implement the MySQL Kerberos authentication plugin.Úauthentication_kerberos_clientFN)Úreturnc              C   s\   y8t jdd�} t| jƒ}|jdƒdkr6|jddƒ\}}|S  t jjjk
rV   t	j
ƒ S X dS )z(Get user from credentials without realm.Úinitiate)Úusageú@r   Néÿÿÿÿ)ÚgssapiÚCredentialsÚstrÚnameÚfindÚsplitÚrawÚmiscÚGSSErrorÚgetpassÚgetuser)ÚcredsÚuserÚ_© r#   úm/var/www/agendate/envp3/lib/python3.6/site-packages/mysql/connector/plugins/authentication_kerberos_client.pyÚget_user_from_credentialsL   s    
z1MySQLKerberosAuthPlugin.get_user_from_credentialsc              C   s`   t jjdt jdkr dt jƒ › �ntdƒjdƒƒ} | s<tdƒ‚tj	d| ƒ dd	| › �j
d
ƒi}|S )zäGet a credentials store dictionary.

        Returns:
            dict: Credentials store dictionary with the krb5 ccache name.

        Raises:
            InterfaceError: If 'KRB5CCNAME' environment variable is empty.
        Z
KRB5CCNAMEÚposixz/tmp/krb5cc_z%TEMP%Zkrb5ccz5The 'KRB5CCNAME' environment variable is set to emptyzUsing krb5 ccache name: FILE:%ss   ccachezFILE:zutf-8)ÚosÚenvironÚgetr   Úgetuidr   Újoinpathr   r	   ÚdebugÚencode)Z
krb5ccnameÚstorer#   r#   r$   Ú	get_storeX   s    
z!MySQLKerberosAuthPlugin.get_store)Úupnr   c             C   sž   t jdƒ tj|tjjƒ}| jjdƒ}y:tjj	||dd�}|j
}tjj| jƒ |tjjddd� W n8 tjjjk
r˜ } ztd|› �ƒ|‚W Y dd}~X nX |S )	zÆAcquire and store credentials through provided password.

        Args:
            upn (str): User Principal Name.

        Returns:
            gssapi.raw.creds.Creds: GSSAPI credentials.
        z8Attempt to acquire credentials through provided passwordzutf-8r   )r   T)r    ZmechÚ	overwriteÚset_defaultz7Unable to acquire credentials with the given password: N)r	   r,   r   ÚNameÚNameTyper!   Ú	_passwordr-   r   Zacquire_cred_with_passwordr    Zstore_cred_intor/   ÚMechTypeÚkerberosr   r   r   )Úselfr0   r!   ÚpasswordZacquire_cred_resultr    Úerrr#   r#   r$   Ú_acquire_cred_with_passwordp   s$    	

z3MySQLKerberosAuthPlugin._acquire_cred_with_password)Úpacketr   c             C   s˜   t jd| dd… ƒd }| dd… } t jd|› d�| d|… ƒd }| |d… } t jd| dd… ƒd }t jd|› d�| dd… ƒd }|jƒ |jƒ fS )aY  Parse authentication data.

        Get the SPN and REALM from the authentication data packet.

        Format:
            SPN string length two bytes <B1> <B2> +
            SPN string +
            UPN realm string length two bytes <B1> <B2> +
            UPN realm string

        Returns:
            tuple: With 'spn' and 'realm'.
        z<HNr   r   ú<Ús)ÚstructÚunpackÚdecode)r<   Úspn_lenÚspnÚ	realm_lenÚrealmr#   r#   r$   Ú_parse_auth_data�   s      z(MySQLKerberosAuthPlugin._parse_auth_data)Ú	auth_datar   c          -   C   s¼  d}d}|rTy| j |ƒ\}}W n4 tjk
rR } ztd|› �ƒ|‚W Y dd}~X nX |dkrd| jƒ S | jrz| j› d|› �nd}tjd|ƒ tjd|ƒ yÎtj	dd�}t
|jƒ}tjdƒ tjd	|ƒ |jdƒdkrä|jdd
ƒ\}}	n|}d}	| j�r| j› d|› �n|}| j�r<| j|k�r<tjdƒ | jdk	�r<| j|ƒ}|	�rb|	|k�rb| jdk	�rb| j|ƒ}W n® tjjjk
�r¼ } z4|�rœ| jdk	�rœ| j|ƒ}ntd|› �ƒ|‚W Y dd}~X nX tjjjk
�r } z4|�rò| jdk	�rò| j|ƒ}ntd|› �ƒ|‚W Y dd}~X nX tjjtjjtjjf}
tj|tjjd�}|jtjjƒ}tj ||t!|
ƒdd�| _"y| j"j#ƒ }W n: tjjjk
�rª } ztd|› �ƒ|‚W Y dd}~X nX tjd|ƒ |S )z(Prepare the first message to the server.NzInvalid authentication data: r   zService Principal: %sz	Realm: %sr   )r   zCached credentials foundzCached credentials UPN: %sr   zBThe user from cached credentials doesn't match with the given userzCredentials has expired: z-Unable to retrieve cached credentials error: )Z	name_type)r   r    Úflagsr   z%Unable to initiate security context: zInitial client token: %sr   )$rF   r?   ÚerrorÚInterruptedErrorZprepare_passwordÚ	_usernamer	   r,   r   r   r   r   r   r   r5   r;   r   Ú
exceptionsZExpiredCredentialsErrorr   r   r   ZRequirementFlagZmutual_authenticationZextended_errorZdelegate_to_peerr3   r4   Zkerberos_principalZcanonicalizer6   r7   ÚSecurityContextÚsumÚcontextÚstep)r8   rG   rC   rE   r:   r0   r    Z	creds_upnZ
creds_userZcreds_realmrH   r   ÚcnameÚinitial_client_tokenr#   r#   r$   Úauth_response©   sh    "


 

"z%MySQLKerberosAuthPlugin.auth_response)Útgt_auth_challenger   c             C   s@   t jd|ƒ | jj|ƒ}t jd|ƒ t jd| jjƒ || jjfS )a!  Continue with the Kerberos TGT service request.

        With the TGT authentication service given response generate a TGT
        service request. This method must be invoked sequentially (in a loop)
        until the security context is completed and an empty response needs to
        be send to acknowledge the server.

        Args:
            tgt_auth_challenge: the challenge for the negotiation.

        Returns:
            tuple (bytearray TGS service request,
            bool True if context is completed otherwise False).
        ztgt_auth challenge: %szContext step response: %szContext completed?: %s)r	   r,   rO   rP   Úcomplete)r8   rT   Úrespr#   r#   r$   Úauth_continue÷   s
    z%MySQLKerberosAuthPlugin.auth_continue)Úmessager   c             C   sÞ   | j jstdƒ‚tjd|ƒ tjd| j jƒ y| j j|ƒ}tjd|ƒ W nD tjj	j
k
rŒ } z"tjd|ƒ td|› �ƒ|‚W Y dd}~X nX tjd|ƒ td	ƒ}tjd
|ƒ | j j|dd�}tjd|d t|d ƒƒ |jS )a_  Accept handshake and generate closing handshake message for server.

        This method verifies the server authenticity from the given message
        and included signature and generates the closing handshake for the
        server.

        When this method is invoked the security context is already established
        and the client and server can send GSSAPI formated secure messages.

        To finish the authentication handshake the server sends a message
        with the security layer availability and the maximum buffer size.

        Since the connector only uses the GSSAPI authentication mechanism to
        authenticate the user with the server, the server will verify clients
        message signature and terminate the GSSAPI authentication and send two
        messages; an authentication acceptance b'  ' and a
        OK packet (that must be received after sent the returned message from
        this method).

        Args:
            message: a wrapped gssapi message from the server.

        Returns:
            bytearray (closing handshake message to be send to the server).
        z!Security context is not completedzServer message: %szGSSAPI flags in use: %szUnwraped: %sz#Unable to unwrap server message: %sz!Unable to unwrap server message: NzUnwrapped server message: %ss      zMessage response: %sF)Zencryptz(Wrapped message response: %s, length: %dr   )rO   rU   r   r	   r,   Zactual_flagsÚunwrapr   r   rL   ZBadMICErrorr   Ú	bytearrayÚwrapÚlenrX   )r8   rX   Zunwrapedr:   ÚresponseZwrapedr#   r#   r$   Úauth_accept_close_handshake  s&    "z3MySQLKerberosAuthPlugin.auth_accept_close_handshake)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úplugin_namer   Úrequires_sslÚboolrO   r   r   rM   Ústaticmethodr%   Údictr/   r   r    ZCredsr;   Úbytesr   rF   rS   rW   r^   r#   r#   r#   r$   r   E   s   
Oc               @   sˆ   e Zd ZU dZdZedZedZe	dZ
e	
eeeeef dœdd„ƒZdee ee dœd	d
„Zee eee ef dœdd„ZdS )r   zDImplement the MySQL Kerberos authentication plugin with Windows SSPIr   FN)r<   r   c             C   s˜   t jd| dd… ƒd }| dd… } t jd|› d�| d|… ƒd }| |d… } t jd| dd… ƒd }t jd|› d�| dd… ƒd }|jƒ |jƒ fS )aY  Parse authentication data.

        Get the SPN and REALM from the authentication data packet.

        Format:
            SPN string length two bytes <B1> <B2> +
            SPN string +
            UPN realm string length two bytes <B1> <B2> +
            UPN realm string

        Returns:
            tuple: With 'spn' and 'realm'.
        z<HNr   r   r=   r>   )r?   r@   rA   )r<   rB   rC   rD   rE   r#   r#   r$   rF   P  s      z,MySQLSSPIKerberosAuthPlugin._parse_auth_data)rG   r   c             C   s–  t jdƒ d}d}|r^y| j|ƒ\}}W n4 tjk
r\ } ztd|› �ƒ|‚W Y dd}~X nX t jd|ƒ t jd|ƒ tdks†tdkrŽtdƒ‚tj	tj
f}| jr¶| jr¶| j|| jf}nd}|}t jd|ƒ t jd|dkƒ tjd	||t|ƒtjd
�| _yZd}| jj|ƒ\}}	t jd|ƒ t jd|	ƒ t jd| jjƒ |	d j}
t jd| jjƒ W n4 tk
�r„ } ztd|› �ƒ|‚W Y dd}~X nX t jd|
ƒ |
S )z(Prepare the first message to the server.zauth_response for sspiNzInvalid authentication data: zService Principal: %sz	Realm: %szKPackage "pywin32" (Python for Win32 (pywin32) extensions) is not installed.ztargetspn: %sz_auth_info is None: %sZ	Negotiate)Ú	targetspnZ	auth_infoZscflagsZdatarepzContext step err: %szContext step out_buf: %szContext completed?: %sr   zpkg_info: %sz%Unable to initiate security context: zInitial client token: %s)r	   r,   rF   r?   rI   rJ   ÚsspiconÚsspir   ZISC_REQ_MUTUAL_AUTHZISC_REQ_DELEGATErK   r5   Z
ClientAuthrN   ZSECURITY_NETWORK_DREPÚ
clientauthÚ	authorizeÚauthenticatedÚBufferÚpkg_infoÚ	Exceptionr   )r8   rG   rC   rE   r:   rH   Z
_auth_infori   ÚdataÚout_bufrR   r#   r#   r$   rS   j  sL    
"
"z)MySQLSSPIKerberosAuthPlugin.auth_response)rT   r   c             C   sf   t jd|ƒ | jj|ƒ\}}t jd|ƒ t jd|ƒ |d j}t jd|ƒ t jd| jjƒ || jjfS )a!  Continue with the Kerberos TGT service request.

        With the TGT authentication service given response generate a TGT
        service request. This method must be invoked sequentially (in a loop)
        until the security context is completed and an empty response needs to
        be send to acknowledge the server.

        Args:
            tgt_auth_challenge: the challenge for the negotiation.

        Returns:
            tuple (bytearray TGS service request,
            bool True if context is completed otherwise False).
        ztgt_auth challenge: %szContext step err: %szContext step out_buf: %sr   zContext step resp: %szContext completed?: %s)r	   r,   rl   rm   ro   rn   )r8   rT   r:   rs   rV   r#   r#   r$   rW   ³  s    
z)MySQLSSPIKerberosAuthPlugin.auth_continue)N)r_   r`   ra   rb   rc   r   rd   re   rO   r   rl   rf   rh   r   rF   r   rS   rW   r#   r#   r#   r$   r   H  s   
J)rb   r   r'   r?   Úpathlibr   Útypingr   r   r   Úerrorsr   r   r	   r   ÚImportErrorr   rk   rj   Ú r   ZAUTHENTICATION_PLUGIN_CLASSr   r   r#   r#   r#   r$   Ú<module>   s6   


  