|
1 | 1 | package hudson.plugins.active_directory; |
2 | 2 |
|
3 | 3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; |
| 4 | +import java.nio.charset.StandardCharsets; |
| 5 | +import java.util.Arrays; |
4 | 6 | import org.kohsuke.accmod.Restricted; |
5 | 7 | import org.kohsuke.accmod.restrictions.NoExternalUse; |
6 | | -import org.mindrot.jbcrypt.BCrypt; |
| 8 | +import org.springframework.security.crypto.bcrypt.BCrypt; |
7 | 9 |
|
8 | 10 | import edu.umd.cs.findbugs.annotations.CheckForNull; |
9 | 11 | import edu.umd.cs.findbugs.annotations.NonNull; |
|
13 | 15 |
|
14 | 16 | @Restricted(NoExternalUse.class) |
15 | 17 | public final class CacheUtil { |
| 18 | + private static final int BCRYPT_MAX_LENGTH = 72; |
16 | 19 | @SuppressFBWarnings("MS_SHOULD_BE_FINAL") |
17 | 20 | public static /* non-final for Groovy */ boolean NO_CACHE_AUTH = Boolean.getBoolean(CacheUtil.class.getName() + ".noCacheAuth"); // Groovy console: hudson.plugins.active_directory.CacheUtil.NO_CACHE_AUTH = true |
18 | 21 | @SuppressFBWarnings("MS_SHOULD_BE_FINAL") |
@@ -62,8 +65,14 @@ private static CacheKey findExistingKeyForUserAndPasswordInSet(String username, |
62 | 65 | if (!Objects.equals(key.getUsername(), username)) { |
63 | 66 | continue; |
64 | 67 | } |
65 | | - // username matches |
66 | | - if (BCrypt.checkpw(password, key.getPasswordHash())) { |
| 68 | + // At this point, username matches. |
| 69 | + // Next, truncate the password to 72 bytes due to the length limit of BCrypt, otherwise Spring's impl would throw. |
| 70 | + // TODO We should use an unlimited length password hash here, but realistically this is unlikely to be a problem |
| 71 | + byte[] passwordBytes = password.getBytes(StandardCharsets.UTF_8); |
| 72 | + if (passwordBytes.length > BCRYPT_MAX_LENGTH) { |
| 73 | + passwordBytes = Arrays.copyOfRange(passwordBytes, 0, BCRYPT_MAX_LENGTH); |
| 74 | + } |
| 75 | + if (BCrypt.checkpw(passwordBytes, key.getPasswordHash())) { |
67 | 76 | return key; |
68 | 77 | } |
69 | 78 | } |
|
0 commit comments