
    3i]                        d Z ddlZddlmZmZ ddlmZmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ e	rddlmZ 	 ddlZddlmZm Z! ddl"m#Z# dZ$ G d de#      Z%y# e$ r
  ed      dw xY w)z LDAP SASL Authentication Plugin.    N)	b64decode	b64encode)sha1sha256)TYPE_CHECKINGAnyCallableListOptionalTuple)uuid4   )
ERR_STATUS)InterfaceErrorProgrammingError)logger)
StrOrBytes)MySQLSocketzwModule gssapi is required for GSSAPI authentication mechanism but was not found. Unable to authenticate with the server)normalize_unicode_string"validate_normalized_unicode_string   )MySQLAuthPluginMySQLLdapSaslPasswordAuthPluginc                   x   e Zd ZU dZg dZee   ed<   eZ	e
ed<   dZee   ed<   dZeed<   dZee   ed<   dZee   ed	<   d
Zeed<   dZee   ed<   dZeej,                     ed<   dZej0                  ed<   dZee   ed<   dZee   ed<   edededefd       ZdededefdZdedededefdZededefd       Z defdZ!dee   fdZ"dee   de#ee   e$f   fdZ%d edefd!Z&d"ed#edee   fd$Z'defd%Z(deddfd&Z)d'edefd(Z*d)e+de$fd*Z,d+e+de$fd,Z-e.defd-       Z/e.de$fd.       Z0d/d0d"ed#edefd1Z1y)2r   a5  Class implementing the MySQL ldap sasl authentication plugin.

    The MySQL's ldap sasl authentication plugin support two authentication
    methods SCRAM-SHA-1 and GSSAPI (using Kerberos). This implementation only
    support SCRAM-SHA-1 and SCRAM-SHA-256.

    SCRAM-SHA-1 amd SCRAM-SHA-256
        This method requires 2 messages from client and 2 responses from
        server.

        The first message from client will be generated by prepare_password(),
        after receive the response from the server, it is required that this
        response is passed back to auth_continue() which will return the
        second message from the client. After send this second message to the
        server, the second server respond needs to be passed to auth_finalize()
        to finish the authentication process.
    )zSCRAM-SHA-1zSCRAM-SHA-256GSSAPIsasl_mechanismsdef_digest_modeNclient_nonceclient_saltserver_saltkrb_service_principalr   
iterationsserver_auth_vartarget_namectxservers_firstserver_noncebytes1bytes2returnc                 d    t        t        | |      D cg c]
  \  }}||z   c}}      S c c}}w N)byteszip)r(   r)   b1b2s       \D:\jyotish\venv\Lib\site-packages\mysql/connector/plugins/authentication_ldap_sasl_client.py_xorz$MySQLLdapSaslPasswordAuthPlugin._xora   s0    C,?@,?&"bb2g,?@AA@s   ,
passwordsaltc                 d    t        j                  ||| j                        }|j                         S r,   )hmacnewr   digest)selfr3   r4   digest_makers       r1   _hmacz%MySQLLdapSaslPasswordAuthPlugin._hmace   s)    xx$0D0DE""$$    countc                     |j                         }| j                  ||dz         }|}t        |dz
        D ]&  }| j                  ||      }| j                  ||      }( |S )zPrepares Hi
        Hi(password, salt, iterations) where Hi(p,s,i) is defined as
        PBKDF2 (HMAC, p, s, i, output length of H).
        s      r   )encoder;   ranger2   )r9   r3   r4   r=   pwhiaux_s           r1   _hiz#MySQLLdapSaslPasswordAuthPlugin._hii   se    
 __ZZD#667uqy!A**R%C2s#B " 	r<   stringc                 R    t        |       }t        |      }|t        d|       |S )Nzbroken_rule: )	norm_ustr
valid_normr   )rF   norm_strbroken_rules      r1   
_normalizez*MySQLLdapSaslPasswordAuthPlugin._normalizev   s3    V$ *" =!>??r<   c                    d}t        t                     j                  dd      | _        |j	                  | j                  | j                        | j                        }t        |t               r|j                  d      }|S )aq  This method generates the first message to the server to start the

        The client-first message consists of a gs2-header,
        the desired username, and a randomly generated client nonce cnonce.

        The first message from the server has the form:
            b'n,a=<user_name>,n=<user_name>,r=<client_nonce>

        Returns client's first message
        z.n,a={user_name},n={user_name},r={client_nonce}- )	user_namer   utf8)	strr   replacer   formatrL   	_username
isinstancer?   )r9   
cfm_fprnatcfms      r1   _first_messagez.MySQLLdapSaslPasswordAuthPlugin._first_message~   sr     F
L00b9$++oodnn5** , 

 c3**V$C
r<   c                 V   t         j                  j                  j                  | j                  j                  d      t         j                  j                        }	 t        j                         }t        j                  d       	 |j                   	 t         j,                  j.                  t         j,                  j0                  t         j,                  j2                  f}| j4                  r| j4                  }nd}t        j                  d|       t        j6                  |t         j                  j8                        }|| _        t        j<                  ||t?        |      d	      | _         	 | j@                  jC                         }	t        j                  d|	       |	S # t         j                  j                  j                  $ r;}t        j                  d|       |j                  |       t!        d|       |d}~ww xY w# t         j                  j"                  j$                  $ r}| j&                  st!        d|       |	 t        j                  d       t         j                  j)                  || j&                  j                  d      d	
      }|d   }n># t         j                  j"                  j$                  $ r}t+        d|       |d}~ww xY wY d}~Pd}~ww xY w# t         j                  j"                  j$                  $ r}t!        d|       |d}~ww xY w)zGet a TGT Authentication request and initiates security context.

        This method will contact the Kerberos KDC in order of obtain a TGT.
        rQ   )	name_typezE# Stored credentials found, if password was given it will be ignored.z Credentials has expired: %szCredentials has expired: Nz-Unable to retrieve stored credentials error: z5# Attempt to retrieve credentials with given passwordinitiate)usager   z8Unable to retrieve credentials with the given password: zldap/ldapauthz# service principal: %s)namecredsflagsr]   z%Unable to initiate security context: z# initial client token: %s)"gssapirawnamesimport_namerU   r?   NameTypeuserCredentialsr   debuglifetime
exceptionsExpiredCredentialsErrorwarningacquirer   miscGSSError	_passwordacquire_cred_with_passwordr   RequirementFlagmutual_authenticationextended_errordelegate_to_peerr!   Namekerberos_principalr$   SecurityContextsumr%   step)
r9   rP   crederracquire_cred_resulterr2flags_lservice_principalservkinitial_client_tokens
             r1   _first_message_krbz2MySQLLdapSaslPasswordAuthPlugin._first_message_krb   s   
 JJ$$00NN!!&)V__5I5I 1 
		**,DLLWQ0 ""88""11""33
 %% $ : : /.0AB)K)K
 !))d#g,j
	Y
 $(88==?  	13GH##g ::((@@ Q=sCY'$'@%FGSPQ zz'' 	>>$CC5ITU&,jj&K&KNN))&1$ 'L '#
 +1-::??++ &NtfU 	V zz'' 	Y #H!NOUXX	Yss   )H F# 1K- #'H
6H  HH 'K*/K%AJ! K%!'KKKK%%K*-'L(L##L(tgt_auth_challengec                    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   rh   r%   rz   complete)r9   r   resps      r1   auth_continue_krbz1MySQLLdapSaslPasswordAuthPlugin.auth_continue_krb   sd      	-/ABxx}}/02D9/1B1BCTXX&&&&r<   messagec                    | j                   j                  st        d      t        j                  d|       t        j                  d| j                   j
                         	 | j                   j                  |      }t        j                  d|       t        j                  d|       t        d      }t        j                  d	|       | j                   j                  |d
      }t        j                  d|d   t        |d                |j                  S # t        j                  j                  j                  $ r}t        d|       |d}~ww xY w)aP  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 hssapi message from the server.

        Returns: bytearray closing handshake message to be send to the server.
        z"Security context is not completed.z# servers message: %sz# GSSAPI flags in use: %sz# unwraped: %sz!Unable to unwrap server message: Nz# unwrapped server message: %ss      z# message response: %sF)encryptz*# wrapped message response: %s, length: %dr   )r%   r   r   r   rh   actual_flagsunwrapra   rb   rj   BadMICErrorr   	bytearraywraplenr   )r9   r   unwrapedr|   responsewrapeds         r1   auth_accept_close_handshakez;MySQLLdapSaslPasswordAuthPlugin.auth_accept_close_handshake   s   2 xx  "#GHH,g60$((2G2GH	Uxxw/HLL)84 	5x@
 /0-x8x781Iq	N	
 ~~% zz$$00 	U #DSE!JKQTT	Us   #1D 'EEE	auth_datakwargsc           	         || _         | j                   j                         }t        j                  d|       || j                  vr@dj                  | j                  dd       }t        d| d| d| j                  d    d      d	| j                   v r| j                         S | j                   d
k(  rt        | _	        | j                         S )zThis method will prepare the fist message to the server.

        Returns bytes to send to the server as the first message.
        z read_method_name_from_server: %sz", "Nz The sasl authentication method "z4" requested from the server is not supported. Only "z" and "z" are supported   GSSAPIs   SCRAM-SHA-256)
_auth_datadecoder   rh   r   joinr   r   r   r   rY   )r9   r   r   auth_mechanismauth_mechanismss        r1   auth_responsez-MySQLLdapSaslPasswordAuthPlugin.auth_response)  s     $//17H!5!55$kk$*>*>s*CDO 2>2B C;;J:K L,,R01B  '**,,??..#)D ""$$r<   c                    | j                   st        d      | j                  | j                        }| j	                  |t        | j                        | j                        }t        j                  dt        |      j                                | j                  |d      }t        j                  dt        |      j                                | j                  |      j                         }t        j                  dt        |      j                                | j                  |d      }t        j                  dt        |      j                                dj                  d	| j                  | j                          d
| j"                   g      }t        j                  d|       t        d| j                  | j                          dj%                               j                         }dj                  || j&                  d| d
| j(                   g      }t        j                  d|       | j                  ||j%                               }	t        j                  dt        |	      j                                | j+                  ||	      }
t        j                  dt        |
      j                                t        | j                  ||j%                                     j                         | _        t        j                  d| j,                         dj                  d| d
| j(                   dt        |
      j                          g      }t        j                  d|       |j%                         S )a  This method generates the second message to the server

        Second message consist on the concatenation of the client and the
        server nonce, and cproof.

        c=<n,a=<user_name>>,r=<server_nonce>,p=<client_proof>
        where:
            <client_proof>: xor(<client_key>, <client_signature>)

            <client_key>: hmac(salted_password, b"Client Key")
            <client_signature>: hmac(<stored_key>, <auth_msg>)
            <stored_key>: h(<client_key>)
            <auth_msg>: <client_first_no_header>,<servers_first>,
                        c=<client_header>,r=<server_nonce>
            <client_first_no_header>: n=<username>r=<client_nonce>
        z"Missing authentication data (seed)zsalted_password: %ss
   Client Keyzclient_key: %szstored_key: %ss
   Server Keyzserver_key: %s,zn=r=zclient_first_no_header: %szn,a=zc=zauth_msg: %szclient_signature: %szclient_proof: %szserver_auth_var: %szp=zsecond_message: %s)r   r   rL   rp   rE   r   r    r"   r   rh   r   r   r;   r   r8   r   rU   r   r?   r&   r'   r2   r#   )r9   passwsalted_password
client_key
stored_key
server_keyclient_first_no_headerclient_headerauth_msgclient_signatureclient_proofmsgs               r1   _second_messagez/MySQLLdapSaslPasswordAuthPlugin._second_messageG  s   "  !EFF/((5)D4D4D*EtW*Io,F,M,M,OPZZ?
%y'<'C'C'EF))*5<<>
%y'<'C'C'EFZZ?
%y'<'C'C'EF!$T__T^^456T&&'("
 	13IJ!4??4>>2315<<>

&( 	 88&""]O$T&&'(	
 	^X.::j(//2CD+Y7G-H-O-O-QRyy-=>'<)@)G)G)IJ(JJz8??#45 

&( 	 	*D,@,@Ahh]O$T&&'(Y|,33567
 	)3/zz|r<   c                    |rt        |t        t        f      st        dt	        |             	 |j                         }|| _        |j                  d      \  }}}|j                  d      r"|j                  d      r|j                  d      st        d|       | j                  |v r+|dd | _        t        j                  d	| j                         nt        d
|       |dd | _        t        j                  d| j                  t        | j                               	 |dd }t        j                  d|       t!        |      | _        y# t        $ r t        d       dw xY w# t$        $ r}t        d|       |d}~ww xY w)zValidates first message from the server.

        Extracts the server's salt and iterations from the servers 1st response.
        First message from the server is in the form:
            <server_salt>,i=<iterations>
        zUnexpected server message: r   Nr   zs=zi=z$Incomplete reponse from the server: r   zserver_nonce: %sz:Unable to authenticate response: response not well formed zserver_salt: %s length: %sziterations: %sz-Unable to authenticate: iterations not found )rV   r   r-   r   reprr   r&   split
ValueError
startswithr   r'   r   rh   r    r   intr"   	Exception)r9   r&   servers_first_strr_server_nonces_salt	i_counterr|   s          r1   _validate_first_reponsez7MySQLLdapSaslPasswordAuthPlugin._validate_first_reponse  s    J}y%>P$Q #>tM?R>S!TUU	 - 4 4 6!2D0A0G0G0L-NFI ))$/$$T*''- 67H6IJ  . .qr 2DLL+T->->? L$%'  "!":(  !	

	!!"ILL)95!)nDO;  	 -.?-@A	<  	 ?@Q?RS	s#   ,E $+E, E),	F	5FF	servers_first_responsec                 D    | j                  |       | j                         S )zwreturn the second message from the client.

        Returns bytes to send to the server as the second message.
        )r   r   )r9   r   s     r1   auth_continuez-MySQLLdapSaslPasswordAuthPlugin.auth_continue  s"    
 	$$%;<##%%r<   servers_secondc                     |r/t        |t              rt        |      dk  s|j                  d      st	        d      |dd j                         }t        j                  d|       | j                  |k(  S )aX  Validates second message from the server.

        The client and the server prove to each other they have the same Auth
        variable.

        The second message from the server consist of the server's proof:
            server_proof = HMAC(<server_key>, <auth_msg>)
            where:
                <server_key>: hmac(<salted_password>, b"Server Key")
                <auth_msg>: <client_first_no_header>,<servers_first>,
                            c=<client_header>,r=<server_nonce>

        Our server_proof must be equal to the Auth variable send on this second
        response.
        r   s   v=z'The server's proof is not well formatedNzserver auth variable: %s)	rV   r   r   r   r   r   r   rh   r#   )r9   r   
server_vars      r1   _validate_second_reponsez8MySQLLdapSaslPasswordAuthPlugin._validate_second_reponse  sm    " ni8>"a'!,,U3 !JKK#AB'..0
/<##z11r<   servers_second_responsec                 <    | j                  |      st        d      y)zfinalize the authentication process.

        Raises InterfaceError if the ervers_second_response is invalid.

        Returns True in successful authentication False otherwise.
        z6Authentication failed: Unable to proof server identityT)r   r   )r9   r   s     r1   auth_finalizez-MySQLLdapSaslPasswordAuthPlugin.auth_finalize  s(     ,,-DE H  r<   c                      y)zPlugin official name.authentication_ldap_sasl_client r9   s    r1   r^   z$MySQLLdapSaslPasswordAuthPlugin.name  s     1r<   c                      y)z'Signals whether or not SSL is required.Fr   r   s    r1   requires_sslz,MySQLLdapSaslPasswordAuthPlugin.requires_ssl  s     r<   sockr   c                 v   t        j                  d|       |j                  d      | _         | j                  |fi |}|t        d      t        j                  d|t        |             |j                  |       |j                         }t        j                  d|       t        |      dk\  r|d   d	k(  r|d   d
k(  ry|dd }| j                  |      }|j                  |       |j                         }|d   dk(  r.|d   d
k(  r%| j                  |dd       r|j                         }t        |      S |dk(  r|d   t        k7  rd}t        j                  d       t        j                  d|d|dz           t        j                  dt        |             t        j                  d       d}	d}
|	s|
dk  rt        j                  dd|
dz   d       t        j                  d|       t        j                  d|d|dz           | j                  ||d       \  }}	t        j                  d|       |j                  |xs d       |j                         }|
dz  }
|	s|
dk  r|	st        d|
 d|       t        j                  d|t        |             | j                  ||d       }t        j                  d|t        |             |j                  |       |j                         }t        j                  d|       |j                         }t        j                  d |       t        |      S )!aS  Handles server's `auth switch request` response.

        Args:
            sock: Pointer to the socket connection.
            auth_data: Plugin provided data (extracted from a packet
                       representing an `auth switch request` response).
            kwargs: Custom configuration to be passed to the auth plugin
                    when invoked. The parameters defined here will override the ones
                    defined in the auth plugin itself.

        Returns:
            packet: Last server's response after back-and-forth
                    communication.
        z# auth_data: %sr!   NzGot a NULL auth responsez# request: %s size: %sz# server response packet: %s      r   =   v   r      z*# Continue with sasl GSSAPI authenticationz# response header: %sr   z# response size: %sz# Negotiate a service requestFr   z%s Attempt %s %sz--------------------z<< server response: %sz# response code: %sz >> response to server: %sr<   z'Unable to fulfill server request after z! attempts. Last server response: z0 last GSSAPI response from server: %s length: %dz* >> last response to server: %s length: %dz"<< final handshake from server: %sz<< ok packet from server: %s)r   rh   getr!   r   r   r   sendrecvr   r   r   r   r   r-   )r9   r   r   r   r   packetdec_response	cresponse
rcode_sizer   triesrz   	last_steps                r1   auth_switch_responsez4MySQLLdapSaslPasswordAuthPlugin.auth_switch_response  s   " 	&	2%+ZZ0G%H"%4%%i:6: !;<<-xXG		(3V<v;!q	S 0VAY"_!!":L**<8IIIi YY[FayCF1IO%%fQRj1!YY[FX V}W )#q	Z(?JLLEFLL0&9I:>2JKLL.F<LL89HE519/519hO5v>2F;KZ!^4LM!%!7!7z{8K!Lh94@		$+#&
 519 $=eW E77=h@  LLBF
 88
9LMILL<I
 IIi YY[FLL=vF YY[FLL7@V}r<   )2__name__
__module____qualname____doc__r   r
   rR   __annotations__r   r   r	   r   r   r   r   r    r!   r"   r   r#   r$   ra   rv   r%   rx   r&   r'   staticmethodr-   r2   r;   rE   rL   rY   r   r   boolr   r   r   r   r   r   r   r   r   propertyr^   r   r   r   r<   r1   r   r   A   sr   $ "LOT#YK $OX$"&L(3-&K!%K#%+/8C=/J%)OXc]))-K&++&-"&C		&#'M8C='"&L(3-&BU BE Be B B%e %5 %U %C u S U  3 3   ,G$HUO G$R'"*5/'	x$	%'025 2U 2h%% % 
%	%<J JX.U .t .`&E &e &2y 2T 26Y 4  1c 1 1 d  S!S.3S?BS	Sr<   )&r   r6   base64r   r   hashlibr   r   typingr   r   r	   r
   r   r   uuidr   authenticationr   errorsr   r   r   typesr   networkr   ra   ImportErrorutilsr   rH   r   rI   rO   r   AUTHENTICATION_PLUGIN_CLASSr   r   r<   r1   <module>r      s|   : '  '   F F  ' 5  % ? Oo O#  
	 	s   A0 0A?