Index: components/jetspeed-portal/src/main/java/org/apache/jetspeed/administration/SimplePasswordGeneratorImpl.java =================================================================== --- components/jetspeed-portal/src/main/java/org/apache/jetspeed/administration/SimplePasswordGeneratorImpl.java (revision 1605844) +++ components/jetspeed-portal/src/main/java/org/apache/jetspeed/administration/SimplePasswordGeneratorImpl.java (working copy) @@ -17,20 +17,24 @@ package org.apache.jetspeed.administration; import java.util.ArrayList; +import java.util.Arrays; import org.apache.jetspeed.security.CredentialPasswordValidator; import org.apache.jetspeed.security.SecurityException; import org.apache.taglibs.random.RandomStrg; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @version $Id$ */ public class SimplePasswordGeneratorImpl implements PasswordGenerator { + Logger log = LoggerFactory.getLogger(SimplePasswordGeneratorImpl.class); /** the list of characters from which a password can be generatored. */ protected static final char[] DEFAULT_PASS_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', - 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }; + 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; // removed these for aesthetic purposes // '!', '&', '-', '_', '=', // '*','@', '#', '$', '%', '^', @@ -40,6 +44,7 @@ protected ArrayList lower = new ArrayList(); protected Integer length = new Integer(12); protected CredentialPasswordValidator validator; + protected int maximumValidationAttempts = 1000; protected RandomStrg newRandomStrg() { @@ -123,6 +128,7 @@ String retval = null; RandomStrg rs = newRandomStrg(); initRandomStrg(rs); + int validationAttemptCount = 0; while (retval == null) { retval = rs.getRandom(); @@ -130,14 +136,46 @@ { try { + if(log.isDebugEnabled()){ + log.debug("passing string "+retval+" to credential validator"); + } validator.validate(retval); } catch (SecurityException sex) { + if(validationAttemptCount==maximumValidationAttempts){ + log.warn("Unable to validate generated password after "+maximumValidationAttempts+ + " returning last generated password string unvalidated"); + break; + } retval = null; } } + + validationAttemptCount++; } + if(log.isDebugEnabled()){ + log.debug("returning string "+retval+" after "+validationAttemptCount+" validation attempts"); + } return retval; } + + public char[] getPasswordChars() { + return passwordChars; + } + + public void setPasswordChars(char[] passwordChars) { + if(log.isDebugEnabled()){ + log.debug("setting up password character array "+Arrays.toString(passwordChars)); + } + this.passwordChars = passwordChars; + } + + public int getMaximumValidationAttempts() { + return maximumValidationAttempts; + } + + public void setMaximumValidationAttempts(int maximumValidationAttempts) { + this.maximumValidationAttempts = maximumValidationAttempts; + } } Index: components/jetspeed-portal/src/test/java/org/apache/jetspeed/administration/TestPortalAdministrationImpl.java =================================================================== --- components/jetspeed-portal/src/test/java/org/apache/jetspeed/administration/TestPortalAdministrationImpl.java (revision 1605844) +++ components/jetspeed-portal/src/test/java/org/apache/jetspeed/administration/TestPortalAdministrationImpl.java (working copy) @@ -19,12 +19,16 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; + import org.apache.jetspeed.aggregator.TestWorkerMonitor; +import org.apache.jetspeed.security.CredentialPasswordValidator; +import org.apache.jetspeed.security.spi.impl.DefaultCredentialPasswordValidator; import org.springframework.mail.javamail.JavaMailSenderImpl; import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; + import java.io.ByteArrayOutputStream; import java.net.URL; import java.net.URLClassLoader; @@ -77,17 +81,58 @@ return new TestSuite(TestPortalAdministrationImpl.class); } - public void testPasswordGen() throws Exception + public void testBasicPasswordGen() throws Exception { + System.out.println("*** testing basic (unvalidated) password generation"); PortalAdministrationImpl pai = new PortalAdministrationImpl(null,null,null,null,null,null,null,null); String newPassword = pai.generatePassword(); + System.out.println("new password is "+newPassword); assertNotNull("new password was NULL!!!",newPassword); assertTrue("password is not long enough",(newPassword.length() > 4) ); } + public void testPasswordGenWithValidationFailure() throws Exception + { + System.out.println("*** testing password generation with validator but unmatched character array and pattern"); + PortalAdministrationImpl pai = new PortalAdministrationImpl(null,null,null,null,null,null,null,null); + SimplePasswordGeneratorImpl pg = new SimplePasswordGeneratorImpl(); + CredentialPasswordValidator cpv = new DefaultCredentialPasswordValidator("^.*(?=.{6,})(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$"); + pg.setValidator(cpv); + pg.setMaximumValidationAttempts(1500); + pai.setPasswordGenerator(pg); + String newPassword = pai.generatePassword(); + System.out.println("new password is "+newPassword); + assertNotNull("new password was NULL!!!",newPassword); + assertTrue("password is not long enough",(newPassword.length() > 4) ); + + } + + public void testFullPasswordGenWithValidation() throws Exception + { + System.out.println("*** testing password generation with matched character array and pattern"); + PortalAdministrationImpl pai = new PortalAdministrationImpl(null,null,null,null,null,null,null,null); + SimplePasswordGeneratorImpl pg = new SimplePasswordGeneratorImpl(); + CredentialPasswordValidator cpv = new DefaultCredentialPasswordValidator("^.*(?=.{6,})(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$"); + pg.setValidator(cpv); + pg.setMaximumValidationAttempts(1500); + pai.setPasswordGenerator(pg); + //char array that matches the pattern above + char[] validChars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0','@','#','$','%','^','&','+','=' }; + pg.setPasswordChars(validChars); + String newPassword = pai.generatePassword(); + + System.out.println("new password is "+newPassword); + assertNotNull("new password was NULL!!!",newPassword); + assertTrue("password is not long enough",(newPassword.length() > 4) ); + + } + public void testSendEmail() throws Exception { + System.out.println("*** testing sendEmail"); JavaMailSenderImpl javaMailSender = null; if (smtpHost != null) @@ -135,6 +180,7 @@ } public void testSendMailFromAnotherThread() throws Exception { + System.out.println("*** testing sendEmailFromAnotherThread"); final List exceptions = new ArrayList(); Thread t = new Thread(new Runnable() { Index: jetspeed-portal-resources/src/main/resources/assembly/administration.xml =================================================================== --- jetspeed-portal-resources/src/main/resources/assembly/administration.xml (revision 1605844) +++ jetspeed-portal-resources/src/main/resources/assembly/administration.xml (working copy) @@ -65,6 +65,84 @@ If a generated password fails validation, the SimplePasswordGeneratorImpl will simply regenerate a new one to test. --> + + 1500 + + + + + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z + A + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + @ + # + $ + % + ^ + + + = + + - --> + * Valid special characters are @#$%^&+= --> + +