U
    4JeND                     @   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 zddlZW n, ek
r   dZejdkred	dY nX z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rd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ed< dZeed< dZ	e
ej ed< 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_clientplugin_nameFrequires_sslNcontext)returnc                  C   sb   z:t jdd} t| j}|ddkr6|dd\}}|W S  t jjjk
r\   t	
  Y 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'   Z/tmp/pip-unpacked-wheel-7_167w8m/mysql/connector/plugins/authentication_kerberos_client.pyget_user_from_credentialsL   s    
z1MySQLKerberosAuthPlugin.get_user_from_credentialsc                  C   s`   t jdt jdkr dt   ntdd} | s<tdt	d|  dd	|  
d
i}|S )zGet 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: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 d t|tjj}| jd}z:tjj	||dd}|j
}tjj|  |tjjddd W n8 tjjjk
r } ztd| |W 5 d}~X Y nX |S )	zAcquire 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 passwordr+   r   r   T)r$   Zmech	overwriteset_defaultz7Unable to acquire credentials with the given password: N)r	   r1   r   NameNameTyper%   	_passwordr2   r   Zacquire_cred_with_passwordr$   Zstore_cred_intor4   MechTypekerberosr    r!   r   )selfr5   r%   passwordZacquire_cred_resultr$   errr'   r'   r(   _acquire_cred_with_passwordp   s0    	
  
z3MySQLKerberosAuthPlugin._acquire_cred_with_passwordpacketr   c                 C   s   t d| dd d }| dd } t d| d| d| d }| |d } t d| dd d }t d| d| dd d }| | 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rB   Zspn_lenspnZ	realm_lenrealmr'   r'   r(   _parse_auth_data   s      z(MySQLKerberosAuthPlugin._parse_auth_data	auth_datar   c              
   C   s  d}d}|rTz|  |\}}W n4 tjk
rR } ztd| |W 5 d}~X Y nX |dkrd|  S | jrz| j d| nd}td| td| ztj	dd}t
|j}td td	| |dd
kr|dd\}}	n|}d}	| jr| j d| n|}| jr<| j|kr<td | jdk	r<| |}|	rb|	|krb| jdk	rb| |}W n tjjjk
r } z2|r| jdk	r| |}ntd| |W 5 d}~X Y nX tjjjk
r } z2|r| jdk	r| |}ntd| |W 5 d}~X Y nX tjjtjjtjjf}
tj|tjjd}|tjj}tj ||t!|
dd| _"z| j"# }W n: tjjjk
r } ztd| |W 5 d}~X Y nX td| |S )(Prepare the first message to the server.NInvalid authentication data: r   Service Principal: %s	Realm: %sr   r   zCached credentials foundzCached credentials UPN: %sr   r   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   %Unable to initiate security context: Initial client token: %s)$rM   rG   errorInterruptedErrorZprepare_password	_usernamer	   r1   r   r   r   r   r   r   r:   r@   r   
exceptionsZExpiredCredentialsErrorr   r    r!   ZRequirementFlagZmutual_authenticationZextended_errorZdelegate_to_peerr8   r9   Zkerberos_principalcanonicalizer;   r<   SecurityContextsumr   step)r=   rO   rK   rL   r?   r5   r$   Z	creds_upnZ
creds_userZcreds_realmrT   r   cnameinitial_client_tokenr'   r'   r(   auth_response   sx    "


    "z%MySQLKerberosAuthPlugin.auth_responsetgt_auth_challenger   c                 C   s@   t d| | j|}t d| t d| jj || jjfS )!  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).
        tgt_auth challenge: %szContext step response: %sContext completed?: %s)r	   r1   r   r^   complete)r=   rc   respr'   r'   r(   auth_continue   s
    z%MySQLKerberosAuthPlugin.auth_continue)messager   c              
   C   s   | j jstdtd| td| j j z| j |}td| W nD tjj	j
k
r } z td| td| |W 5 d}~X Y nX td| td	}td
| | j j|dd}t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   )r   rg   r   r	   r1   Zactual_flagsunwrapr   r   rZ   ZBadMICErrorr   	bytearraywraplenrj   )r=   rj   Zunwrapedr?   responseZwrapedr'   r'   r(   auth_accept_close_handshake  s(    "
z3MySQLKerberosAuthPlugin.auth_accept_close_handshake)N)__name__
__module____qualname____doc__r   r   __annotations__r   boolr   r   r   r\   staticmethodr)   dictr4   r   r$   ZCredsr@   bytesr   rM   ra   ri   rp   r'   r'   r'   r(   r   E   s    
Oc                   @   s   e Zd ZU dZdZeed< dZeed< dZ	e
ed< dZe
ed< 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   r   Fr   Nr   
clientauthrA   c                 C   s   t d| dd d }| dd } t d| d| d| d }| |d } t d| dd d }t d| d| dd d }| | fS rC   rF   rJ   r'   r'   r(   rM   P  s      z,MySQLSSPIKerberosAuthPlugin._parse_auth_datarN   c              
   C   s  t d d}d}|r^z| |\}}W n4 tjk
r\ } ztd| |W 5 d}~X Y nX t d| t d| tdkstdkrtdtj	tj
f}| jr| jr| j|| jf}nd}|}t d| t d|dk tjd	||t|tjd
| _zZd}| j|\}}	t d| t d|	 t d| jj |	d j}
t d| jj W n4 tk
r } ztd| |W 5 d}~X Y nX t d|
 |
S )rP   zauth_response for sspiNrQ   rR   rS   zKPackage "pywin32" (Python for Win32 (pywin32) extensions) is not installed.ztargetspn: %sz_auth_info is None: %sZ	Negotiate)	targetspnZ	auth_infoZscflagsZdatarepContext step err: %sContext step out_buf: %srf   r   zpkg_info: %srU   rV   )r	   r1   rM   rG   rW   rX   sspiconsspir   ZISC_REQ_MUTUAL_AUTHZISC_REQ_DELEGATErY   r:   Z
ClientAuthr]   ZSECURITY_NETWORK_DREPrz   	authorizeauthenticatedBufferpkg_info	Exceptionr   )r=   rO   rK   rL   r?   rT   Z
_auth_infor{   dataout_bufr`   r'   r'   r(   ra   j  sP    
"
"z)MySQLSSPIKerberosAuthPlugin.auth_responserb   c                 C   sf   t d| | j|\}}t d| t d| |d j}t d| t d| jj || jjfS )rd   re   r|   r}   r   zContext step resp: %srf   )r	   r1   rz   r   r   r   )r=   rc   r?   r   rh   r'   r'   r(   ri     s    
z)MySQLSSPIKerberosAuthPlugin.auth_continue)N)rq   rr   rs   rt   r   r   ru   r   rv   r   r   rz   rw   ry   r   rM   r   ra   ri   r'   r'   r'   r(   r   H  s   
J)rt   r"   r,   rG   pathlibr   typingr   r   r   errorsr   r   r	   r   ImportErrorr   r   r~    r   ZAUTHENTICATION_PLUGIN_CLASSr   r   r'   r'   r'   r(   <module>   s<   

  