From 5c8bd44a7fe27d85b5e8cab381c45a0e3909fa57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ira=20=28=E3=83=84=29?=
 <45-lambdaclan@users.noreply.gitlab.archlinux.org>
Date: Thu, 4 Feb 2021 16:17:26 +0900
Subject: [PATCH] Add password validation prior to hash generation

---
 .../mailpass/rest/MailPassResource.java       | 31 ++++++++++++++++---
 .../mailpass/rest/MailPassRestResource.java   | 10 +++++-
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassResource.java b/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassResource.java
index edd3e6b33..5ad552a3d 100644
--- a/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassResource.java
+++ b/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassResource.java
@@ -13,17 +13,21 @@ import javax.ws.rs.core.Response;
 import org.bouncycastle.crypto.generators.OpenBSDBCrypt;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.policy.PasswordPolicyManagerProvider;
+import org.keycloak.policy.PolicyError;
 
 /**
- * A custom REST endpoint to trigger functionality on the Keycloak server, which is not available
- * through the default set of built-in Keycloak REST endpoints. This is to be used during the
- * storage of a custom attribute on the Account Management Console for the mail password. The data
- * stored will be a Bcrypt hash instead of the plain text password.
+ * A custom REST endpoint to trigger functionality on the Keycloak server, which
+ * is not available through the default set of built-in Keycloak REST endpoints.
+ * This is to be used during the storage of a custom attribute on the Account
+ * Management Console for the mail password. The data stored will be a Bcrypt
+ * hash instead of the plain text password.
  */
 public class MailPassResource {
 
   @SuppressWarnings("unused")
   private final KeycloakSession session;
+  private final String userName;
 
   private static final int SALT_LENGTH = 16;
   private static final int COST = 12;
@@ -37,8 +41,21 @@ public class MailPassResource {
     return salt;
   }
 
-  public MailPassResource(KeycloakSession session) {
+  private boolean validatePassword(String pass) {
+    PasswordPolicyManagerProvider policy = session.getProvider(PasswordPolicyManagerProvider.class);
+
+    PolicyError error = policy.validate(this.userName, pass);
+
+    if (error != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public MailPassResource(KeycloakSession session, String userName) {
     this.session = session;
+    this.userName = userName;
   }
 
   /**
@@ -64,6 +81,10 @@ public class MailPassResource {
         throw new BadRequestException("password object not detected in provided JSON body");
       }
 
+      if (!validatePassword(password)) {
+        throw new BadRequestException("password policy error(length(8) and notUsername)");
+      }
+
       byte[] salt = generateSalt();
       String hash = OpenBSDBCrypt.generate(VARIANT, password.toCharArray(), salt, COST);
 
diff --git a/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassRestResource.java b/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassRestResource.java
index c3d856eff..daf788737 100644
--- a/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassRestResource.java
+++ b/roles/keycloak/files/providers/keycloak-mailpass-rest/src/main/java/org/archlinux/keycloak/mailpass/rest/MailPassRestResource.java
@@ -18,6 +18,7 @@ public class MailPassRestResource {
   private final KeycloakSession session;
   private final String realmName;
   private final String realmRole;
+  private final String userName;
   private final AuthenticationManager.AuthResult auth;
 
   /**
@@ -30,6 +31,13 @@ public class MailPassRestResource {
   public MailPassRestResource(KeycloakSession session, String realmName, String realmRole) {
     this.session = session;
     this.auth = new AppAuthManager.BearerTokenAuthenticator(session).authenticate();
+
+    if (auth != null) {
+      this.userName = this.auth.getUser().getUsername();
+    } else {
+      this.userName = "";
+    }
+
     this.realmName = realmName;
     this.realmRole = realmRole;
   }
@@ -43,7 +51,7 @@ public class MailPassRestResource {
   public MailPassResource getMailPassResourceAuthenticated() {
     checkRealm();
     checkRealmAdmin();
-    return new MailPassResource(session);
+    return new MailPassResource(session, userName);
   }
 
   private void checkRealm() {
-- 
GitLab