Beispiel #1
0
 private void makePatternMap(List<String> patternPairs) throws IllegalArgumentException {
   if (patternPairs != null) {
     patternMap = new LinkedMap();
     for (String pair : patternPairs) {
       // Find the last occurrence of comma to avoid regexp quoting
       int pos = pair.lastIndexOf(',');
       if (pos < 0) {
         throw new IllegalArgumentException("Marformed pattern,int pair; no comma: " + pair);
       }
       String regexp = pair.substring(0, pos);
       String pristr = pair.substring(pos + 1);
       int pri;
       Pattern pat;
       try {
         pri = Integer.parseInt(pristr);
         int flags = Perl5Compiler.READ_ONLY_MASK;
         pat = RegexpUtil.getCompiler().compile(regexp, flags);
         patternMap.put(pat, pri);
       } catch (NumberFormatException e) {
         throw new IllegalArgumentException("Illegal priority: " + pristr);
       } catch (MalformedPatternException e) {
         throw new IllegalArgumentException("Illegal regexp: " + regexp);
       }
     }
   }
 }
 boolean hasRequiredCharacterMix(String str) {
   // Must have at least 3 of: upper alpha, lower alpha, numeric, special
   int cnt = 0;
   Perl5Matcher matcher = RegexpUtil.getMatcher();
   for (Pattern pat : charPats) {
     if (matcher.contains(str, pat)) {
       cnt++;
     }
   }
   return cnt >= 3;
 }
Beispiel #3
0
 /**
  * Return the value associated with the first pattern that the string matches, or the specified
  * default value if none, considering only patterns whose associated value is less than or equal
  * to maxPri.
  */
 public int getMatch(String str, int dfault, int maxPri) {
   Perl5Matcher matcher = RegexpUtil.getMatcher();
   for (Map.Entry<Pattern, Integer> ent : patternMap.entrySet()) {
     if (ent.getValue() <= maxPri) {
       Pattern pat = ent.getKey();
       if (matcher.contains(str, pat)) {
         log.debug2("getMatch(" + str + "): " + ent.getValue());
         return ent.getValue();
       }
     }
   }
   log.debug2("getMatch(" + str + "): default: " + dfault);
   return dfault;
 }
 /** Parse a string of the form [x1,y1},[x2,y2},...,[xN,yN} into a list of Points ([int,int]) */
 public static List<Point> parseString(String str) throws NumberFormatException {
   if (StringUtil.isNullString(str)) {
     throw new IllegalArgumentException("Must supply non-empty string");
   }
   ArrayList<Point> res = new ArrayList<Point>();
   Perl5Matcher matcher = RegexpUtil.getMatcher();
   while (matcher.contains(str, ONE_POINT_PAT)) {
     MatchResult matchResult = matcher.getMatch();
     String xstr = matchResult.group(1);
     String ystr = matchResult.group(2);
     str = matchResult.group(3);
     try {
       int x = Integer.parseInt(xstr);
       int y = Integer.parseInt(ystr);
       res.add(new Point(x, y));
     } catch (NumberFormatException e) {
       throw new IllegalArgumentException("bad point [" + xstr + "," + ystr + "] in " + str);
     }
   }
   res.trimToSize();
   return res;
 }
/** A simple integer step function. Should be genericized */
public class IntStepFunction {

  static class Point {
    final int x;
    final int y;

    Point(int x, int y) {
      this.x = x;
      this.y = y;
    }

    public boolean equals(Object o) {
      if (!(o instanceof Point)) {
        return false;
      }
      Point op = (Point) o;
      return x == op.x && y == op.y;
    }

    public int hashCode() {
      return (int) ((x ^ (x >>> 32)) + (y ^ (y >>> 32)));
    }

    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append("(");
      if (x == Integer.MIN_VALUE) {
        sb.append("-INF");
      } else if (x == Integer.MAX_VALUE) {
        sb.append("+INF");
      } else {
        sb.append(Integer.toString(x));
      }
      sb.append(",");
      sb.append(y);
      sb.append(")");
      return sb.toString();
    }
  }

  private Point points[];

  /**
   * Create a IntStepFunction from a string specifying a list of pairs: [x1,y1},[x2,y2},...,[xN,yN}
   */
  public IntStepFunction(String spec) {
    this(parseString(spec));
  }

  /** Create a IntStepFunction from a List of Points */
  public IntStepFunction(List<Point> pointList) {
    if (pointList == null || pointList.isEmpty()) {
      throw new IllegalArgumentException("Must supply non-empty pointList");
    }
    points = new Point[pointList.size()];
    int ix = 0;
    for (Point p : pointList) {
      points[ix++] = p;
    }
  }

  /** Return the value of the function of X */
  public int getValue(int x) {
    if (x < points[0].x) {
      return 0;
    }
    Point p2 = points[0];
    for (int ix = 0; ix < points.length - 1; ix++) {
      Point p1 = p2;
      p2 = points[ix + 1];
      if (x < p2.x) {
        return p1.y;
      }
    }
    return p2.y;
  }

  // * Pattern picks off first x,y pair into group(1) and group(2) and rest
  // * of string into group(3) */
  static Pattern ONE_POINT_PAT =
      RegexpUtil.uncheckedCompile(
          "^\\s*,?\\s*\\[(\\d+)\\s*,\\s*(-?\\d+)\\](.*)$", Perl5Compiler.READ_ONLY_MASK);

  /** Parse a string of the form [x1,y1},[x2,y2},...,[xN,yN} into a list of Points ([int,int]) */
  public static List<Point> parseString(String str) throws NumberFormatException {
    if (StringUtil.isNullString(str)) {
      throw new IllegalArgumentException("Must supply non-empty string");
    }
    ArrayList<Point> res = new ArrayList<Point>();
    Perl5Matcher matcher = RegexpUtil.getMatcher();
    while (matcher.contains(str, ONE_POINT_PAT)) {
      MatchResult matchResult = matcher.getMatch();
      String xstr = matchResult.group(1);
      String ystr = matchResult.group(2);
      str = matchResult.group(3);
      try {
        int x = Integer.parseInt(xstr);
        int y = Integer.parseInt(ystr);
        res.add(new Point(x, y));
      } catch (NumberFormatException e) {
        throw new IllegalArgumentException("bad point [" + xstr + "," + ystr + "] in " + str);
      }
    }
    res.trimToSize();
    return res;
  }

  public String toString() {
    return "[CLS " + "[" + StringUtil.separatedString(points, ", ") + "]]";
  }
}
/**
 * Library of Congress password rules:
 *
 * <p>- The system must enforce a minimum password length of 8 characters for user passwords.
 *
 * <p>- The system must enforce at least three (3) of the following password complexity rules for
 * user passwords: (a) at least 1 upper case alphabetic character, (b) at least 1 lower case
 * alphabetic character, (c) at least 1 numeric character, (d) at least 1 special character.
 *
 * <p>- The system must prevent passwords with consecutive repeated characters for user accounts.
 *
 * <p>- The system must prevent the reuse of the 11 most recently used passwords for a particular
 * user account for user accounts.
 *
 * <p>- The system must prevent the user from changing his or her password more than one time per
 * day.
 *
 * <p>- The system must ensure that user passwords expire if not changed every sixty (60) days with
 * the exception of Public E-Authentication Level 1 or 2 systems, per NIST SP 800-63, which ensure
 * that user passwords expire if not changed annually.
 *
 * <p>- The system must provide a warning message seven (7) days before the user password expires
 */
public class LCUserAccount extends UserAccount {

  static final long MIN_PASSWORD_CHANGE_INTERVAL = 1 * Constants.DAY;
  static final long MAX_PASSWORD_CHANGE_INTERVAL = 60 * Constants.DAY;
  static final long PASSWORD_CHANGE_REMINDER_INTERVAL = 7 * Constants.DAY;

  static final long INACTIVITY_LOGOUT = 15 * Constants.MINUTE;
  static final int HISTORY_SIZE = 11;
  static final int MAX_FAILED_ATTEMPTS = 3;
  static final long MAX_FAILED_ATTEMPT_WINDOW = 15 * Constants.MINUTE;
  static final long MAX_FAILED_ATTEMPT_RESET_INTERVAL = 15 * Constants.MINUTE;

  static final String HASH_ALGORITHM = "SHA-256";

  public LCUserAccount(String name) {
    super(name);
  }

  public String getType() {
    return "LC";
  }

  protected int getHistorySize() {
    return HISTORY_SIZE;
  }

  protected String getDefaultHashAlgorithm() {
    return HASH_ALGORITHM;
  }

  public long getInactivityLogout() {
    return INACTIVITY_LOGOUT;
  }

  protected int getMinPasswordLength() {
    return 8;
  }

  protected long getMinPasswordChangeInterval() {
    return MIN_PASSWORD_CHANGE_INTERVAL;
  }

  protected long getMaxPasswordChangeInterval() {
    return MAX_PASSWORD_CHANGE_INTERVAL;
  }

  protected long getPasswordChangeReminderInterval() {
    return PASSWORD_CHANGE_REMINDER_INTERVAL;
  }

  protected int getMaxFailedAttempts() {
    return MAX_FAILED_ATTEMPTS;
  }

  protected long getFailedAttemptWindow() {
    return MAX_FAILED_ATTEMPT_WINDOW;
  }

  protected long getFailedAttemptResetInterval() {
    return MAX_FAILED_ATTEMPT_RESET_INTERVAL;
  }

  /** Return the hash algorithm to be used for new accounts */
  @Override
  protected void checkLegalPassword(String newPwd, String hash, boolean isAdmin)
      throws IllegalPasswordChange {
    super.checkLegalPassword(newPwd, hash, isAdmin);

    if (StringUtil.hasRepeatedChar(newPwd)) {
      throw new IllegalPassword("Password may not contain consecutive repeated characters");
    }
    if (!hasRequiredCharacterMix(newPwd)) {
      throw new IllegalPassword(
          "Password must contain mix of upper, lower, numeric and special characters");
    }
  }

  static Pattern[] charPats = {
    RegexpUtil.uncheckedCompile("[a-z]", Perl5Compiler.READ_ONLY_MASK),
    RegexpUtil.uncheckedCompile("[A-Z]", Perl5Compiler.READ_ONLY_MASK),
    RegexpUtil.uncheckedCompile("[0-9]", Perl5Compiler.READ_ONLY_MASK),
    RegexpUtil.uncheckedCompile("[" + SPECIAL_CHARS + "]", Perl5Compiler.READ_ONLY_MASK)
  };

  boolean hasRequiredCharacterMix(String str) {
    // Must have at least 3 of: upper alpha, lower alpha, numeric, special
    int cnt = 0;
    Perl5Matcher matcher = RegexpUtil.getMatcher();
    for (Pattern pat : charPats) {
      if (matcher.contains(str, pat)) {
        cnt++;
      }
    }
    return cnt >= 3;
  }

  public static class Factory extends UserAccount.Factory {
    public UserAccount newUser(String name, AccountManager acctMgr, Configuration config) {
      UserAccount acct = new LCUserAccount(name);
      acct.init(acctMgr, config);
      return acct;
    }
  }
}