This is an automated email from the ASF dual-hosted git repository.
panjuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new a9f1a0b314d Add OpenGaussAuthenticator (#23827)
a9f1a0b314d is described below
commit a9f1a0b314d4d43b5b5f1763d33825f5b2c68595
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Jan 30 13:36:02 2023 +0800
Add OpenGaussAuthenticator (#23827)
---
.../OpenGaussAuthenticationHandler.java | 120 +++++++--------------
.../authenticator/OpenGaussAuthenticator.java | 26 +++++
...OpenGaussSCRAMSha256PasswordAuthenticator.java} | 86 ++-------------
3 files changed, 76 insertions(+), 156 deletions(-)
diff --git
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
index 72cf3077ddc..6c672a70006 100644
---
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
@@ -17,7 +17,6 @@
package org.apache.shardingsphere.proxy.frontend.opengauss.authentication;
-import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@@ -33,6 +32,8 @@ import org.apache.shardingsphere.infra.metadata.user.Grantee;
import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
import
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussAuthenticator;
+import
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussSCRAMSha256PasswordAuthenticator;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
@@ -40,10 +41,8 @@ import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
@@ -59,12 +58,8 @@ public final class OpenGaussAuthenticationHandler {
private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
- private static final String SHA256_ALGORITHM = "SHA-256";
-
private static final String SERVER_KEY = "Server Key";
- private static final String CLIENT_KEY = "Client Key";
-
/**
* Calculate server signature.
*
@@ -81,66 +76,6 @@ public final class OpenGaussAuthenticationHandler {
return bytesToHexString(result);
}
- private static String bytesToHexString(final byte[] src) {
- StringBuilder result = new StringBuilder();
- for (byte each : src) {
- String hex = Integer.toHexString(each & 255);
- if (hex.length() < 2) {
- result.append(0);
- }
- result.append(hex);
- }
- return result.toString();
- }
-
- /**
- * Login with SCRAM SHA-256 password.
- *
- * @param username username
- * @param databaseName database name
- * @param salt salt in hex string
- * @param nonce nonce in hex string
- * @param serverIteration server iteration
- * @param passwordMessagePacket password message packet
- */
- public static void loginWithSCRAMSha256Password(final String username,
final String databaseName, final String salt, final String nonce, final int
serverIteration,
- final
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
-
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) ||
ProxyContext.getInstance().databaseExists(databaseName), () -> new
UnknownDatabaseException(databaseName));
- AuthorityRule authorityRule =
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
- Grantee grantee = new Grantee(username, "%");
- Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
- ShardingSpherePreconditions.checkState(user.isPresent(), () -> new
UnknownUsernameException(username));
- ShardingSpherePreconditions.checkState(isPasswordRight(user.get(), new
Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
- () -> new InvalidPasswordException(username));
- ShardingSpherePreconditions.checkState(null == databaseName || new
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
- () -> new PrivilegeNotGrantedException(username,
databaseName));
- }
-
- private static boolean isPasswordRight(final ShardingSphereUser user,
final Object[] args) {
- String h3HexString = (String) args[0];
- String salt = (String) args[1];
- String nonce = (String) args[2];
- int serverIteration = (int) args[3];
- byte[] serverStoredKey = calculatedStoredKey(user.getPassword(), salt,
serverIteration);
- byte[] h3 = hexStringToBytes(h3HexString);
- byte[] h2 = calculateH2(user.getPassword(), salt, nonce,
serverIteration);
- byte[] clientCalculatedStoredKey = sha256(xor(h3, h2));
- return Arrays.equals(clientCalculatedStoredKey, serverStoredKey);
- }
-
- private static byte[] calculatedStoredKey(final String password, final
String salt, final int serverIteration) {
- byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
- byte[] clientKey = getKeyFromHmac(k, CLIENT_KEY.getBytes());
- return sha256(clientKey);
- }
-
- private static byte[] calculateH2(final String password, final String
salt, final String nonce, final int serverIteration) {
- byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
- byte[] clientKey = getKeyFromHmac(k, CLIENT_KEY.getBytes());
- byte[] storedKey = sha256(clientKey);
- return getKeyFromHmac(storedKey, hexStringToBytes(nonce));
- }
-
@SneakyThrows({NoSuchAlgorithmException.class,
InvalidKeySpecException.class})
private static byte[] generateKFromPBKDF2(final String password, final
String saltString, final int serverIteration) {
char[] chars = password.toCharArray();
@@ -169,13 +104,6 @@ public final class OpenGaussAuthenticationHandler {
return (byte) "0123456789ABCDEF".indexOf(c);
}
- @SneakyThrows(NoSuchAlgorithmException.class)
- private static byte[] sha256(final byte[] str) {
- MessageDigest md = MessageDigest.getInstance(SHA256_ALGORITHM);
- md.update(str);
- return md.digest();
- }
-
@SneakyThrows({NoSuchAlgorithmException.class, InvalidKeyException.class})
private static byte[] getKeyFromHmac(final byte[] key, final byte[] data) {
SecretKeySpec signingKey = new SecretKeySpec(key,
HMAC_SHA256_ALGORITHM);
@@ -184,13 +112,43 @@ public final class OpenGaussAuthenticationHandler {
return mac.doFinal(data);
}
- private static byte[] xor(final byte[] password1, final byte[] password2) {
- Preconditions.checkArgument(password1.length == password2.length, "Xor
values with different length");
- int length = password1.length;
- byte[] result = new byte[length];
- for (int i = 0; i < length; i++) {
- result[i] = (byte) (password1[i] ^ password2[i]);
+ private static String bytesToHexString(final byte[] src) {
+ StringBuilder result = new StringBuilder();
+ for (byte each : src) {
+ String hex = Integer.toHexString(each & 255);
+ if (hex.length() < 2) {
+ result.append(0);
+ }
+ result.append(hex);
}
- return result;
+ return result.toString();
+ }
+
+ /**
+ * Login with SCRAM SHA-256 password.
+ *
+ * @param username username
+ * @param databaseName database name
+ * @param salt salt in hex string
+ * @param nonce nonce in hex string
+ * @param serverIteration server iteration
+ * @param passwordMessagePacket password message packet
+ */
+ public static void loginWithSCRAMSha256Password(final String username,
final String databaseName, final String salt, final String nonce, final int
serverIteration,
+ final
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
+
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) ||
ProxyContext.getInstance().databaseExists(databaseName), () -> new
UnknownDatabaseException(databaseName));
+ AuthorityRule authorityRule =
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
+ Grantee grantee = new Grantee(username, "%");
+ Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
+ ShardingSpherePreconditions.checkState(user.isPresent(), () -> new
UnknownUsernameException(username));
+
ShardingSpherePreconditions.checkState(getAuthenticator(grantee).authenticate(user.get(),
new Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
+ () -> new InvalidPasswordException(username));
+ ShardingSpherePreconditions.checkState(null == databaseName || new
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
+ () -> new PrivilegeNotGrantedException(username,
databaseName));
+ }
+
+ private static OpenGaussAuthenticator getAuthenticator(final Grantee
grantee) {
+ // TODO get authenticator by username and hostname
+ return new OpenGaussSCRAMSha256PasswordAuthenticator();
}
}
diff --git
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
new file mode 100644
index 00000000000..c125e174435
--- /dev/null
+++
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator;
+
+import org.apache.shardingsphere.proxy.frontend.authentication.Authenticator;
+
+/**
+ * OpenGauss authenticator.
+ */
+public interface OpenGaussAuthenticator extends Authenticator<Object[]> {
+}
diff --git
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
similarity index 55%
copy from
proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
copy to
proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
index 72cf3077ddc..6556c946810 100644
---
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
@@ -15,45 +15,28 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.frontend.opengauss.authentication;
+package
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator;
import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
-import org.apache.shardingsphere.authority.checker.AuthorityChecker;
-import org.apache.shardingsphere.authority.rule.AuthorityRule;
-import
org.apache.shardingsphere.db.protocol.postgresql.packet.handshake.PostgreSQLPasswordMessagePacket;
-import
org.apache.shardingsphere.dialect.exception.syntax.database.UnknownDatabaseException;
-import
org.apache.shardingsphere.dialect.postgresql.exception.authority.InvalidPasswordException;
-import
org.apache.shardingsphere.dialect.postgresql.exception.authority.PrivilegeNotGrantedException;
-import
org.apache.shardingsphere.dialect.postgresql.exception.authority.UnknownUsernameException;
-import org.apache.shardingsphere.infra.metadata.user.Grantee;
+import
org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLAuthenticationMethod;
import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
-import
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
-import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Locale;
-import java.util.Optional;
/**
- * Authentication handler for openGauss.
- *
- * @see <a
href="https://opengauss.org/zh/blogs/blogs.html?post/douxin/sm3_for_opengauss/">SM3
for openGauss</a>
+ * SCRAM Sha256 password authenticator for openGauss.
*/
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class OpenGaussAuthenticationHandler {
+public final class OpenGaussSCRAMSha256PasswordAuthenticator implements
OpenGaussAuthenticator {
private static final String PBKDF2_WITH_HMAC_SHA1_ALGORITHM =
"PBKDF2WithHmacSHA1";
@@ -61,62 +44,10 @@ public final class OpenGaussAuthenticationHandler {
private static final String SHA256_ALGORITHM = "SHA-256";
- private static final String SERVER_KEY = "Server Key";
-
private static final String CLIENT_KEY = "Client Key";
- /**
- * Calculate server signature.
- *
- * @param password password
- * @param salt salt in hex string
- * @param nonce nonce in hex string
- * @param serverIteration server iteration
- * @return server signature
- */
- public static String calculateServerSignature(final String password, final
String salt, final String nonce, final int serverIteration) {
- byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
- byte[] serverKey = getKeyFromHmac(k,
SERVER_KEY.getBytes(StandardCharsets.UTF_8));
- byte[] result = getKeyFromHmac(serverKey, hexStringToBytes(nonce));
- return bytesToHexString(result);
- }
-
- private static String bytesToHexString(final byte[] src) {
- StringBuilder result = new StringBuilder();
- for (byte each : src) {
- String hex = Integer.toHexString(each & 255);
- if (hex.length() < 2) {
- result.append(0);
- }
- result.append(hex);
- }
- return result.toString();
- }
-
- /**
- * Login with SCRAM SHA-256 password.
- *
- * @param username username
- * @param databaseName database name
- * @param salt salt in hex string
- * @param nonce nonce in hex string
- * @param serverIteration server iteration
- * @param passwordMessagePacket password message packet
- */
- public static void loginWithSCRAMSha256Password(final String username,
final String databaseName, final String salt, final String nonce, final int
serverIteration,
- final
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
-
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) ||
ProxyContext.getInstance().databaseExists(databaseName), () -> new
UnknownDatabaseException(databaseName));
- AuthorityRule authorityRule =
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
- Grantee grantee = new Grantee(username, "%");
- Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
- ShardingSpherePreconditions.checkState(user.isPresent(), () -> new
UnknownUsernameException(username));
- ShardingSpherePreconditions.checkState(isPasswordRight(user.get(), new
Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
- () -> new InvalidPasswordException(username));
- ShardingSpherePreconditions.checkState(null == databaseName || new
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
- () -> new PrivilegeNotGrantedException(username,
databaseName));
- }
-
- private static boolean isPasswordRight(final ShardingSphereUser user,
final Object[] args) {
+ @Override
+ public boolean authenticate(final ShardingSphereUser user, final Object[]
args) {
String h3HexString = (String) args[0];
String salt = (String) args[1];
String nonce = (String) args[2];
@@ -193,4 +124,9 @@ public final class OpenGaussAuthenticationHandler {
}
return result;
}
+
+ @Override
+ public String getAuthenticationMethodName() {
+ return PostgreSQLAuthenticationMethod.SCRAM_SHA256.getMethodName();
+ }
}