use of com.mysql.cj.protocol.ServerSession in project ABC by RuiPinto96274.
the class NativeAuthenticationProvider method proceedHandshakeWithPluggableAuthentication.
/**
* Performs an authentication handshake to authorize connection to a given database as a given MySQL user.
* This can happen upon initial connection to the server, after receiving Auth Challenge Packet, or
* at any moment during the connection life-time via a Change User request.
*
* This method will use registered authentication plugins as requested by the server.
*
* @param challenge
* the Auth Challenge Packet received from server if
* this method is used during the initial connection.
* Otherwise null.
*/
private void proceedHandshakeWithPluggableAuthentication(final NativePacketPayload challenge) {
ServerSession serverSession = this.protocol.getServerSession();
if (this.authenticationPlugins == null) {
loadAuthenticationPlugins();
}
boolean forChangeUser = true;
if (challenge != null) {
this.serverDefaultAuthenticationPluginName = challenge.readString(StringSelfDataType.STRING_TERM, "ASCII");
forChangeUser = false;
}
serverSession.getCharsetSettings().configurePreHandshake(forChangeUser);
/*
* Select the initial plugin:
* Choose the client-side default authentication plugin, if explicitely specified, otherwise choose the server-side default authentication plugin.
*/
String pluginName;
if (this.clientDefaultAuthenticationPluginExplicitelySet) {
pluginName = this.clientDefaultAuthenticationPluginName;
} else {
pluginName = this.serverDefaultAuthenticationPluginName != null ? this.serverDefaultAuthenticationPluginName : this.clientDefaultAuthenticationPluginName;
}
AuthenticationPlugin<NativePacketPayload> plugin = getAuthenticationPlugin(pluginName);
if (plugin == null) {
/* Use default if there is no plugin for pluginName. */
pluginName = this.clientDefaultAuthenticationPluginName;
plugin = getAuthenticationPlugin(pluginName);
}
boolean skipPassword = false;
if (pluginName.equals(Sha256PasswordPlugin.PLUGIN_NAME) && !pluginName.equals(this.clientDefaultAuthenticationPluginName) && !this.protocol.getSocketConnection().isSSLEstablished() && this.propertySet.getStringProperty(PropertyKey.serverRSAPublicKeyFile).getValue() == null && !this.propertySet.getBooleanProperty(PropertyKey.allowPublicKeyRetrieval).getValue()) {
/*
* Fall back to client default if plugin is 'sha256_password' but required conditions for this to work aren't met.
* If client default is other than 'sha256_password', this will result in an immediate authentication switch request, allowing for other plugins to
* authenticate successfully. If client default is 'sha256_password' then the authentication will fail as expected. In both cases user's password
* won't be sent to avoid subjecting it to lesser security levels.
*/
plugin = getAuthenticationPlugin(this.clientDefaultAuthenticationPluginName);
skipPassword = true;
}
checkConfidentiality(plugin);
// Servers not affected by Bug#70865 expect the Change User Request containing a correct answer to seed sent by the server during the initial handshake,
// thus we reuse it here. Servers affected by Bug#70865 will just ignore it and send the Auth Switch.
NativePacketPayload fromServer = new NativePacketPayload(StringUtils.getBytes(this.seed));
String sourceOfAuthData = this.serverDefaultAuthenticationPluginName;
boolean old_raw_challenge = false;
NativePacketPayload last_sent = null;
NativePacketPayload last_received = challenge;
ArrayList<NativePacketPayload> toServer = new ArrayList<>();
/* Max iterations number */
int counter = 100;
while (0 < counter--) {
/*
* call plugin
*/
plugin.setAuthenticationParameters(this.username, skipPassword ? null : this.password);
plugin.setSourceOfAuthData(sourceOfAuthData);
plugin.nextAuthenticationStep(fromServer, toServer);
/*
* send response to server
*/
if (toServer.size() > 0) {
if (forChangeUser) {
// write COM_CHANGE_USER Packet
last_sent = createChangeUserPacket(serverSession, plugin.getProtocolPluginName(), toServer);
this.protocol.send(last_sent, last_sent.getPosition());
// this branch should be executed only once
forChangeUser = false;
} else if (last_received.isAuthMethodSwitchRequestPacket() || last_received.isAuthMoreData() || old_raw_challenge) {
// write AuthSwitchResponse packet or raw packet(s)
for (NativePacketPayload buffer : toServer) {
this.protocol.send(buffer, buffer.getPayloadLength());
}
} else {
// write HandshakeResponse packet
last_sent = createHandshakeResponsePacket(serverSession, plugin.getProtocolPluginName(), toServer);
this.protocol.send(last_sent, last_sent.getPosition());
}
}
/*
* read packet from server
*/
last_received = this.protocol.checkErrorMessage();
old_raw_challenge = false;
if (last_received.isOKPacket()) {
// read OK packet
OkPacket ok = OkPacket.parse(last_received, null);
serverSession.setStatusFlags(ok.getStatusFlags(), true);
serverSession.getServerSessionStateController().setSessionStateChanges(ok.getSessionStateChanges());
// if OK packet then finish handshake
plugin.destroy();
break;
} else if (last_received.isAuthMethodSwitchRequestPacket()) {
// read AuthSwitchRequest Packet
skipPassword = false;
pluginName = last_received.readString(StringSelfDataType.STRING_TERM, "ASCII");
if (plugin.getProtocolPluginName().equals(pluginName)) {
// just reset the current one
plugin.reset();
} else {
// get new plugin
plugin.destroy();
plugin = getAuthenticationPlugin(pluginName);
if (plugin == null) {
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("AuthenticationProvider.BadAuthenticationPlugin", new Object[] { pluginName }), getExceptionInterceptor());
}
}
checkConfidentiality(plugin);
fromServer = new NativePacketPayload(last_received.readBytes(StringSelfDataType.STRING_EOF));
} else {
// read raw packet
if (!this.protocol.versionMeetsMinimum(5, 5, 16)) {
old_raw_challenge = true;
last_received.setPosition(last_received.getPosition() - 1);
}
fromServer = new NativePacketPayload(last_received.readBytes(StringSelfDataType.STRING_EOF));
}
sourceOfAuthData = pluginName;
}
if (counter == 0) {
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("CommunicationsException.TooManyAuthenticationPluginNegotiations"), getExceptionInterceptor());
}
this.protocol.afterHandshake();
if (!this.useConnectWithDb) {
this.protocol.changeDatabase(this.database);
}
}
Aggregations