1 /*******************************************************************************
2 * Copyright � Igor Barma, Alexandre Desoubeaux, Christian Martel, Eric Brun, Mathieu Amblard, Gwenael Gevet, Pierre Guillot, 2012
3 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Alexandre Lefevre, Marc Salvat 2014-2016
4 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Marc Salvat, Marc Suarez, Harifetra Ramamonjy 2017
6 * This file is part of the work and learning management system Pentila Nero.
8 * Pentila Nero is free software. You can redistribute it and/or modify since
9 * you respect the terms of either (at least one of the both license) :
10 * - under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 * - the CeCILL-C as published by CeCILL-C; either version 1 of the
14 * License, or any later version
15 * - the GNU Lesser General Public License as published by the
16 * Free Software Foundation, either version 3 of the license,
17 * or (at your option) any later version.
19 * There are special exceptions to the terms and conditions of the
20 * licenses as they are applied to this software. View the full text of
21 * the exception in file LICENSE-PROJECT.txt in the directory of this software
24 * Pentila Nero is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * Licenses for more details.
29 * You should have received a copy of the GNU Affero General Public License
30 * and the CeCILL-C and the GNU Lesser General Public License along with
31 * Pentila Nero. If not, see :
32 * <http://www.gnu.org/licenses/> and
33 * <http://www.cecill.info/licences.fr.html>.
34 ******************************************************************************/
36 * @author Darron Schall
41 * PasswordGenerator for creating random passwords.
43 * Four password flags are available to dictate generation,
44 * or a template can be specificed to generate a string with
45 * a specified character type at each position.
48 * Rev Date Who Description
49 * 1.0 8/22/03 darron Initial Draft
50 * --------------------------------------
52 * --------------------------------------
53 * Redistribution and use in source and binary forms, with or without modification,
54 * are permitted provided that the following conditions are met:
56 * 1. Redistributions of source code must retain the above copyright notice, this
57 * list of conditions and the following disclaimer.
59 * 2. Redistributions in binary form must reproduce the above copyright notice,
60 * this list of conditions and the following disclaimer in the documentation
61 * and/or other materials provided with the distribution.
63 * 3. The name of the author may not be used to endorse or promote products derived
64 * from this software without specific prior written permission.
66 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
67 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
68 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
69 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
70 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
71 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
72 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
73 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
74 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
78 package com.liferay.portal.security.ldap;
80 import java.util.ArrayList;
81 import java.util.prefs.InvalidPreferencesFormatException;
82 import java.text.ParseException;
84 public class PasswordGenerator {
89 /** The lowercase included. */
90 private boolean lowercaseIncluded;
92 /** The numbers included. */
93 private boolean numbersIncluded;
95 /** The others included. */
96 private boolean othersIncluded;
98 /** The uppercase included. */
99 private boolean uppercaseIncluded;
102 private String password;
105 private String template;
108 * Instantiates a new password generator.
110 public PasswordGenerator() {
111 // by default, include lowercase only
112 // in the password, and make it 8 characters long.
116 lowercaseIncluded = true;
117 uppercaseIncluded = true;
118 numbersIncluded = true;
119 othersIncluded = false;
121 // start the ball rolling by generating a password so that
122 // we keep our data integrity
123 // i.e. so length matches password.length());
130 * @return true if at least one of the password generation flags is true,
131 * otherwise returns false
133 private boolean flagsOK() {
134 return lowercaseIncluded || uppercaseIncluded || numbersIncluded
141 * @return a random lowercase character from 'a' to 'z'
143 private static char randomLowercase() {
144 return (char) (97 + (int) (Math.random() * 26));
150 * @return a random uppercase character from 'A' to 'Z'
152 private static char randomUppercase() {
153 return (char) (65 + (int) (Math.random() * 26));
159 * @return a random character in this list: !"#$%&'()*+,-./
161 private static char randomOther() {
162 return (char) (33 + (int) (Math.random() * 15));
168 * @return a random character from '0' to '9'
170 private static char randomNumber() {
171 return (char) (48 + (int) (Math.random() * 10));
177 public void generatePassword() /*
178 * throws InvalidPreferencesFormatException,
181 // clear password if necessary
182 if (password.length() != 0) {
186 // check to make sure at least one "type" is included
187 // for password generation if template is not defined
189 // commented out because our setters/construcor should
190 // ensure data integrity
191 // if (!flagsOK() && template.length() == 0) {
193 // java.util.prefs.InvalidPreferencesFormatException("At least one flag must be on to generate a password");
196 // we know length >= 1 here because setLength
197 // doesn't allow invalid lengths and the constructor
198 // initializes length to 8
200 // a template being defined overrides all flags
201 if (template.length() > 0) {
202 length = template.length();
203 for (int i = 0; i < length; i++) {
204 switch (template.charAt(i)) {
206 password += randomLowercase();
210 password += randomUppercase();
215 password += randomNumber();
220 password += randomOther();
223 // commented out because our setters/constructor
224 // should ensure data integrity
227 // ParseException("Password template contains an invalid character",
232 // In Java we can't create an array of function references
233 // so I've created 4 "wrapper" classes that inherit from the
234 // randomCharacter interface to provide the same
235 // type of functionality.
237 // create an ArrayList to store the functions that we're allowed
238 // to call to generate the password, based on what the flags
240 ArrayList flags = new ArrayList();
241 if (lowercaseIncluded) {
242 flags.add(new randomLowercase());
244 if (uppercaseIncluded) {
245 flags.add(new randomUppercase());
247 if (othersIncluded) {
248 flags.add(new randomOther());
250 if (numbersIncluded) {
251 flags.add(new randomNumber());
254 int flagLength = flags.size();
256 for (int i = 0; i < length; i++) {
257 // get a random wrapper class from the flags ArrayList
258 // and cast it to our interface so we can call the execute
260 // which just calls the function and returns its value.
261 password += ((randomCharacter) flags
262 .get((int) (Math.random() * flagLength))).execute();
270 * @return the length of the generated password
272 public int getLength() {
279 * @return the generated password
281 public String getPassword() {
288 * @return password template
290 public String getTemplate() {
295 * Checks if is lowercase included.
297 * @return lowercaseIncluded
299 public boolean isLowercaseIncluded() {
300 return lowercaseIncluded;
304 * Checks if is numbers included.
306 * @return numbersIncluded
308 public boolean isNumbersIncluded() {
309 return numbersIncluded;
313 * Checks if is others included.
315 * @return othersIncluded
317 public boolean isOthersIncluded() {
318 return othersIncluded;
322 * Checks if is uppercase included.
324 * @return uppercaseIncluded
326 public boolean isUppercaseIncluded() {
327 return uppercaseIncluded;
333 * @param length , enforced to be a positive integer >= 3.
335 public void setLength(int length) {
336 this.length = (length < 3) ? 3 : length;
340 * Sets the lowercase included.
344 * @throws InvalidPreferencesFormatException the invalid preferences format exception
346 public void setLowercaseIncluded(boolean b)
347 throws InvalidPreferencesFormatException {
348 lowercaseIncluded = b;
350 // did we turn off the last flag? if so
351 // turn it back on and report error
352 if (b == false && !flagsOK()) {
353 lowercaseIncluded = true;
354 throw new InvalidPreferencesFormatException(
355 "At least one flag must be on to generate a password");
360 * Sets the numbers included.
364 * @throws InvalidPreferencesFormatException the invalid preferences format exception
366 public void setNumbersIncluded(boolean b)
367 throws InvalidPreferencesFormatException {
370 // did we turn off the last flag? if so
371 // turn it back on and report error
372 if (b == false && !flagsOK()) {
373 numbersIncluded = true;
374 throw new InvalidPreferencesFormatException(
375 "At least one flag must be on to generate a password");
380 * Sets the others included.
384 * @throws InvalidPreferencesFormatException the invalid preferences format exception
386 public void setOthersIncluded(boolean b)
387 throws InvalidPreferencesFormatException {
390 // did we turn off the last flag? if so
391 // turn it back on and report error
392 if (b == false && !flagsOK()) {
393 othersIncluded = true;
394 throw new InvalidPreferencesFormatException(
395 "At least one flag must be on to generate a password");
402 * @param template the template
404 * @throws ParseException the parse exception
406 public void setTemplate(String template) throws ParseException {
407 // make sure the template contains only legal characters
408 for (int i = 0; i < template.length(); i++) {
409 switch (template.charAt(i)) {
419 throw new ParseException(
420 "Password template contains an invalid character", i);
423 this.template = template;
427 * Clears the password template,making generation rely on the flags.
429 public void clearTemplate() {
434 * Sets the uppercase included.
438 * @throws InvalidPreferencesFormatException the invalid preferences format exception
440 public void setUppercaseIncluded(boolean b)
441 throws InvalidPreferencesFormatException {
442 uppercaseIncluded = b;
444 // did we turn off the last flag? if so
445 // turn it back on and report error
446 if (b == false && !flagsOK()) {
447 uppercaseIncluded = true;
448 throw new InvalidPreferencesFormatException(
449 "At least one flag must be on to generate a password");
453 /*--------------------------------------------------------
454 Wrapper classes and interface to mimic the array of
455 function references functionality required.
456 ----------------------------------------------------------*/
458 * The Class randomLowercase.
460 private static class randomLowercase implements randomCharacter {
463 * @see com.pentila.sconet.util.PasswordGenerator.randomCharacter#execute()
465 public char execute() {
466 return PasswordGenerator.randomLowercase();
471 * The Class randomUppercase.
473 private static class randomUppercase implements randomCharacter {
476 * @see com.pentila.sconet.util.PasswordGenerator.randomCharacter#execute()
478 public char execute() {
479 return PasswordGenerator.randomUppercase();
484 * The Class randomOther.
486 private static class randomOther implements randomCharacter {
489 * @see com.pentila.sconet.util.PasswordGenerator.randomCharacter#execute()
491 public char execute() {
492 return PasswordGenerator.randomOther();
497 * The Class randomNumber.
499 private static class randomNumber implements randomCharacter {
502 * @see com.pentila.sconet.util.PasswordGenerator.randomCharacter#execute()
504 public char execute() {
505 return PasswordGenerator.randomNumber();
510 * The Interface randomCharacter.
512 private static interface randomCharacter {