Skip to content

Commit

Permalink
JDBC-536 Add support for Srp256
Browse files Browse the repository at this point in the history
* Includes plugins for Srp224, Srp384 and Srp512 which are not yet selectable.
  • Loading branch information
mrotteveel committed Jun 23, 2018
1 parent a483426 commit a61214b
Show file tree
Hide file tree
Showing 18 changed files with 350 additions and 69 deletions.
32 changes: 32 additions & 0 deletions src/documentation/release_notes.md
Expand Up @@ -390,6 +390,38 @@ Other warnings and limitations
someone with access to your application or the machine hosting your
application (although that in itself would already imply a severe security
breach).

Authentication plugin improvements
----------------------------------

Jaybird 4 has added support for the new `SrpNNN` (with NNN is 224, 256, 384 and
512) authentication plugins added in Firebird 4 (backported to Firebird 3.0.4).

The original `Srp` plugin used SHA-1, the new Srp-variants use SHA-224, SHA-256,
SHA-384 and SHA-512 respectively[^srpHash].

[^srpHash]: Internally `SrpNNN` continues to uses SHA-1, only the client-proof
applies the SHA-NNN hash. See also [CORE-5788](http://tracker.firebirdsql.org/browse/CORE-5788)).

Be aware, support for these plugins depends on support of these hash algorithms
in the JVM. For example, SHA-224 is not supported in Oracle Java 7.

### Default authentication plugins ###

The default plugins applied by Jaybird are now - in order - `Srp256`, `Srp` and
`Legacy_Auth`.

When connecting to Firebird 3 versions earlier than 3.0.4, or if `Srp256` has
been removed from the `AuthServer` setting in Firebird, this might result in a
slower authentication because more roundtrips to the server are needed because
the attempt to use `Srp256` fails, and authentication then
continues with `Srp`.

Firebird 2.5 and earlier are not affected.

### Configure authentication plugins ###

_Still TODO_

Firebird 4 DECFLOAT support
---------------------------
Expand Down
1 change: 1 addition & 0 deletions src/main/org/firebirdsql/gds/JaybirdErrorCodes.java
Expand Up @@ -72,6 +72,7 @@ public interface JaybirdErrorCodes {
int jb_invalidConnectionPropertyValue = 337248283;
int jb_dbCryptCallbackInitError = 337248284;
int jb_dbCryptDataError = 337248285;
int jb_hashAlgorithmNotAvailable = 337248286;

@SuppressWarnings("unused")
int jb_range_end = 337264639;
Expand Down
10 changes: 9 additions & 1 deletion src/main/org/firebirdsql/gds/ng/wire/WireConnection.java
Expand Up @@ -69,9 +69,9 @@ public abstract class WireConnection<T extends IAttachProperties<T>, C extends F

private static final Logger log = LoggerFactory.getLogger(WireConnection.class);

private final ClientAuthBlock clientAuthBlock;
// Micro-optimization: we usually expect at most 1 (Firebird 3), and usually 0 (Firebird 2.5 and earlier)
private final List<KnownServerKey> knownServerKeys = new ArrayList<>(1);
private ClientAuthBlock clientAuthBlock;
private Socket socket;
private ProtocolCollection protocols;
private int protocolVersion;
Expand Down Expand Up @@ -334,6 +334,14 @@ public final C identify() throws SQLException {
}
}

/**
* Clear authentication data.
*/
public final void clearAuthData() {
clientAuthBlock = null;
clearServerKeys();
}

private byte[] createUserIdentificationBlock() throws IOException, SQLException {
// Here we identify the user to the engine.
// This may or may not be used as login info to a database.
Expand Down
10 changes: 7 additions & 3 deletions src/main/org/firebirdsql/gds/ng/wire/auth/ClientAuthBlock.java
Expand Up @@ -185,8 +185,9 @@ private static String getPluginNames(List<AuthenticationPluginSpi> pluginProvide
}

public void writePluginDataTo(OutputStream userId) throws IOException {
if (attachProperties.getUser() != null) {
final byte[] loginBytes = attachProperties.getUser().getBytes(StandardCharsets.UTF_8);
final String user = getLogin();
if (user != null) {
final byte[] loginBytes = user.getBytes(StandardCharsets.UTF_8);
userId.write(CNCT_login);
int loginLength = Math.min(loginBytes.length, 255);
userId.write(loginLength);
Expand Down Expand Up @@ -237,7 +238,10 @@ private void addMultiPartConnectParameter(OutputStream userId, int paramType, by
private static List<AuthenticationPluginSpi> getSupportedPluginProviders() {
// TODO Create from service provider interface; use properties?
return Collections.unmodifiableList(
Arrays.<AuthenticationPluginSpi>asList(new SrpAuthenticationPluginSpi(), new LegacyAuthenticationPluginSpi()));
Arrays.<AuthenticationPluginSpi>asList(
new Srp256AuthenticationPluginSpi(),
new SrpAuthenticationPluginSpi(),
new LegacyAuthenticationPluginSpi()));
}

public boolean switchPlugin(String pluginName) {
Expand Down
Expand Up @@ -30,19 +30,18 @@
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 3.0
*/
public class LegacyAuthenticationPlugin implements AuthenticationPlugin {
class LegacyAuthenticationPlugin implements AuthenticationPlugin {

private static final Logger log = LoggerFactory.getLogger(LegacyAuthenticationPlugin.class);

public static final String LEGACY_AUTH_NAME = "Legacy_Auth";
public static final String LEGACY_PASSWORD_SALT = "9z";

private byte[] clientData;
private boolean hasServerData;

@Override
public String getName() {
return LEGACY_AUTH_NAME;
return LegacyAuthenticationPluginSpi.LEGACY_AUTH_NAME;
}

@Override
Expand Down
Expand Up @@ -24,9 +24,12 @@
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
*/
public class LegacyAuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String LEGACY_AUTH_NAME = "Legacy_Auth";

@Override
public String getPluginName() {
return LegacyAuthenticationPlugin.LEGACY_AUTH_NAME;
return LEGACY_AUTH_NAME;
}

@Override
Expand Down
@@ -0,0 +1,41 @@
/*
* Firebird Open Source JavaEE Connector - JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.gds.ng.wire.auth;

/**
* Srp224 authentication plugin service provider.
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 4.0
*/
public class Srp224AuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String SRP_AUTH_NAME = "Srp224";

@Override
public String getPluginName() {
return SRP_AUTH_NAME;
}

@Override
public AuthenticationPlugin createPlugin() {
return new SrpAuthenticationPlugin(SRP_AUTH_NAME, "SHA-224");
}

}
@@ -0,0 +1,41 @@
/*
* Firebird Open Source JavaEE Connector - JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.gds.ng.wire.auth;

/**
* Srp256 authentication plugin service provider.
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 3.0.5
*/
public class Srp256AuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String SRP_AUTH_NAME = "Srp256";

@Override
public String getPluginName() {
return SRP_AUTH_NAME;
}

@Override
public AuthenticationPlugin createPlugin() {
return new SrpAuthenticationPlugin(SRP_AUTH_NAME, "SHA-256");
}

}
@@ -0,0 +1,41 @@
/*
* Firebird Open Source JavaEE Connector - JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.gds.ng.wire.auth;

/**
* Srp384 authentication plugin service provider.
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 4.0
*/
public class Srp384AuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String SRP_AUTH_NAME = "Srp384";

@Override
public String getPluginName() {
return SRP_AUTH_NAME;
}

@Override
public AuthenticationPlugin createPlugin() {
return new SrpAuthenticationPlugin(SRP_AUTH_NAME, "SHA-384");
}

}
@@ -0,0 +1,41 @@
/*
* Firebird Open Source JavaEE Connector - JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.gds.ng.wire.auth;

/**
* Srp512 authentication plugin service provider.
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 4.0
*/
public class Srp512AuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String SRP_AUTH_NAME = "Srp512";

@Override
public String getPluginName() {
return SRP_AUTH_NAME;
}

@Override
public AuthenticationPlugin createPlugin() {
return new SrpAuthenticationPlugin(SRP_AUTH_NAME, "SHA-512");
}

}
Expand Up @@ -28,23 +28,40 @@
import java.sql.SQLException;

/**
* Authentication plugin for authentication with SRP.
* Authentication plugin for authentication with Srp.
* <p>
* Supports multiple hash algorithms for the client proof.
* </p>
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
*/
public class SrpAuthenticationPlugin implements AuthenticationPlugin {
class SrpAuthenticationPlugin implements AuthenticationPlugin {

private static final Logger log = LoggerFactory.getLogger(SrpAuthenticationPlugin.class);

public static final String SRP_AUTH_NAME = "Srp";

private final String pluginName;
private final String clientProofHashAlgorithm;
private byte[] clientData;
private SrpClient srpClient;
private byte[] serverData;

/**
* Initializes the SRP authentication plugin.
*
* @param pluginName
* Firebird name of the plugin
* @param clientProofHashAlgorithm
* Hash algorithm name (as accepted by {@code MessageDigest.getInstance}) for
* creating the client proof.
*/
SrpAuthenticationPlugin(String pluginName, String clientProofHashAlgorithm) {
this.pluginName = pluginName;
this.clientProofHashAlgorithm = clientProofHashAlgorithm;
}

@Override
public String getName() {
return SRP_AUTH_NAME;
return pluginName;
}

@Override
Expand All @@ -54,7 +71,7 @@ public AuthStatus authenticate(ClientAuthBlock clientAuthBlock) throws SQLExcept
if (clientAuthBlock.getLogin() == null || clientAuthBlock.getPassword() == null) {
return AuthStatus.AUTH_CONTINUE;
}
srpClient = new SrpClient();
srpClient = new SrpClient(clientProofHashAlgorithm);
clientData = srpClient.getPublicKeyHex().getBytes(StandardCharsets.US_ASCII);
return AuthStatus.AUTH_MORE_DATA;
} else if (srpClient.getSessionKey() != null) {
Expand All @@ -66,7 +83,6 @@ public AuthStatus authenticate(ClientAuthBlock clientAuthBlock) throws SQLExcept
log.debug("SRP phase 2");
clientData = toHex(srpClient.clientProof(clientAuthBlock.getLogin(), clientAuthBlock.getPassword(), serverData))
.getBytes(StandardCharsets.US_ASCII);
// TODO store key as in the Firebird sources?
return AuthStatus.AUTH_SUCCESS;
}

Expand Down
Expand Up @@ -19,19 +19,23 @@
package org.firebirdsql.gds.ng.wire.auth;

/**
* SRP authentication plugin service provider.
* Srp (Srp using SHA-1) authentication plugin service provider.
*
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
* @since 3.0
*/
public class SrpAuthenticationPluginSpi implements AuthenticationPluginSpi {

public static final String SRP_AUTH_NAME = "Srp";

@Override
public String getPluginName() {
return SrpAuthenticationPlugin.SRP_AUTH_NAME;
return SRP_AUTH_NAME;
}

@Override
public AuthenticationPlugin createPlugin() {
return new SrpAuthenticationPlugin();
return new SrpAuthenticationPlugin(SRP_AUTH_NAME, "SHA-1");
}

}

0 comments on commit a61214b

Please sign in to comment.