Search in sources :

Example 1 with CachingSha2PasswordPlugin

use of com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin in project ABC by RuiPinto96274.

the class ConnectionRegressionTest method testCachingSha2PasswordPlugin.

/**
 * Test for caching_sha2_password authentication.
 *
 * @throws Exception
 */
@Test
public void testCachingSha2PasswordPlugin() throws Exception {
    assumeTrue(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 3), "Requires MySQL 8.0.3+.");
    assumeTrue((((MysqlConnection) this.conn).getSession().getServerSession().getCapabilities().getCapabilityFlags() & NativeServerSession.CLIENT_SSL) != 0, "This test requires server with SSL support.");
    assumeTrue(supportsTestCertificates(this.stmt), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
    assumeTrue(pluginIsActive(this.stmt, "caching_sha2_password"), "caching_sha2_password plugin required to run this test");
    String trustStorePath = "src/test/config/ssl-test-certs/ca-truststore";
    System.setProperty("javax.net.ssl.keyStore", trustStorePath);
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    System.setProperty("javax.net.ssl.trustStore", trustStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    boolean withCachingTestRsaKeys = supportsTestCachingSha2PasswordKeys(this.stmt);
    try {
        // create user with long password and caching_sha2_password auth
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET @current_old_passwords = @@global.old_passwords");
        }
        createUser(this.stmt, "'wl11060user'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060user'@'%'");
        createUser(this.stmt, "'wl11060nopassword'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060nopassword'@'%'");
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords= 2");
            this.stmt.executeUpdate("SET SESSION old_passwords= 2");
        }
        this.stmt.executeUpdate(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'wl11060user'@'%' IDENTIFIED BY 'pwd'" : "set password for 'wl11060user'@'%' = PASSWORD('pwd')");
        this.stmt.executeUpdate("flush privileges");
        final Properties propsNoRetrieval = new Properties();
        propsNoRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsNoRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        final Properties propsNoRetrievalNoPassword = new Properties();
        propsNoRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        final Properties propsAllowRetrieval = new Properties();
        propsAllowRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsAllowRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        propsAllowRetrieval.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        final Properties propsAllowRetrievalNoPassword = new Properties();
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        // 1. with client-default MysqlNativePasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        // 1.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 1.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2. with client-default CachingSha2PasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        // 2.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        // wl11060user scramble is cached now, thus authenticated successfully
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                // now, with full authentication, it's failed
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3. with serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        // 3.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsAllowRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3.2. Runtime setServerRSAPublicKeyFile must be denied
        if (withCachingTestRsaKeys) {
            final Connection c2 = getConnectionWithProps(dbUrl, propsNoRetrieval);
            assertThrows(PropertyNotModifiableException.class, "Dynamic change of ''serverRSAPublicKeyFile'' is not allowed.", new Callable<Void>() {

                public Void call() throws Exception {
                    ((JdbcConnection) c2).getPropertySet().getProperty(PropertyKey.serverRSAPublicKeyFile).setValue("src/test/config/ssl-test-certs/mykey.pub");
                    return null;
                }
            });
            c2.close();
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        // 3.4. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 4. with wrong serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        // 4.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        // 4.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
    } finally {
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords = @current_old_passwords");
        }
    }
}
Also used : ReplicationConnection(com.mysql.cj.jdbc.ha.ReplicationConnection) MysqlPooledConnection(com.mysql.cj.jdbc.MysqlPooledConnection) SuspendableXAConnection(com.mysql.cj.jdbc.SuspendableXAConnection) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) MysqlConnection(com.mysql.cj.MysqlConnection) Properties(java.util.Properties) MysqlNativePasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin) CachingSha2PasswordPlugin(com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) SQLTransientException(java.sql.SQLTransientException) InvocationTargetException(java.lang.reflect.InvocationTargetException) XAException(javax.transaction.xa.XAException) SocketException(java.net.SocketException) SQLClientInfoException(java.sql.SQLClientInfoException) SQLException(java.sql.SQLException) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) PasswordExpiredException(com.mysql.cj.exceptions.PasswordExpiredException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) SQLNonTransientConnectionException(java.sql.SQLNonTransientConnectionException) CommunicationsException(com.mysql.cj.jdbc.exceptions.CommunicationsException) CertificateException(java.security.cert.CertificateException) ClosedOnExpiredPasswordException(com.mysql.cj.exceptions.ClosedOnExpiredPasswordException) PropertyNotModifiableException(com.mysql.cj.exceptions.PropertyNotModifiableException) Test(org.junit.jupiter.api.Test)

Example 2 with CachingSha2PasswordPlugin

use of com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin in project aws-mysql-jdbc by awslabs.

the class NativeAuthenticationProvider method loadAuthenticationPlugins.

/**
 * Fill the authentication plugins map.
 *
 * Starts by filling the map with instances of the built-in authentication plugins. Then creates instances of plugins listed in the "authenticationPlugins"
 * connection property and adds them to the map too.
 *
 * The key for the map entry is got by {@link AuthenticationPlugin#getProtocolPluginName()} thus it is possible to replace built-in plugins with custom
 * implementations. To do it, the custom plugin should return one of the values "mysql_native_password", "mysql_clear_password", "sha256_password",
 * "caching_sha2_password", "mysql_old_password", "authentication_ldap_sasl_client" or "authentication_kerberos_client" from its own getProtocolPluginName()
 * method.
 */
@SuppressWarnings("unchecked")
private void loadAuthenticationPlugins() {
    // default plugin
    RuntimeProperty<String> defaultAuthenticationPluginProp = this.propertySet.getStringProperty(PropertyKey.defaultAuthenticationPlugin);
    String defaultAuthenticationPluginValue = defaultAuthenticationPluginProp.getValue();
    if (defaultAuthenticationPluginValue == null || "".equals(defaultAuthenticationPluginValue.trim())) {
        throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadDefaultAuthenticationPlugin", new Object[] { defaultAuthenticationPluginValue }), getExceptionInterceptor());
    }
    // disabled plugins
    String disabledPlugins = this.propertySet.getStringProperty(PropertyKey.disabledAuthenticationPlugins).getValue();
    List<String> disabledAuthenticationPlugins;
    if (disabledPlugins != null && !"".equals(disabledPlugins)) {
        disabledAuthenticationPlugins = StringUtils.split(disabledPlugins, ",", true);
    } else {
        disabledAuthenticationPlugins = Collections.EMPTY_LIST;
    }
    this.authenticationPlugins = new HashMap<>();
    List<AuthenticationPlugin<NativePacketPayload>> pluginsToInit = new LinkedList<>();
    // built-in plugins
    pluginsToInit.add(new Sha256PasswordPlugin());
    pluginsToInit.add(new CachingSha2PasswordPlugin());
    pluginsToInit.add(new MysqlOldPasswordPlugin());
    pluginsToInit.add(new AuthenticationLdapSaslClientPlugin());
    pluginsToInit.add(new AuthenticationKerberosClient());
    pluginsToInit.add(new AuthenticationOciClient());
    final boolean useAwsIam = this.propertySet.getBooleanProperty(PropertyKey.useAwsIam).getValue();
    if (useAwsIam) {
        try {
            Class.forName("software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider");
        } catch (ClassNotFoundException ex) {
            throw ExceptionFactory.createException(Messages.getString("AuthenticationAwsIamPlugin.MissingSDK"));
        }
        final String host = this.protocol.getSocketConnection().getHost();
        final int port = this.protocol.getSocketConnection().getPort();
        final AwsIamAuthenticationTokenHelper tokenHelper = new AwsIamAuthenticationTokenHelper(host, port, this.propertySet.getStringProperty(PropertyKey.logger).getStringValue());
        pluginsToInit.add(new AwsIamAuthenticationPlugin(tokenHelper));
        pluginsToInit.add(new AwsIamClearAuthenticationPlugin(tokenHelper));
        final String defaultPluginClassName = this.propertySet.getStringProperty(PropertyKey.defaultAuthenticationPlugin).getPropertyDefinition().getDefaultValue();
        if (defaultAuthenticationPluginValue.equals(defaultPluginClassName)) {
            defaultAuthenticationPluginValue = AwsIamAuthenticationPlugin.class.getName();
        }
    } else {
        pluginsToInit.add(new MysqlNativePasswordPlugin());
        pluginsToInit.add(new MysqlClearPasswordPlugin());
    }
    // plugins from authenticationPluginClasses connection parameter
    String authenticationPluginClasses = this.propertySet.getStringProperty(PropertyKey.authenticationPlugins).getValue();
    if (authenticationPluginClasses != null && !"".equals(authenticationPluginClasses.trim())) {
        List<String> pluginsToCreate = StringUtils.split(authenticationPluginClasses, ",", true);
        for (String className : pluginsToCreate) {
            try {
                pluginsToInit.add((AuthenticationPlugin<NativePacketPayload>) Class.forName(className).newInstance());
            } catch (Throwable t) {
                throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadAuthenticationPlugin", new Object[] { className }), t, this.exceptionInterceptor);
            }
        }
    }
    // add plugin instances
    boolean defaultFound = false;
    for (AuthenticationPlugin<NativePacketPayload> plugin : pluginsToInit) {
        String pluginProtocolName = plugin.getProtocolPluginName();
        String pluginClassName = plugin.getClass().getName();
        boolean disabledByProtocolName = disabledAuthenticationPlugins.contains(pluginProtocolName);
        boolean disabledByClassName = disabledAuthenticationPlugins.contains(pluginClassName);
        if (disabledByProtocolName || disabledByClassName) {
            // check if the default plugin is disabled
            if (!defaultFound && (defaultAuthenticationPluginValue.equals(pluginProtocolName) || defaultAuthenticationPluginValue.equals(pluginClassName))) {
                throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadDisabledAuthenticationPlugin", new Object[] { disabledByClassName ? pluginClassName : pluginProtocolName }), getExceptionInterceptor());
            }
        } else {
            this.authenticationPlugins.put(pluginProtocolName, plugin);
            if (!defaultFound && (defaultAuthenticationPluginValue.equals(pluginProtocolName) || defaultAuthenticationPluginValue.equals(pluginClassName))) {
                this.clientDefaultAuthenticationPluginName = pluginProtocolName;
                this.clientDefaultAuthenticationPluginExplicitelySet = defaultAuthenticationPluginProp.isExplicitlySet();
                defaultFound = true;
            }
        }
    }
    // check if the default plugin is listed
    if (!defaultFound) {
        throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.DefaultAuthenticationPluginIsNotListed", new Object[] { defaultAuthenticationPluginValue }), getExceptionInterceptor());
    }
}
Also used : MysqlOldPasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlOldPasswordPlugin) AuthenticationKerberosClient(com.mysql.cj.protocol.a.authentication.AuthenticationKerberosClient) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) AuthenticationLdapSaslClientPlugin(com.mysql.cj.protocol.a.authentication.AuthenticationLdapSaslClientPlugin) Sha256PasswordPlugin(com.mysql.cj.protocol.a.authentication.Sha256PasswordPlugin) AuthenticationOciClient(com.mysql.cj.protocol.a.authentication.AuthenticationOciClient) MysqlClearPasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin) AwsIamAuthenticationTokenHelper(com.mysql.cj.protocol.a.authentication.AwsIamAuthenticationTokenHelper) LinkedList(java.util.LinkedList) AwsIamClearAuthenticationPlugin(com.mysql.cj.protocol.a.authentication.AwsIamClearAuthenticationPlugin) AuthenticationPlugin(com.mysql.cj.protocol.AuthenticationPlugin) AwsIamClearAuthenticationPlugin(com.mysql.cj.protocol.a.authentication.AwsIamClearAuthenticationPlugin) AwsIamAuthenticationPlugin(com.mysql.cj.protocol.a.authentication.AwsIamAuthenticationPlugin) AwsIamAuthenticationPlugin(com.mysql.cj.protocol.a.authentication.AwsIamAuthenticationPlugin) CachingSha2PasswordPlugin(com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin) MysqlNativePasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin)

Example 3 with CachingSha2PasswordPlugin

use of com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin in project aws-mysql-jdbc by awslabs.

the class ConnectionRegressionTest method testCachingSha2PasswordPlugin.

/**
 * Test for caching_sha2_password authentication.
 *
 * @throws Exception
 */
@Test
public void testCachingSha2PasswordPlugin() throws Exception {
    assumeTrue(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 3), "Requires MySQL 8.0.3+.");
    assumeTrue((((MysqlConnection) this.conn).getSession().getServerSession().getCapabilities().getCapabilityFlags() & NativeServerSession.CLIENT_SSL) != 0, "This test requires server with SSL support.");
    assumeTrue(supportsTestCertificates(this.stmt), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
    assumeTrue(pluginIsActive(this.stmt, "caching_sha2_password"), "caching_sha2_password plugin required to run this test");
    String trustStorePath = "src/test/config/ssl-test-certs/ca-truststore";
    System.setProperty("javax.net.ssl.keyStore", trustStorePath);
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    System.setProperty("javax.net.ssl.trustStore", trustStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    boolean withCachingTestRsaKeys = supportsTestCachingSha2PasswordKeys(this.stmt);
    try {
        // create user with long password and caching_sha2_password auth
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET @current_old_passwords = @@global.old_passwords");
        }
        createUser(this.stmt, "'wl11060user'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060user'@'%'");
        createUser(this.stmt, "'wl11060nopassword'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060nopassword'@'%'");
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords= 2");
            this.stmt.executeUpdate("SET SESSION old_passwords= 2");
        }
        this.stmt.executeUpdate(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'wl11060user'@'%' IDENTIFIED BY 'pwd'" : "set password for 'wl11060user'@'%' = PASSWORD('pwd')");
        this.stmt.executeUpdate("flush privileges");
        final Properties propsNoRetrieval = new Properties();
        propsNoRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsNoRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        final Properties propsNoRetrievalNoPassword = new Properties();
        propsNoRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        final Properties propsAllowRetrieval = new Properties();
        propsAllowRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsAllowRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        propsAllowRetrieval.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        final Properties propsAllowRetrievalNoPassword = new Properties();
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        // 1. with client-default MysqlNativePasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        // 1.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 1.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2. with client-default CachingSha2PasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        // 2.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        // wl11060user scramble is cached now, thus authenticated successfully
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                // now, with full authentication, it's failed
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3. with serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        // 3.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsAllowRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3.2. Runtime setServerRSAPublicKeyFile must be denied
        if (withCachingTestRsaKeys) {
            final Connection c2 = getConnectionWithProps(dbUrl, propsNoRetrieval);
            assertThrows(PropertyNotModifiableException.class, "Dynamic change of ''serverRSAPublicKeyFile'' is not allowed.", new Callable<Void>() {

                public Void call() throws Exception {
                    ((JdbcConnection) c2).getPropertySet().getProperty(PropertyKey.serverRSAPublicKeyFile).setValue("src/test/config/ssl-test-certs/mykey.pub");
                    return null;
                }
            });
            c2.close();
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        // 3.4. over SSL
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 4. with wrong serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        // 4.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        // 4.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrieval.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.REQUIRED.name());
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
    } finally {
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords = @current_old_passwords");
        }
    }
}
Also used : ReplicationConnection(com.mysql.cj.jdbc.ha.ReplicationConnection) MysqlPooledConnection(com.mysql.cj.jdbc.MysqlPooledConnection) SuspendableXAConnection(com.mysql.cj.jdbc.SuspendableXAConnection) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) MysqlConnection(com.mysql.cj.MysqlConnection) Properties(java.util.Properties) MysqlNativePasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin) CachingSha2PasswordPlugin(com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) SQLTransientException(java.sql.SQLTransientException) InvocationTargetException(java.lang.reflect.InvocationTargetException) XAException(javax.transaction.xa.XAException) SocketException(java.net.SocketException) SQLClientInfoException(java.sql.SQLClientInfoException) SQLException(java.sql.SQLException) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) PasswordExpiredException(com.mysql.cj.exceptions.PasswordExpiredException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) SQLNonTransientConnectionException(java.sql.SQLNonTransientConnectionException) CommunicationsException(com.mysql.cj.jdbc.exceptions.CommunicationsException) CertificateException(java.security.cert.CertificateException) ClosedOnExpiredPasswordException(com.mysql.cj.exceptions.ClosedOnExpiredPasswordException) PropertyNotModifiableException(com.mysql.cj.exceptions.PropertyNotModifiableException) Test(org.junit.jupiter.api.Test)

Example 4 with CachingSha2PasswordPlugin

use of com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin in project JavaSegundasQuintas by ecteruel.

the class NativeAuthenticationProvider method loadAuthenticationPlugins.

/**
 * Fill the authentication plugins map.
 *
 * Starts by filling the map with instances of the built-in authentication plugins. Then creates instances of plugins listed in the "authenticationPlugins"
 * connection property and adds them to the map too.
 *
 * The key for the map entry is got by {@link AuthenticationPlugin#getProtocolPluginName()} thus it is possible to replace built-in plugins with custom
 * implementations. To do it, the custom plugin should return one of the values "mysql_native_password", "mysql_clear_password", "sha256_password",
 * "caching_sha2_password", "mysql_old_password", "authentication_ldap_sasl_client" or "authentication_kerberos_client" from its own getProtocolPluginName()
 * method.
 */
@SuppressWarnings("unchecked")
private void loadAuthenticationPlugins() {
    // default plugin
    RuntimeProperty<String> defaultAuthenticationPluginProp = this.propertySet.getStringProperty(PropertyKey.defaultAuthenticationPlugin);
    String defaultAuthenticationPluginValue = defaultAuthenticationPluginProp.getValue();
    if (defaultAuthenticationPluginValue == null || "".equals(defaultAuthenticationPluginValue.trim())) {
        throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadDefaultAuthenticationPlugin", new Object[] { defaultAuthenticationPluginValue }), getExceptionInterceptor());
    }
    // disabled plugins
    String disabledPlugins = this.propertySet.getStringProperty(PropertyKey.disabledAuthenticationPlugins).getValue();
    List<String> disabledAuthenticationPlugins;
    if (disabledPlugins != null && !"".equals(disabledPlugins)) {
        disabledAuthenticationPlugins = StringUtils.split(disabledPlugins, ",", true);
    } else {
        disabledAuthenticationPlugins = Collections.EMPTY_LIST;
    }
    this.authenticationPlugins = new HashMap<>();
    List<AuthenticationPlugin<NativePacketPayload>> pluginsToInit = new LinkedList<>();
    // built-in plugins
    pluginsToInit.add(new MysqlNativePasswordPlugin());
    pluginsToInit.add(new MysqlClearPasswordPlugin());
    pluginsToInit.add(new Sha256PasswordPlugin());
    pluginsToInit.add(new CachingSha2PasswordPlugin());
    pluginsToInit.add(new MysqlOldPasswordPlugin());
    pluginsToInit.add(new AuthenticationLdapSaslClientPlugin());
    pluginsToInit.add(new AuthenticationKerberosClient());
    pluginsToInit.add(new AuthenticationOciClient());
    // plugins from authenticationPluginClasses connection parameter
    String authenticationPluginClasses = this.propertySet.getStringProperty(PropertyKey.authenticationPlugins).getValue();
    if (authenticationPluginClasses != null && !"".equals(authenticationPluginClasses.trim())) {
        List<String> pluginsToCreate = StringUtils.split(authenticationPluginClasses, ",", true);
        for (String className : pluginsToCreate) {
            try {
                pluginsToInit.add((AuthenticationPlugin<NativePacketPayload>) Class.forName(className).newInstance());
            } catch (Throwable t) {
                throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadAuthenticationPlugin", new Object[] { className }), t, this.exceptionInterceptor);
            }
        }
    }
    // add plugin instances
    boolean defaultFound = false;
    for (AuthenticationPlugin<NativePacketPayload> plugin : pluginsToInit) {
        String pluginProtocolName = plugin.getProtocolPluginName();
        String pluginClassName = plugin.getClass().getName();
        boolean disabledByProtocolName = disabledAuthenticationPlugins.contains(pluginProtocolName);
        boolean disabledByClassName = disabledAuthenticationPlugins.contains(pluginClassName);
        if (disabledByProtocolName || disabledByClassName) {
            // check if the default plugin is disabled
            if (!defaultFound && (defaultAuthenticationPluginValue.equals(pluginProtocolName) || defaultAuthenticationPluginValue.equals(pluginClassName))) {
                throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadDisabledAuthenticationPlugin", new Object[] { disabledByClassName ? pluginClassName : pluginProtocolName }), getExceptionInterceptor());
            }
        } else {
            this.authenticationPlugins.put(pluginProtocolName, plugin);
            if (!defaultFound && (defaultAuthenticationPluginValue.equals(pluginProtocolName) || defaultAuthenticationPluginValue.equals(pluginClassName))) {
                this.clientDefaultAuthenticationPluginName = pluginProtocolName;
                this.clientDefaultAuthenticationPluginExplicitelySet = defaultAuthenticationPluginProp.isExplicitlySet();
                defaultFound = true;
            }
        }
    }
    // check if the default plugin is listed
    if (!defaultFound) {
        throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.DefaultAuthenticationPluginIsNotListed", new Object[] { defaultAuthenticationPluginValue }), getExceptionInterceptor());
    }
}
Also used : MysqlClearPasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin) MysqlOldPasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlOldPasswordPlugin) AuthenticationOciClient(com.mysql.cj.protocol.a.authentication.AuthenticationOciClient) AuthenticationKerberosClient(com.mysql.cj.protocol.a.authentication.AuthenticationKerberosClient) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) LinkedList(java.util.LinkedList) AuthenticationPlugin(com.mysql.cj.protocol.AuthenticationPlugin) AuthenticationLdapSaslClientPlugin(com.mysql.cj.protocol.a.authentication.AuthenticationLdapSaslClientPlugin) Sha256PasswordPlugin(com.mysql.cj.protocol.a.authentication.Sha256PasswordPlugin) MysqlNativePasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin) CachingSha2PasswordPlugin(com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin)

Example 5 with CachingSha2PasswordPlugin

use of com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin in project JavaSegundasQuintas by ecteruel.

the class ConnectionRegressionTest method testCachingSha2PasswordPlugin.

/**
 * Test for caching_sha2_password authentication.
 *
 * @throws Exception
 */
@Test
public void testCachingSha2PasswordPlugin() throws Exception {
    assumeTrue(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 3), "Requires MySQL 8.0.3+.");
    assumeTrue((((MysqlConnection) this.conn).getSession().getServerSession().getCapabilities().getCapabilityFlags() & NativeServerSession.CLIENT_SSL) != 0, "This test requires server with SSL support.");
    assumeTrue(supportsTestCertificates(this.stmt), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
    assumeTrue(pluginIsActive(this.stmt, "caching_sha2_password"), "caching_sha2_password plugin required to run this test");
    String trustStorePath = "src/test/config/ssl-test-certs/ca-truststore";
    System.setProperty("javax.net.ssl.keyStore", trustStorePath);
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    System.setProperty("javax.net.ssl.trustStore", trustStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    boolean withCachingTestRsaKeys = supportsTestCachingSha2PasswordKeys(this.stmt);
    try {
        // create user with long password and caching_sha2_password auth
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET @current_old_passwords = @@global.old_passwords");
        }
        createUser(this.stmt, "'wl11060user'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060user'@'%'");
        createUser(this.stmt, "'wl11060nopassword'@'%'", "identified WITH caching_sha2_password");
        this.stmt.executeUpdate("grant all on *.* to 'wl11060nopassword'@'%'");
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords= 2");
            this.stmt.executeUpdate("SET SESSION old_passwords= 2");
        }
        this.stmt.executeUpdate(((MysqlConnection) this.conn).getSession().versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'wl11060user'@'%' IDENTIFIED BY 'pwd'" : "set password for 'wl11060user'@'%' = PASSWORD('pwd')");
        this.stmt.executeUpdate("flush privileges");
        final Properties propsNoRetrieval = new Properties();
        propsNoRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsNoRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        final Properties propsNoRetrievalNoPassword = new Properties();
        propsNoRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        final Properties propsAllowRetrieval = new Properties();
        propsAllowRetrieval.setProperty(PropertyKey.USER.getKeyName(), "wl11060user");
        propsAllowRetrieval.setProperty(PropertyKey.PASSWORD.getKeyName(), "pwd");
        propsAllowRetrieval.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        final Properties propsAllowRetrievalNoPassword = new Properties();
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.USER.getKeyName(), "wl11060nopassword");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.PASSWORD.getKeyName(), "");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
        // 1. with client-default MysqlNativePasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), MysqlNativePasswordPlugin.class.getName());
        // 1.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 1.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2. with client-default CachingSha2PasswordPlugin
        propsNoRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsNoRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrieval.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.defaultAuthenticationPlugin.getKeyName(), CachingSha2PasswordPlugin.class.getName());
        // 2.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        // wl11060user scramble is cached now, thus authenticated successfully
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Public Key Retrieval is not allowed", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                // now, with full authentication, it's failed
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 2.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3. with serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "src/test/config/ssl-test-certs/mykey.pub");
        // 3.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        if (withCachingTestRsaKeys) {
            assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", false);
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsAllowRetrieval);
                    return null;
                }
            });
        }
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 3.2. Runtime setServerRSAPublicKeyFile must be denied
        if (withCachingTestRsaKeys) {
            final Connection c2 = getConnectionWithProps(dbUrl, propsNoRetrieval);
            assertThrows(PropertyNotModifiableException.class, "Dynamic change of ''serverRSAPublicKeyFile'' is not allowed.", new Callable<Void>() {

                public Void call() throws Exception {
                    ((JdbcConnection) c2).getPropertySet().getProperty(PropertyKey.serverRSAPublicKeyFile).setValue("src/test/config/ssl-test-certs/mykey.pub");
                    return null;
                }
            });
            c2.close();
        } else {
            assertThrows(SQLException.class, "Access denied for user 'wl11060user'.*", new Callable<Void>() {

                @SuppressWarnings("synthetic-access")
                public Void call() throws Exception {
                    getConnectionWithProps(dbUrl, propsNoRetrieval);
                    return null;
                }
            });
        }
        // 3.4. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsNoRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsNoRetrievalNoPassword, "wl11060nopassword", false);
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertCurrentUser(dbUrl, propsAllowRetrieval, "wl11060user", true);
        assertCurrentUser(dbUrl, propsAllowRetrievalNoPassword, "wl11060nopassword", false);
        // 4. with wrong serverRSAPublicKeyFile specified
        propsNoRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrieval.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.serverRSAPublicKeyFile.getKeyName(), "unexistant/dummy.pub");
        // 4.1. RSA
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "false");
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        // to ensure that we'll go through the full authentication
        this.stmt.executeUpdate("flush privileges");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        // 4.2. over SSL
        propsNoRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.useSSL.getKeyName(), "true");
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "false");
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key 'unexistant/dummy.pub'.*", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
        propsNoRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsNoRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrieval.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        propsAllowRetrievalNoPassword.setProperty(PropertyKey.paranoid.getKeyName(), "true");
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsNoRetrievalNoPassword);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrieval);
                return null;
            }
        });
        assertThrows(SQLException.class, "Unable to read public key ", new Callable<Void>() {

            @SuppressWarnings("synthetic-access")
            public Void call() throws Exception {
                getConnectionWithProps(dbUrl, propsAllowRetrievalNoPassword);
                return null;
            }
        });
    } finally {
        if (!((MysqlConnection) this.conn).getSession().versionMeetsMinimum(8, 0, 5)) {
            this.stmt.executeUpdate("SET GLOBAL old_passwords = @current_old_passwords");
        }
    }
}
Also used : ReplicationConnection(com.mysql.cj.jdbc.ha.ReplicationConnection) MysqlPooledConnection(com.mysql.cj.jdbc.MysqlPooledConnection) SuspendableXAConnection(com.mysql.cj.jdbc.SuspendableXAConnection) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) MysqlConnection(com.mysql.cj.MysqlConnection) Properties(java.util.Properties) MysqlNativePasswordPlugin(com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin) CachingSha2PasswordPlugin(com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) SQLTransientException(java.sql.SQLTransientException) InvocationTargetException(java.lang.reflect.InvocationTargetException) XAException(javax.transaction.xa.XAException) SocketException(java.net.SocketException) SQLClientInfoException(java.sql.SQLClientInfoException) SQLException(java.sql.SQLException) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) PasswordExpiredException(com.mysql.cj.exceptions.PasswordExpiredException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) SQLNonTransientConnectionException(java.sql.SQLNonTransientConnectionException) CommunicationsException(com.mysql.cj.jdbc.exceptions.CommunicationsException) CertificateException(java.security.cert.CertificateException) ClosedOnExpiredPasswordException(com.mysql.cj.exceptions.ClosedOnExpiredPasswordException) PropertyNotModifiableException(com.mysql.cj.exceptions.PropertyNotModifiableException) Test(org.junit.jupiter.api.Test)

Aggregations

CachingSha2PasswordPlugin (com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin)6 MysqlNativePasswordPlugin (com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin)6 MysqlConnection (com.mysql.cj.MysqlConnection)3 ClosedOnExpiredPasswordException (com.mysql.cj.exceptions.ClosedOnExpiredPasswordException)3 PasswordExpiredException (com.mysql.cj.exceptions.PasswordExpiredException)3 PropertyNotModifiableException (com.mysql.cj.exceptions.PropertyNotModifiableException)3 WrongArgumentException (com.mysql.cj.exceptions.WrongArgumentException)3 JdbcConnection (com.mysql.cj.jdbc.JdbcConnection)3 MysqlPooledConnection (com.mysql.cj.jdbc.MysqlPooledConnection)3 MysqlXAConnection (com.mysql.cj.jdbc.MysqlXAConnection)3 SuspendableXAConnection (com.mysql.cj.jdbc.SuspendableXAConnection)3 CommunicationsException (com.mysql.cj.jdbc.exceptions.CommunicationsException)3 ReplicationConnection (com.mysql.cj.jdbc.ha.ReplicationConnection)3 AuthenticationPlugin (com.mysql.cj.protocol.AuthenticationPlugin)3 AuthenticationKerberosClient (com.mysql.cj.protocol.a.authentication.AuthenticationKerberosClient)3 AuthenticationLdapSaslClientPlugin (com.mysql.cj.protocol.a.authentication.AuthenticationLdapSaslClientPlugin)3 AuthenticationOciClient (com.mysql.cj.protocol.a.authentication.AuthenticationOciClient)3 MysqlClearPasswordPlugin (com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin)3 MysqlOldPasswordPlugin (com.mysql.cj.protocol.a.authentication.MysqlOldPasswordPlugin)3 IOException (java.io.IOException)3