Search in sources :

Example 1 with XDevAPIError

use of com.mysql.cj.xdevapi.XDevAPIError in project aws-mysql-jdbc by awslabs.

the class XAuthenticationProvider method changeUser.

@Override
public void changeUser(String userName, String password, String database) {
    boolean overTLS = ((XServerCapabilities) this.protocol.getServerSession().getCapabilities()).getTls();
    RuntimeProperty<AuthMech> authMechProp = this.protocol.getPropertySet().<AuthMech>getEnumProperty(PropertyKey.xdevapiAuth);
    List<AuthMech> tryAuthMech;
    if (overTLS || authMechProp.isExplicitlySet()) {
        tryAuthMech = Arrays.asList(authMechProp.getValue());
    } else {
        tryAuthMech = Arrays.asList(AuthMech.MYSQL41, AuthMech.SHA256_MEMORY);
    }
    XProtocolError capturedAuthErr = null;
    for (AuthMech am : tryAuthMech) {
        this.authMech = am;
        try {
            switch(this.authMech) {
                case SHA256_MEMORY:
                    this.protocol.send(this.messageBuilder.buildSha256MemoryAuthStart(), 0);
                    byte[] nonce = this.protocol.readAuthenticateContinue();
                    this.protocol.send(this.messageBuilder.buildSha256MemoryAuthContinue(userName, password, nonce, database), 0);
                    break;
                case MYSQL41:
                    this.protocol.send(this.messageBuilder.buildMysql41AuthStart(), 0);
                    byte[] salt = this.protocol.readAuthenticateContinue();
                    this.protocol.send(this.messageBuilder.buildMysql41AuthContinue(userName, password, salt, database), 0);
                    break;
                case PLAIN:
                    if (overTLS) {
                        this.protocol.send(this.messageBuilder.buildPlainAuthStart(userName, password, database), 0);
                    } else {
                        throw new XProtocolError("PLAIN authentication is not allowed via unencrypted connection.");
                    }
                    break;
                case EXTERNAL:
                    this.protocol.send(this.messageBuilder.buildExternalAuthStart(database), 0);
                    break;
                default:
                    throw new WrongArgumentException("Unknown authentication mechanism '" + this.authMech + "'.");
            }
        } catch (CJCommunicationsException e) {
            if (capturedAuthErr != null && e.getCause() instanceof ClosedChannelException) {
                // High probability that the server doesn't support authentication sequences. Ignore this exception and throw the previous one.
                throw capturedAuthErr;
            }
            throw e;
        }
        try {
            this.protocol.readAuthenticateOk();
            // Clear any captured exception and stop trying remaining auth mechanisms.
            capturedAuthErr = null;
            break;
        } catch (XProtocolError e) {
            if (e.getErrorCode() != MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR) {
                throw e;
            }
            capturedAuthErr = e;
        }
    }
    if (capturedAuthErr != null) {
        if (tryAuthMech.size() == 1) {
            throw capturedAuthErr;
        }
        // More than one authentication mechanism was tried.
        String errMsg = "Authentication failed using " + StringUtils.joinWithSerialComma(tryAuthMech) + ", check username and password or try a secure connection";
        XDevAPIError ex = new XDevAPIError(errMsg, capturedAuthErr);
        ex.setVendorCode(capturedAuthErr.getErrorCode());
        ex.setSQLState(capturedAuthErr.getSQLState());
        throw ex;
    }
    this.protocol.afterHandshake();
}
Also used : AuthMech(com.mysql.cj.conf.PropertyDefinitions.AuthMech) ClosedChannelException(java.nio.channels.ClosedChannelException) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) XDevAPIError(com.mysql.cj.xdevapi.XDevAPIError) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException)

Aggregations

AuthMech (com.mysql.cj.conf.PropertyDefinitions.AuthMech)1 CJCommunicationsException (com.mysql.cj.exceptions.CJCommunicationsException)1 WrongArgumentException (com.mysql.cj.exceptions.WrongArgumentException)1 XDevAPIError (com.mysql.cj.xdevapi.XDevAPIError)1 ClosedChannelException (java.nio.channels.ClosedChannelException)1