Skip to content

Commit bb0f86d

Browse files
committed
WL#15197, Support WebauthN in fido authentication plugin.
Change-Id: Ia83d2c1f7619e7c0febbbc426a7cfef4d0feae43
1 parent 4e97a3e commit bb0f86d

File tree

9 files changed

+436
-6
lines changed

9 files changed

+436
-6
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.2.0
55

6+
- WL#15197, Support WebauthN in fido authentication plugin.
7+
68
- Fix for Bug#107215 (Bug#34139593), ClassCastException: java.time.LocalDateTime cannot be cast to java.sql.Timestamp.
79

810
- WL#15747, Remove autoDeserialize feature.
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it under
5+
* the terms of the GNU General Public License, version 2.0, as published by the
6+
* Free Software Foundation.
7+
*
8+
* This program is also distributed with certain software (including but not
9+
* limited to OpenSSL) that is licensed under separate terms, as designated in a
10+
* particular file or component or in included license documentation. The
11+
* authors of MySQL hereby grant you an additional permission to link the
12+
* program and your derivative works with the separately licensed software that
13+
* they have included with MySQL.
14+
*
15+
* Without limiting anything contained in the foregoing, this file, which is
16+
* part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
17+
* version 1.0, a copy of which can be found at
18+
* http://oss.oracle.com/licenses/universal-foss-exception.
19+
*
20+
* This program is distributed in the hope that it will be useful, but WITHOUT
21+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
23+
* for more details.
24+
*
25+
* You should have received a copy of the GNU General Public License along with
26+
* this program; if not, write to the Free Software Foundation, Inc.,
27+
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28+
*/
29+
30+
package com.mysql.cj.callback;
31+
32+
import java.util.ArrayList;
33+
import java.util.List;
34+
35+
/**
36+
* The callback object used by the authentication plugin AuthenticationWebAuthnClient to exchange authenticator data between the driver and the client
37+
* application.
38+
*
39+
* Applications must implement a MysqlCallbackHandler to manage the interaction with authenticator devices and provide the data required to proceed with
40+
* FIDO2/WebAuthn authentication. Such handler receives an instance of this class, which must then be used to obtain the data to send to the device and to
41+
* submit the produced authenticator data and signature into the driver.
42+
*/
43+
public class WebAuthnAuthenticationCallback implements MysqlCallback {
44+
45+
// FIDO inputs.
46+
private byte[] clientDataHash;
47+
private String relyingPartyId;
48+
private byte[] credentialId;
49+
50+
// FIDO outputs.
51+
private boolean supportsCredentialManagement;
52+
private List<byte[]> authenticatorDataEntries;
53+
private List<byte[]> signatureEntries;
54+
55+
/**
56+
* Instances of this object are used to exchange FIDO data between the client application and the driver and are responsible for managing all the
57+
* interactions with the FIDO authenticator devices.
58+
*
59+
* @param clientDataHash
60+
* the client data hash
61+
* @param relyingPartyId
62+
* the relying party id
63+
* @param credentialId
64+
* the credential id
65+
*/
66+
public WebAuthnAuthenticationCallback(byte[] clientDataHash, String relyingPartyId, byte[] credentialId) {
67+
this.clientDataHash = clientDataHash;
68+
this.relyingPartyId = relyingPartyId;
69+
this.credentialId = credentialId;
70+
this.authenticatorDataEntries = new ArrayList<>();
71+
this.signatureEntries = new ArrayList<>();
72+
}
73+
74+
/**
75+
* Returns the FIDO Client Data Hash (an SHA-256 hash computed from the Client Data JSON) for the upcoming authenticator interaction.
76+
*
77+
* @return
78+
* the client data hash
79+
*/
80+
public byte[] getClientDataHash() {
81+
return this.clientDataHash;
82+
}
83+
84+
/**
85+
* Returns the FIDO Relying Party Id for the upcoming authenticator interaction.
86+
*
87+
* @return
88+
* the relying party id
89+
*/
90+
public String getRelyingPartyId() {
91+
return this.relyingPartyId;
92+
}
93+
94+
/**
95+
* Returns the FIDO Credential Id for the upcoming authenticator interaction.
96+
*
97+
* @return
98+
* the credential id
99+
*/
100+
public byte[] getCredentialId() {
101+
return this.credentialId;
102+
}
103+
104+
/**
105+
* Sets whether this FIDO Authenticator device supports Credential Management.
106+
*
107+
* @param supportsCredMan
108+
* is credential management supported?
109+
*/
110+
public void setSupportsCredentialManagement(boolean supportsCredMan) {
111+
this.supportsCredentialManagement = supportsCredMan;
112+
}
113+
114+
/**
115+
* Returns whether this FIDO Authenticator device supports Credential Management.
116+
*
117+
* @return
118+
* is credential management supported?
119+
*/
120+
public boolean getSupportsCredentialManagement() {
121+
return this.supportsCredentialManagement;
122+
}
123+
124+
/**
125+
* Adds a FIDO Authenticator Data produced by the authenticator interaction.
126+
*
127+
* @param authenticatorData
128+
* the authenticator data
129+
*/
130+
public void addAuthenticatorData(byte[] authenticatorData) {
131+
this.authenticatorDataEntries.add(authenticatorData);
132+
}
133+
134+
/**
135+
* Returns one of FIDO Authenticator Data produced by the authenticator interaction.
136+
*
137+
* @param idx
138+
* the index of the Authenticator Data to return
139+
*
140+
* @return
141+
* the authenticator data
142+
*/
143+
public byte[] getAuthenticatorData(int idx) {
144+
if (idx >= this.authenticatorDataEntries.size()) {
145+
return null;
146+
}
147+
return this.authenticatorDataEntries.get(idx);
148+
}
149+
150+
/**
151+
* Adds a FIDO Signature produced by the authenticator interaction.
152+
*
153+
* @param signature
154+
* the signature
155+
*/
156+
public void addSignature(byte[] signature) {
157+
this.signatureEntries.add(signature);
158+
}
159+
160+
/**
161+
* Returns one of the FIDO Signatures produced by the authenticator interaction
162+
*
163+
* @param idx
164+
* the index of the Signature to return
165+
*
166+
* @return
167+
* the signature
168+
*/
169+
public byte[] getSignature(int idx) {
170+
if (idx >= this.signatureEntries.size()) {
171+
return null;
172+
}
173+
return this.signatureEntries.get(idx);
174+
}
175+
176+
/**
177+
* Returns the number of assertions produced by the authenticator interaction
178+
*
179+
* @return
180+
* the number of assertions
181+
*/
182+
public int getAssertCount() {
183+
return Math.min(this.authenticatorDataEntries.size(), this.signatureEntries.size());
184+
}
185+
186+
}

src/main/core-api/java/com/mysql/cj/conf/PropertyDefinitions.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,16 @@ public enum DatabaseTerm {
209209
Messages.getString("ConnectionProperties.ldapServerHostname"), "8.0.23", CATEGORY_AUTH, Integer.MIN_VALUE + 9),
210210

211211
new StringPropertyDefinition(PropertyKey.ociConfigFile, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
212-
Messages.getString("ConnectionProperties.ociConfigFile"), "8.0.27", CATEGORY_AUTH, Integer.MIN_VALUE + 7),
212+
Messages.getString("ConnectionProperties.ociConfigFile"), "8.0.27", CATEGORY_AUTH, Integer.MIN_VALUE + 10),
213213

214214
new StringPropertyDefinition(PropertyKey.ociConfigProfile, "DEFAULT", RUNTIME_MODIFIABLE,
215-
Messages.getString("ConnectionProperties.ociConfigProfile"), "8.0.33", CATEGORY_AUTH, Integer.MIN_VALUE + 8),
215+
Messages.getString("ConnectionProperties.ociConfigProfile"), "8.0.33", CATEGORY_AUTH, Integer.MIN_VALUE + 11),
216216

217217
new StringPropertyDefinition(PropertyKey.authenticationFidoCallbackHandler, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
218-
Messages.getString("ConnectionProperties.authenticationFidoCallbackHandler"), "8.0.29", CATEGORY_AUTH, Integer.MIN_VALUE + 9),
218+
Messages.getString("ConnectionProperties.authenticationFidoCallbackHandler"), "8.0.29", CATEGORY_AUTH, Integer.MIN_VALUE + 12),
219+
220+
new StringPropertyDefinition(PropertyKey.authenticationWebAuthnCallbackHandler, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
221+
Messages.getString("ConnectionProperties.authenticationWebAuthnCallbackHandler"), "8.2.0", CATEGORY_AUTH, Integer.MIN_VALUE + 13),
219222

220223
//
221224
// CATEGORY_CONNECTION

src/main/core-api/java/com/mysql/cj/conf/PropertyKey.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public enum PropertyKey {
7272
alwaysSendSetIsolation("alwaysSendSetIsolation", true), //
7373
authenticationFidoCallbackHandler("authenticationFidoCallbackHandler", true), //
7474
authenticationPlugins("authenticationPlugins", true), //
75+
authenticationWebAuthnCallbackHandler("authenticationWebAuthnCallbackHandler", true), //
7576
autoClosePStmtStreams("autoClosePStmtStreams", true), //
7677
autoGenerateTestcaseScript("autoGenerateTestcaseScript", true), //
7778
autoReconnect("autoReconnect", true), //

src/main/protocol-impl/java/com/mysql/cj/protocol/a/NativeAuthenticationProvider.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import com.mysql.cj.protocol.a.authentication.AuthenticationKerberosClient;
6060
import com.mysql.cj.protocol.a.authentication.AuthenticationLdapSaslClientPlugin;
6161
import com.mysql.cj.protocol.a.authentication.AuthenticationOciClient;
62+
import com.mysql.cj.protocol.a.authentication.AuthenticationWebAuthnClient;
6263
import com.mysql.cj.protocol.a.authentication.CachingSha2PasswordPlugin;
6364
import com.mysql.cj.protocol.a.authentication.MysqlClearPasswordPlugin;
6465
import com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin;
@@ -260,6 +261,7 @@ private void loadAuthenticationPlugins() {
260261
pluginsToInit.add(new AuthenticationKerberosClient());
261262
pluginsToInit.add(new AuthenticationOciClient());
262263
pluginsToInit.add(new AuthenticationFidoClient());
264+
pluginsToInit.add(new AuthenticationWebAuthnClient());
263265

264266
// plugins from authenticationPluginClasses connection parameter
265267
String authenticationPluginClasses = this.propertySet.getStringProperty(PropertyKey.authenticationPlugins).getValue();

src/main/protocol-impl/java/com/mysql/cj/protocol/a/authentication/AuthenticationFidoClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public boolean nextAuthenticationStep(NativePacketPayload fromServer, List<Nativ
137137
throw ExceptionFactory.createException(Messages.getString("AuthenticationFidoClientPlugin.InvalidSignature"));
138138
}
139139

140-
NativePacketPayload packet = new NativePacketPayload(authenticatorData.length + signature.length + 4); // 2 + 2 Bytes for length encoding.
140+
NativePacketPayload packet = new NativePacketPayload(authenticatorData.length + signature.length + 2); // 1 + 1 Bytes for length encoding.
141141
packet.writeBytes(StringSelfDataType.STRING_LENENC, authenticatorData);
142142
packet.writeBytes(StringSelfDataType.STRING_LENENC, signature);
143143
toServer.add(packet);

0 commit comments

Comments
 (0)