U
    ¤�©j#7  ã                   @  s¶   d Z ddlmZ ddlZddlmZmZmZmZ ddl	m
Z
mZmZ ddlmZ ddlmZmZ dd	lmZmZmZmZmZmZmZmZ dd
lmZ er¤ddlmZ G dd„ dƒZdS )z5Implementing support for MySQL Authentication Pluginsé    )ÚannotationsN)ÚTYPE_CHECKINGÚAnyÚDictÚOptionalé   )ÚInterfaceErrorÚNotSupportedErrorÚget_exception)Úlogger)ÚMySQLAuthPluginÚget_auth_plugin)ÚAUTH_SWITCH_STATUSÚDEFAULT_CHARSET_IDÚDEFAULT_MAX_ALLOWED_PACKETÚ
ERR_STATUSÚEXCHANGE_FURTHER_STATUSÚ
MFA_STATUSÚ	OK_STATUSÚMySQLProtocol)ÚHandShakeType)ÚMySQLSocketc                   @  sæ   e Zd ZdZddœdd„Zeddœdd„ƒZed	dœd
d„ƒZede	fddddddddœdd„Z
d)ddddddœdd„Zddddœdd„Zddddœdd „Zd!d!d!d!dede	dddd"fdd#ddddddddddd$dd%dd&œd'd(„ZdS )*ÚMySQLAuthenticatorz$Implements the authentication phase.ÚNone)Úreturnc                 C  s(   d| _ i | _i | _d| _d| _d| _dS )zConstructor.Ú FN)Ú	_usernameÚ
_passwordsÚ_plugin_configÚ_ssl_enabledÚ_auth_strategyÚ_auth_plugin_class©Úself© r$   úB/tmp/pip-unpacked-wheel-d6bt0v6z/mysql/connector/authentication.pyÚ__init__:   s    zMySQLAuthenticator.__init__Úboolc                 C  s   | j S )z&Signals whether or not SSL is enabled.)r   r"   r$   r$   r%   Ússl_enabledC   s    zMySQLAuthenticator.ssl_enabledzDict[str, Any]c                 C  s   | j S )a  Custom arguments that are being provided to the authentication plugin when called.

        The parameters defined here will override the ones defined in the
        auth plugin itself.

        The plugin config is a read-only property - the plugin configuration
        provided when invoking `authenticate()` is recorded and can be queried
        by accessing this property.

        Returns:
            dict: The latest plugin configuration provided when invoking
                  `authenticate()`.
        )r   r"   r$   r$   r%   Úplugin_configH   s    z MySQLAuthenticator.plugin_configr   r   ÚstrzOptional[Dict[str, Any]]ÚintÚbytes)ÚsockÚhostÚssl_optionsÚcharsetÚclient_flagsÚmax_allowed_packetr   c           	   
   C  s    |dkri }t j|||d�}| |¡ t d¡ |j| d¡| d¡| d¡| dd¡| d	d¡| d
¡| d¡d�}t d¡ | ||¡ t d¡ d| _|S )aã  Sets up an SSL communication channel.

        Args:
            sock: Pointer to the socket connection.
            host: Server host name.
            ssl_options: SSL and TLS connection options (see
                         `network.MySQLSocket.build_ssl_context`).
            charset: Client charset (see [1]), only the lower 8-bits.
            client_flags: Integer representing client capabilities flags.
            max_allowed_packet: Maximum packet size.

        Returns:
            ssl_request_payload: Payload used to carry out SSL authentication.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_basic_character_set.html#a_protocol_character_set
        N)r0   r1   r2   zBuilding SSL contextÚcaÚcertÚkeyZverify_certFZverify_identityÚtls_versionsZtls_ciphersuites)Zssl_caZssl_certZssl_keyZssl_verify_certZssl_verify_identityr6   Ztls_cipher_suiteszSwitching to SSLzSSL has been enabledT)	r   Zmake_auth_sslÚsendr   ÚdebugZbuild_ssl_contextÚgetZswitch_to_sslr   )	r#   r-   r.   r/   r0   r1   r2   Zssl_request_payloadÚssl_contextr$   r$   r%   Ú	setup_sslY   s.    ý



ù


zMySQLAuthenticator.setup_sslNr   zOptional[str])Únew_strategy_nameÚstrategy_classÚusernameÚpassword_factorr   c                 C  sP   |dkr| j }|dkr| j}t d|¡ t||d�|| j |d¡| jd�| _dS )a®  Switches the authorization plugin.

        Args:
            new_strategy_name: New authorization plugin name to switch to.
            strategy_class: New authorization plugin class to switch to
                            (has higher precedence than the authorization plugin name).
            username: Username to be used - if not defined, the username
                      provided when `authentication()` was invoked is used.
            password_factor: Up to three levels of authentication (MFA) are allowed,
                             hence you can choose the password corresponding to the 1st,
                             2nd, or 3rd factor - 1st is the default.
        NzSwitching to strategy %s)Zplugin_nameÚauth_plugin_classr   )r(   )	r   r!   r   r8   r   r   r9   r(   r    )r#   r<   r=   r>   r?   r$   r$   r%   Ú_switch_auth_strategy’   s     ÿûz(MySQLAuthenticator._switch_auth_strategyzOptional[bytes])r-   Úpktr   c                 C  sÔ   d}|d t krÆ|| jkr"tdƒ‚t |¡\}}| j||d� t d|| jj	¡ | jj
||f| jŽ}|d tkrŽt |¡}| jj||f| jŽ}|d tkr¨t d¡ |S |d tkr¼t|ƒ‚|d7 }qt d¡ d	S )
a  Handles MFA (Multi-Factor Authentication) response.

        Up to three levels of authentication (MFA) are allowed.

        Args:
            sock: Pointer to the socket connection.
            pkt: MFA response.

        Returns:
            ok_packet: If last server's response is an OK packet.
            None: If last server's response isn't an OK packet and no ERROR was raised.

        Raises:
            InterfaceError: If got an invalid N factor.
            errors.ErrorTypes: If got an ERROR response.
        é   é   z5Failed Multi Factor Authentication (invalid N factor))r?   zMFA %i factor %szMFA completed succesfullyr   z"MFA terminated with a no ok packetN)r   r   r   r   Zparse_auth_next_factorrA   r   r8   r    ÚnameÚauth_switch_responser   r   Úparse_auth_more_dataÚauth_more_responser   r   r
   Úwarning)r#   r-   rB   Zn_factorr<   Ú	auth_datar$   r$   r%   Ú_mfa_n_factor´   s>    
ÿ ÿÿ
 ÿÿ


z MySQLAuthenticator._mfa_n_factorc                 C  s   |d t kr t|ƒdkr tdƒ‚|d t krbt d¡ t |¡\}}|  |¡ | jj	||f| j
Ž}|d tkr–t d¡ t |¡}| jj||f| j
Ž}|d tkr¶t d| jj¡ |S |d tkrèt d¡ t d| jj¡ |  ||¡S |d tkrüt|ƒ‚d	S )
aý  Handles server's response.

        Args:
            sock: Pointer to the socket connection.
            pkt: Server's response after completing the `HandShakeResponse`.

        Returns:
            ok_packet: If last server's response is an OK packet.
            None: If last server's response isn't an OK packet and no ERROR was raised.

        Raises:
            errors.ErrorTypes: If got an ERROR response.
            NotSupportedError: If got Authentication with old (insecure) passwords.
        rD   é   z‡Authentication with old (insecure) passwords is not supported. For more information, lookup Password Hashing in the latest MySQL manualz+Server's response is an auth switch requestzExchanging further packetsz%s completed succesfullyz$Starting multi-factor authenticationzMFA 1 factor %sN)r   Úlenr	   r   r8   r   Zparse_auth_switch_requestrA   r    rF   r   r   rG   rH   r   rE   r   rK   r   r
   )r#   r-   rB   r<   rJ   r$   r$   r%   Ú_handle_server_responseê   sB    ÿ

 ÿÿ

 ÿÿ
z*MySQLAuthenticator._handle_server_responser   Fr   zOptional[Dict[str, str]]r   )r-   Ú	handshaker>   Ú	password1Ú	password2Ú	password3Údatabaser0   r1   r2   Úauth_pluginr@   Ú
conn_attrsÚis_change_user_requestr)   r   c                 K  sž   || _ |||dœ| _t |¡| _|| _tj||||||	|
||||| j| j	d�\}| _
|r\dnd}|j|f|žŽ  t| ¡ ƒ}|  ||¡}|dkrštdƒd‚|S )a  Performs the authentication phase.

        During re-authentication you must set `is_change_user_request` to True.

        Args:
            sock: Pointer to the socket connection.
            handshake: Initial handshake.
            username: Account's username.
            password1: Account's password factor 1.
            password2: Account's password factor 2.
            password3: Account's password factor 3.
            database: Initial database name for the connection.
            charset: Client charset (see [1]), only the lower 8-bits.
            client_flags: Integer representing client capabilities flags.
            max_allowed_packet: Maximum packet size.
            auth_plugin: Authorization plugin name.
            auth_plugin_class: Authorization plugin class (has higher precedence
                               than the authorization plugin name).
            conn_attrs: Connection attributes.
            is_change_user_request: Whether is a `change user request` operation or not.
            plugin_config: 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:
            ok_packet: OK packet.

        Raises:
            InterfaceError: If OK packet is NULL.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_basic_character_set.html#a_protocol_character_set
        )r   rC   é   )rO   r>   ÚpasswordrS   r0   r1   r2   rT   r@   rU   rV   r(   r)   )r   r   )NNNzGot a NULL ok_pkt)r   r   ÚcopyÚdeepcopyr   r!   r   Z	make_authr(   r)   r    r7   r,   ÚrecvrN   r   )r#   r-   rO   r>   rP   rQ   rR   rS   r0   r1   r2   rT   r@   rU   rV   r)   Zresponse_payloadZ	send_argsrB   Zok_pktr$   r$   r%   Úauthenticate!  s4    5ó
zMySQLAuthenticator.authenticate)NNr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r&   Úpropertyr(   r)   r   r   r;   rA   rK   rN   r\   r$   r$   r$   r%   r   7   s:   	ù<   û"6;ñr   )r`   Ú
__future__r   rY   Útypingr   r   r   r   Úerrorsr   r	   r
   r   Zpluginsr   r   Úprotocolr   r   r   r   r   r   r   r   Útypesr   Únetworkr   r   r$   r$   r$   r%   Ú<module>   s   (
