diff --git a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java index 41b46484a5..7a1c1da7aa 100644 --- a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java +++ b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java @@ -75,6 +75,9 @@ import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import jenkins.model.Jenkins; import jenkins.security.FIPS140; +import jenkins.security.NonePasswordComplexityRule; +import jenkins.security.PasswordComplexityException; +import jenkins.security.PasswordComplexityRule; import jenkins.security.SecurityListener; import jenkins.security.seed.UserSeedProperty; import jenkins.util.SystemProperties; diff --git a/core/src/main/java/hudson/security/BasicPasswordComplexityRule.java b/core/src/main/java/jenkins/security/BasicPasswordComplexityRule.java similarity index 78% rename from core/src/main/java/hudson/security/BasicPasswordComplexityRule.java rename to core/src/main/java/jenkins/security/BasicPasswordComplexityRule.java index 1db65bf08f..cde698b2f4 100644 --- a/core/src/main/java/hudson/security/BasicPasswordComplexityRule.java +++ b/core/src/main/java/jenkins/security/BasicPasswordComplexityRule.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2025, Jenkins project contributors + * Copyright (c) 2026, Jenkins project contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,21 +22,24 @@ * THE SOFTWARE. */ -package hudson.security; +package jenkins.security; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import java.util.ArrayList; import java.util.List; import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.DataBoundConstructor; /** * Built-in {@link PasswordComplexityRule} that checks minimum length * and character type requirements. * - * @since 2.572 + * @since 2.572 (moved from hudson.security to jenkins.security in 2.TODO) */ +@Restricted(NoExternalUse.class) public class BasicPasswordComplexityRule extends PasswordComplexityRule { private final int minimumLength; @@ -83,26 +86,27 @@ public class BasicPasswordComplexityRule extends PasswordComplexityRule { public void validate(@NonNull String password) throws PasswordComplexityException { List errors = new ArrayList<>(); if (minimumLength > 0 && password.length() < minimumLength) { - errors.add(Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordTooShort(minimumLength)); + errors.add(Messages.BasicPasswordComplexityRule_PasswordTooShort(minimumLength)); } if (requireUppercase && !password.matches(".*[A-Z].*")) { - errors.add(Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordRequiresUppercase()); + errors.add(Messages.BasicPasswordComplexityRule_PasswordRequiresUppercase()); } if (requireLowercase && !password.matches(".*[a-z].*")) { - errors.add(Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordRequiresLowercase()); + errors.add(Messages.BasicPasswordComplexityRule_PasswordRequiresLowercase()); } if (requireDigit && !password.matches(".*[0-9].*")) { - errors.add(Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordRequiresDigit()); + errors.add(Messages.BasicPasswordComplexityRule_PasswordRequiresDigit()); } - if (requireSpecialCharacter && !password.matches(".*[^a-zA-Z0-9].*")) { - errors.add(Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordRequiresSpecialCharacter()); + if (requireSpecialCharacter && !password.matches(".*\\p{Punct}.*")) { + errors.add(Messages.BasicPasswordComplexityRule_PasswordRequiresSpecialCharacter()); } if (!errors.isEmpty()) { - throw new PasswordComplexityException(String.join(" ", errors)); + throw new PasswordComplexityException(errors); } } - @Extension @Symbol("basicPasswordComplexity") + @Extension + @Symbol("basicPasswordComplexity") public static final class DescriptorImpl extends PasswordComplexityRuleDescriptor { @NonNull @Override diff --git a/core/src/main/java/hudson/security/NonePasswordComplexityRule.java b/core/src/main/java/jenkins/security/NonePasswordComplexityRule.java similarity index 84% rename from core/src/main/java/hudson/security/NonePasswordComplexityRule.java rename to core/src/main/java/jenkins/security/NonePasswordComplexityRule.java index c934588f46..bb115b5504 100644 --- a/core/src/main/java/hudson/security/NonePasswordComplexityRule.java +++ b/core/src/main/java/jenkins/security/NonePasswordComplexityRule.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2025, Jenkins project contributors + * Copyright (c) 2026, Jenkins project contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,18 +22,21 @@ * THE SOFTWARE. */ -package hudson.security; +package jenkins.security; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.DataBoundConstructor; /** * A {@link PasswordComplexityRule} that accepts any password. * - * @since 2.572 + * @since 2.572 (moved from hudson.security to jenkins.security in 2.TODO) */ +@Restricted(NoExternalUse.class) public class NonePasswordComplexityRule extends PasswordComplexityRule { @DataBoundConstructor @@ -42,10 +45,10 @@ public class NonePasswordComplexityRule extends PasswordComplexityRule { @Override public void validate(@NonNull String password) { - // No validation — any password is accepted } - @Extension @Symbol("nonePasswordComplexity") + @Extension + @Symbol("nonePasswordComplexity") public static final class DescriptorImpl extends PasswordComplexityRuleDescriptor { @NonNull @Override diff --git a/core/src/main/java/hudson/security/PasswordComplexityException.java b/core/src/main/java/jenkins/security/PasswordComplexityException.java similarity index 74% rename from core/src/main/java/hudson/security/PasswordComplexityException.java rename to core/src/main/java/jenkins/security/PasswordComplexityException.java index 7a68efa6bb..4cc9544136 100644 --- a/core/src/main/java/hudson/security/PasswordComplexityException.java +++ b/core/src/main/java/jenkins/security/PasswordComplexityException.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2025, Jenkins project contributors + * Copyright (c) 2026, Jenkins project contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,16 +22,26 @@ * THE SOFTWARE. */ -package hudson.security; +package jenkins.security; + +import java.util.List; /** * Thrown by {@link PasswordComplexityRule#validate(String)} when a password * does not meet the configured complexity requirements. * - * @since 2.572 + * @since 2.572 (moved from hudson.security to jenkins.security in 2.TODO) */ public class PasswordComplexityException extends Exception { - public PasswordComplexityException(String message) { - super(message); + + private final List violations; + + public PasswordComplexityException(List violations) { + super(String.join(" ", violations)); + this.violations = List.copyOf(violations); + } + + public List getViolations() { + return violations; } } diff --git a/core/src/main/java/hudson/security/PasswordComplexityRule.java b/core/src/main/java/jenkins/security/PasswordComplexityRule.java similarity index 92% rename from core/src/main/java/hudson/security/PasswordComplexityRule.java rename to core/src/main/java/jenkins/security/PasswordComplexityRule.java index a0c1edf248..97eecb786e 100644 --- a/core/src/main/java/hudson/security/PasswordComplexityRule.java +++ b/core/src/main/java/jenkins/security/PasswordComplexityRule.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2025, Jenkins project contributors + * Copyright (c) 2026, Jenkins project contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,13 +22,14 @@ * THE SOFTWARE. */ -package hudson.security; +package jenkins.security; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.DescriptorExtensionList; import hudson.ExtensionPoint; import hudson.model.Describable; import hudson.model.Descriptor; +import hudson.security.HudsonPrivateSecurityRealm; import jenkins.model.Jenkins; /** @@ -39,7 +40,7 @@ import jenkins.model.Jenkins; * and password changes. Each implementation can have an optional {@code config.jelly} * to configure its validation rules. * - * @since 2.572 + * @since 2.572 (moved from hudson.security to jenkins.security in 2.TODO) */ public abstract class PasswordComplexityRule implements Describable, ExtensionPoint { diff --git a/core/src/main/java/hudson/security/PasswordComplexityRuleDescriptor.java b/core/src/main/java/jenkins/security/PasswordComplexityRuleDescriptor.java similarity index 89% rename from core/src/main/java/hudson/security/PasswordComplexityRuleDescriptor.java rename to core/src/main/java/jenkins/security/PasswordComplexityRuleDescriptor.java index f19bb8595b..7801c0c694 100644 --- a/core/src/main/java/hudson/security/PasswordComplexityRuleDescriptor.java +++ b/core/src/main/java/jenkins/security/PasswordComplexityRuleDescriptor.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2025, Jenkins project contributors + * Copyright (c) 2026, Jenkins project contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,14 +22,14 @@ * THE SOFTWARE. */ -package hudson.security; +package jenkins.security; import hudson.model.Descriptor; /** * {@link Descriptor} for {@link PasswordComplexityRule}. * - * @since 2.572 + * @since 2.572 (moved from hudson.security to jenkins.security in 2.TODO) */ public abstract class PasswordComplexityRuleDescriptor extends Descriptor { } diff --git a/core/src/main/java/jenkins/util/HttpSessionListener.java b/core/src/main/java/jenkins/util/HttpSessionListener.java index 85ff806ac6..8cebb53cb5 100644 --- a/core/src/main/java/jenkins/util/HttpSessionListener.java +++ b/core/src/main/java/jenkins/util/HttpSessionListener.java @@ -61,8 +61,8 @@ public abstract class HttpSessionListener implements ExtensionPoint, jakarta.ser @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { - if (Util.isOverridden(HttpSessionListener.class, getClass(), "sessionCreated", javax.servlet.http.HttpSessionEvent.class)) { - sessionCreated(HttpSessionEventWrapper.fromJakartaHttpSessionEvent(httpSessionEvent)); + if (Util.isOverridden(HttpSessionListener.class, getClass(), "sessionDestroyed", javax.servlet.http.HttpSessionEvent.class)) { + sessionDestroyed(HttpSessionEventWrapper.fromJakartaHttpSessionEvent(httpSessionEvent)); } } diff --git a/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/Details/config.jelly b/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/Details/config.jelly index efdb8912c6..3129c8a505 100644 --- a/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/Details/config.jelly +++ b/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/Details/config.jelly @@ -25,9 +25,9 @@ THE SOFTWARE. - + - + diff --git a/core/src/main/resources/hudson/security/LegacySecurityRealm/config_es.properties b/core/src/main/resources/hudson/security/LegacySecurityRealm/config_es.properties index e9b07760c6..19be6078df 100644 --- a/core/src/main/resources/hudson/security/LegacySecurityRealm/config_es.properties +++ b/core/src/main/resources/hudson/security/LegacySecurityRealm/config_es.properties @@ -1,6 +1,6 @@ # This file is under the MIT License by authors -Unprotected\ URLs=URLs Desprotegidas +Unprotected\ URLs=URLs no protegidas blurb=\ - Estas URLs (y las URLs que inician con el prefijo /) no requieren autenticación. \ - Si es posible, configure su servidor para pasar estas peticiones directamente a Jenkins sin requerir autenticación. + Estas URLs (y las URLs que empiecen con estos prefijos seguidos de una barra "/") no deberían requerir autenticación. \ + Si es posible, configure su contenedor para que estas peticiones se pasen directamente a Jenkins sin necesidad de iniciar sesión. \ No newline at end of file diff --git a/core/src/main/resources/hudson/security/Messages.properties b/core/src/main/resources/hudson/security/Messages.properties index 6abb20a7f6..88079e321d 100644 --- a/core/src/main/resources/hudson/security/Messages.properties +++ b/core/src/main/resources/hudson/security/Messages.properties @@ -45,14 +45,6 @@ HudsonPrivateSecurityRealm.CreateAccount.UserNameInvalidCharacters=User name mus HudsonPrivateSecurityRealm.CreateAccount.UserNameInvalidCharactersCustom=User name must match the following expression: {0} HudsonPrivateSecurityRealm.CreateAccount.InvalidEmailAddress=Invalid e-mail address HudsonPrivateSecurityRealm.CreateAccount.UserNameAlreadyTaken=User name is already taken -HudsonPrivateSecurityRealm.CreateAccount.PasswordTooShort=Password must be at least {0} characters long. -HudsonPrivateSecurityRealm.CreateAccount.PasswordRequiresUppercase=Password must contain at least one uppercase letter (A-Z). -HudsonPrivateSecurityRealm.CreateAccount.PasswordRequiresLowercase=Password must contain at least one lowercase letter (a-z). -HudsonPrivateSecurityRealm.CreateAccount.PasswordRequiresDigit=Password must contain at least one digit (0-9). -HudsonPrivateSecurityRealm.CreateAccount.PasswordRequiresSpecialCharacter=Password must contain at least one special character. - -BasicPasswordComplexityRule.DisplayName=Basic password complexity -NonePasswordComplexityRule.DisplayName=None FullControlOnceLoggedInAuthorizationStrategy.DisplayName=Logged-in users can do anything diff --git a/core/src/main/resources/hudson/security/BasicPasswordComplexityRule/config.jelly b/core/src/main/resources/jenkins/security/BasicPasswordComplexityRule/config.jelly similarity index 94% rename from core/src/main/resources/hudson/security/BasicPasswordComplexityRule/config.jelly rename to core/src/main/resources/jenkins/security/BasicPasswordComplexityRule/config.jelly index 8144ca6962..c519439431 100644 --- a/core/src/main/resources/hudson/security/BasicPasswordComplexityRule/config.jelly +++ b/core/src/main/resources/jenkins/security/BasicPasswordComplexityRule/config.jelly @@ -13,6 +13,6 @@ - + diff --git a/core/src/main/resources/jenkins/security/Messages.properties b/core/src/main/resources/jenkins/security/Messages.properties index d475fc0b3d..9d81496b03 100644 --- a/core/src/main/resources/jenkins/security/Messages.properties +++ b/core/src/main/resources/jenkins/security/Messages.properties @@ -70,3 +70,11 @@ ResourceDomainConfiguration.Invalid=Not a valid URL. ResourceDomainConfiguration.SameAsJenkinsRoot=Cannot use the same host name for both Jenkins URL and resource root URL. ResourceDomainConfiguration.SameAsCurrent=You are currently accessing Jenkins through a URL similar to the proposed resource root URL. Saving this URL might remove your access to Jenkins. +BasicPasswordComplexityRule.DisplayName=Basic password complexity +BasicPasswordComplexityRule.PasswordTooShort=Password must be at least {0} characters long. +BasicPasswordComplexityRule.PasswordRequiresUppercase=Password must contain at least one uppercase letter (A-Z). +BasicPasswordComplexityRule.PasswordRequiresLowercase=Password must contain at least one lowercase letter (a-z). +BasicPasswordComplexityRule.PasswordRequiresDigit=Password must contain at least one digit (0-9). +BasicPasswordComplexityRule.PasswordRequiresSpecialCharacter=Password must contain at least one special character (e.g. !@#$%^&*). +NonePasswordComplexityRule.DisplayName=None + diff --git a/core/src/test/java/hudson/security/BasicPasswordComplexityRuleTest.java b/core/src/test/java/jenkins/security/BasicPasswordComplexityRuleTest.java similarity index 99% rename from core/src/test/java/hudson/security/BasicPasswordComplexityRuleTest.java rename to core/src/test/java/jenkins/security/BasicPasswordComplexityRuleTest.java index b2273e5836..d400e03f8e 100644 --- a/core/src/test/java/hudson/security/BasicPasswordComplexityRuleTest.java +++ b/core/src/test/java/jenkins/security/BasicPasswordComplexityRuleTest.java @@ -1,4 +1,4 @@ -package hudson.security; +package jenkins.security; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; diff --git a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java index e7d45cdd1f..44f86ef70d 100644 --- a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java +++ b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java @@ -55,6 +55,7 @@ import java.util.Collections; import java.util.List; import java.util.logging.Level; import jenkins.security.ApiTokenProperty; +import jenkins.security.BasicPasswordComplexityRule; import jenkins.security.SecurityListener; import jenkins.security.apitoken.ApiTokenPropertyConfiguration; import jenkins.security.seed.UserSeedProperty;