0001: /*************************************************************************
0002: * *
0003: * EJBCA: The OpenSource Certificate Authority *
0004: * *
0005: * This software is free software; you can redistribute it and/or *
0006: * modify it under the terms of the GNU Lesser General Public *
0007: * License as published by the Free Software Foundation; either *
0008: * version 2.1 of the License, or any later version. *
0009: * *
0010: * See terms of license at gnu.org. *
0011: * *
0012: *************************************************************************/package org.ejbca.core.model.ra.raadmin;
0013:
0014: import java.text.DateFormat;
0015: import java.text.ParseException;
0016: import java.util.ArrayList;
0017: import java.util.Arrays;
0018: import java.util.Collection;
0019: import java.util.Collections;
0020: import java.util.Date;
0021: import java.util.HashMap;
0022: import java.util.Iterator;
0023: import java.util.List;
0024: import java.util.Locale;
0025: import java.util.Map;
0026: import java.util.Set;
0027:
0028: import org.apache.commons.lang.StringUtils;
0029: import org.apache.log4j.Logger;
0030: import org.ejbca.core.model.InternalResources;
0031: import org.ejbca.core.model.SecConst;
0032: import org.ejbca.core.model.UpgradeableDataHashMap;
0033: import org.ejbca.core.model.ra.ExtendedInformation;
0034: import org.ejbca.util.Base64;
0035: import org.ejbca.util.StringTools;
0036: import org.ejbca.util.dn.DNFieldExtractor;
0037: import org.ejbca.util.dn.DnComponents;
0038: import org.ejbca.util.passgen.PasswordGeneratorFactory;
0039:
0040: /**
0041: * The model representation of an end entity profile, used in in the ra module
0042: * of ejbca web interface.
0043: *
0044: * The algorithm for constants in the EndEntityProfile is:
0045: * Values are stored as 100*parameternumber+parameter, so the first COMMONNAME value is 105, the second 205 etc.
0046: * Use flags are stored as 10000+100*parameternumber+parameter, so the first USE_COMMONNAME value is 10105, the second 10205 etc.
0047: * Required flags are stored as 20000+100*parameternumber+parameter, so the first REQUIRED_COMMONNAME value is 20105, the second 20205 etc.
0048: * Modifyable flags are stored as 30000+100*parameternumber+parameter, so the first MODIFYABLE_COMMONNAME value is 30105, the second 30205 etc.
0049: *
0050: *
0051: * @author Philip Vendil
0052: * @version $Id: EndEntityProfile.java,v 1.28 2008/01/03 12:52:41 anatom Exp $
0053: */
0054: public class EndEntityProfile extends UpgradeableDataHashMap implements
0055: java.io.Serializable, Cloneable {
0056:
0057: private static final Logger log = Logger
0058: .getLogger(EndEntityProfile.class);
0059: /** Internal localization of logs and errors */
0060: private static final InternalResources intres = InternalResources
0061: .getInstance();
0062:
0063: public static final float LATEST_VERSION = 9;
0064:
0065: /**
0066: * Determines if a de-serialized file is compatible with this class.
0067: *
0068: * Maintainers must change this value if and only if the new version
0069: * of this class is not compatible with old versions. See Sun docs
0070: * for <a href=http://java.sun.com/products/jdk/1.1/docs/guide
0071: * /serialization/spec/version.doc.html> details. </a>
0072: *
0073: */
0074: private static final long serialVersionUID = -8356152324295231462L;
0075:
0076: // Public constants
0077: /** Constant values for end entity profile. */
0078: private static HashMap dataConstants = new HashMap();
0079:
0080: // Default values
0081: // These must be in a strict order that can never change
0082: // Custom values configurable in a properties file will start at number 100
0083: static {
0084: dataConstants.put("USERNAME", new Integer(0));
0085: dataConstants.put("PASSWORD", new Integer(1));
0086: dataConstants.put("CLEARTEXTPASSWORD", new Integer(2));
0087: // DN components
0088: /* These are loaded through DnComponents instead
0089: dataConstants.put(DnComponents.DNEMAIL, Integer.valueOf(3));
0090: dataConstants.put(DnComponents.UID, Integer.valueOf(4));
0091: dataConstants.put(DnComponents.COMMONNAME, Integer.valueOf(5));
0092: dataConstants.put(DnComponents.SN, Integer.valueOf(6));
0093: dataConstants.put(DnComponents.GIVENNAME, Integer.valueOf(7));
0094: dataConstants.put(DnComponents.INITIALS, Integer.valueOf(8));
0095: dataConstants.put(DnComponents.SURNAME, Integer.valueOf(9));
0096: dataConstants.put(DnComponents.TITLE, Integer.valueOf(10));
0097: dataConstants.put(DnComponents.ORGANIZATIONUNIT, Integer.valueOf(11));
0098: dataConstants.put(DnComponents.ORGANIZATION, Integer.valueOf(12));
0099: dataConstants.put(DnComponents.LOCALE, Integer.valueOf(13));
0100: dataConstants.put(DnComponents.STATE, Integer.valueOf(14));
0101: dataConstants.put(DnComponents.DOMAINCOMPONENT, Integer.valueOf(15));
0102: dataConstants.put(DnComponents.COUNTRY, Integer.valueOf(16));
0103:
0104: dataConstants.put(DnComponents.UNSTRUCTUREDADDRESS, Integer.valueOf(39));
0105: dataConstants.put(DnComponents.UNSTRUCTUREDNAME, Integer.valueOf(40));
0106: // AltNames
0107: dataConstants.put(DnComponents.RFC822NAME, Integer.valueOf(17));
0108: dataConstants.put(DnComponents.DNSNAME, Integer.valueOf(18));
0109: dataConstants.put(DnComponents.IPADDRESS, Integer.valueOf(19));
0110: dataConstants.put(DnComponents.OTHERNAME, Integer.valueOf(20));
0111: dataConstants.put(DnComponents.UNIFORMRESOURCEID, Integer.valueOf(21));
0112: dataConstants.put(DnComponents.X400ADDRESS, Integer.valueOf(22));
0113: dataConstants.put(DnComponents.DIRECTORYNAME, Integer.valueOf(23));
0114: dataConstants.put(DnComponents.EDIPARTNAME, Integer.valueOf(24));
0115: dataConstants.put(DnComponents.REGISTEREDID, Integer.valueOf(25));
0116:
0117: dataConstants.put(DnComponents.UPN, Integer.valueOf(36));
0118:
0119: dataConstants.put(DnComponents.GUID, Integer.valueOf(41));
0120: // Altnames end
0121: // Subject directory attributes
0122: dataConstants.put(DnComponents.DATEOFBIRTH, Integer.valueOf(42));
0123: dataConstants.put(DnComponents.PLACEOFBIRTH, Integer.valueOf(43));
0124: dataConstants.put(DnComponents.GENDER, Integer.valueOf(44));
0125: dataConstants.put(DnComponents.COUNTRYOFCITIZENSHIP, Integer.valueOf(45));
0126: dataConstants.put(DnComponents.COUNTRYOFRESIDENCE, Integer.valueOf(46));
0127: // Subject directory attributes end
0128: */
0129: dataConstants.put("EMAIL", new Integer(26));
0130: dataConstants.put("ADMINISTRATOR", new Integer(27));
0131: dataConstants.put("KEYRECOVERABLE", new Integer(28));
0132: dataConstants.put("DEFAULTCERTPROFILE", new Integer(29));
0133: dataConstants.put("AVAILCERTPROFILES", new Integer(30));
0134: dataConstants.put("DEFKEYSTORE", new Integer(31));
0135: dataConstants.put("AVAILKEYSTORE", new Integer(32));
0136: dataConstants.put("DEFAULTTOKENISSUER", new Integer(33));
0137: dataConstants.put("AVAILTOKENISSUER", new Integer(34));
0138: dataConstants.put("SENDNOTIFICATION", new Integer(35));
0139:
0140: dataConstants.put("DEFAULTCA", new Integer(37));
0141: dataConstants.put("AVAILCAS", new Integer(38));
0142:
0143: // Load all DN, altName and directoryAttributes from DnComponents.
0144: dataConstants.putAll(DnComponents.getProfilenameIdMap());
0145:
0146: dataConstants.put("ALLOWEDREQUESTS", new Integer(97));
0147: dataConstants.put("STARTTIME", new Integer(98));
0148: dataConstants.put("ENDTIME", new Integer(99));
0149: }
0150: // Type of data constants.
0151: private static final int VALUE = 0;
0152: private static final int USE = 1;
0153: private static final int ISREQUIRED = 2;
0154: private static final int MODIFYABLE = 3;
0155:
0156: // Field constants, used in the map above
0157: public static final String USERNAME = "USERNAME";
0158: public static final String PASSWORD = "PASSWORD";
0159: public static final String CLEARTEXTPASSWORD = "CLEARTEXTPASSWORD";
0160:
0161: public static final String EMAIL = "EMAIL";
0162: public static final String ADMINISTRATOR = "ADMINISTRATOR";
0163: public static final String KEYRECOVERABLE = "KEYRECOVERABLE";
0164: public static final String DEFAULTCERTPROFILE = "DEFAULTCERTPROFILE";
0165: /** A list of available certificate profile names can be retrieved with getAvailableCertificateProfileNames() */
0166: public static final String AVAILCERTPROFILES = "AVAILCERTPROFILES";
0167: public static final String DEFKEYSTORE = "DEFKEYSTORE";
0168: public static final String AVAILKEYSTORE = "AVAILKEYSTORE";
0169: public static final String DEFAULTTOKENISSUER = "DEFAULTTOKENISSUER";
0170: public static final String AVAILTOKENISSUER = "AVAILTOKENISSUER";
0171: public static final String SENDNOTIFICATION = "SENDNOTIFICATION";
0172: public static final String DEFAULTCA = "DEFAULTCA";
0173: public static final String AVAILCAS = "AVAILCAS";
0174: public static final String STARTTIME = "STARTTIME";
0175: public static final String ENDTIME = "ENDTIME";
0176: /** A maximum value of the (optional) counter specifying how many certificate requests can be processed
0177: * before user is finalized (status set to GENERATED). Counter is only used when finishUser is
0178: * enabled in the CA (by default it is)
0179: */
0180: public static final String ALLOWEDREQUESTS = "ALLOWEDREQUESTS";
0181:
0182: public static final String SPLITCHAR = ";";
0183:
0184: public static final String TRUE = "true";
0185: public static final String FALSE = "false";
0186:
0187: // Constants used with field ordering
0188: public static final int FIELDTYPE = 0;
0189: public static final int NUMBER = 1;
0190:
0191: // Public methods.
0192: /** Creates a new instance of EndEntity Profile */
0193: public EndEntityProfile() {
0194: super ();
0195:
0196: // Set default required fields.
0197: init(false);
0198: }
0199:
0200: /** Creates a default empty end entity profile with all standard fields added to it. */
0201: public EndEntityProfile(boolean emptyprofile) {
0202: super ();
0203:
0204: init(emptyprofile);
0205: }
0206:
0207: private void init(boolean emptyprofile) {
0208: if (emptyprofile) {
0209: // initialize profile data
0210: ArrayList numberoffields = new ArrayList(dataConstants
0211: .size());
0212: for (int i = 0; i < dataConstants.size(); i++) {
0213: numberoffields.add(new Integer(0));
0214: }
0215: data.put(NUMBERARRAY, numberoffields);
0216: data.put(SUBJECTDNFIELDORDER, new ArrayList());
0217: data.put(SUBJECTALTNAMEFIELDORDER, new ArrayList());
0218: data.put(SUBJECTDIRATTRFIELDORDER, new ArrayList());
0219:
0220: Set keySet = dataConstants.keySet();
0221: Iterator iter = keySet.iterator();
0222: while (iter.hasNext()) {
0223: String key = (String) iter.next();
0224: if (key.equals(SENDNOTIFICATION)
0225: || key.equals(DnComponents.OTHERNAME)
0226: || key.equals(DnComponents.X400ADDRESS)
0227: || key.equals(DnComponents.EDIPARTNAME)
0228: || key.equals(DnComponents.REGISTEREDID)) {
0229: continue;
0230: } else {
0231: addField(key);
0232: setValue(key, 0, "");
0233: setRequired(key, 0, false);
0234: setUse(key, 0, true);
0235: setModifyable(key, 0, true);
0236: }
0237: }
0238: setRequired(USERNAME, 0, true);
0239: setRequired(PASSWORD, 0, true);
0240: setRequired(DnComponents.COMMONNAME, 0, true);
0241: setRequired(DEFAULTCERTPROFILE, 0, true);
0242: setRequired(AVAILCERTPROFILES, 0, true);
0243: setRequired(DEFKEYSTORE, 0, true);
0244: setRequired(AVAILKEYSTORE, 0, true);
0245: setRequired(DEFAULTCA, 0, true);
0246: setRequired(AVAILCAS, 0, true);
0247: setRequired(STARTTIME, 0, false);
0248: setRequired(ENDTIME, 0, false);
0249: setRequired(ALLOWEDREQUESTS, 0, false);
0250: setValue(DEFAULTCERTPROFILE, 0, "1");
0251: setValue(AVAILCERTPROFILES, 0, "1");
0252: setValue(DEFKEYSTORE, 0, ""
0253: + SecConst.TOKEN_SOFT_BROWSERGEN);
0254: setValue(AVAILKEYSTORE, 0, SecConst.TOKEN_SOFT_BROWSERGEN
0255: + ";" + SecConst.TOKEN_SOFT_P12 + ";"
0256: + SecConst.TOKEN_SOFT_JKS + ";"
0257: + SecConst.TOKEN_SOFT_PEM);
0258: setValue(AVAILCAS, 0, Integer.toString(SecConst.ALLCAS));
0259: // Do not use hard token issuers by default.
0260: setUse(AVAILTOKENISSUER, 0, false);
0261: setUse(STARTTIME, 0, false);
0262: setUse(ENDTIME, 0, false);
0263: setUse(ALLOWEDREQUESTS, 0, false);
0264: } else {
0265: // initialize profile data
0266: ArrayList numberoffields = new ArrayList(dataConstants
0267: .size());
0268: for (int i = 0; i < dataConstants.size(); i++) {
0269: numberoffields.add(new Integer(0));
0270: }
0271:
0272: data.put(NUMBERARRAY, numberoffields);
0273: data.put(SUBJECTDNFIELDORDER, new ArrayList());
0274: data.put(SUBJECTALTNAMEFIELDORDER, new ArrayList());
0275: data.put(SUBJECTDIRATTRFIELDORDER, new ArrayList());
0276:
0277: addField(USERNAME);
0278: addField(PASSWORD);
0279: addField(DnComponents.COMMONNAME);
0280: addField(EMAIL);
0281: addField(DEFAULTCERTPROFILE);
0282: addField(AVAILCERTPROFILES);
0283: addField(DEFKEYSTORE);
0284: addField(AVAILKEYSTORE);
0285: addField(DEFAULTTOKENISSUER);
0286: addField(AVAILTOKENISSUER);
0287: addField(AVAILCAS);
0288: addField(DEFAULTCA);
0289: addField(STARTTIME);
0290: addField(ENDTIME);
0291: addField(ALLOWEDREQUESTS);
0292:
0293: setRequired(USERNAME, 0, true);
0294: setRequired(PASSWORD, 0, true);
0295: setRequired(DnComponents.COMMONNAME, 0, true);
0296: setRequired(DEFAULTCERTPROFILE, 0, true);
0297: setRequired(AVAILCERTPROFILES, 0, true);
0298: setRequired(DEFKEYSTORE, 0, true);
0299: setRequired(AVAILKEYSTORE, 0, true);
0300: setRequired(DEFAULTCA, 0, true);
0301: setRequired(AVAILCAS, 0, true);
0302: setRequired(STARTTIME, 0, false);
0303: setRequired(ENDTIME, 0, false);
0304: setRequired(ALLOWEDREQUESTS, 0, false);
0305:
0306: setValue(DEFAULTCERTPROFILE, 0, "1");
0307: setValue(AVAILCERTPROFILES, 0, "1;2;3");
0308: setValue(DEFKEYSTORE, 0, ""
0309: + SecConst.TOKEN_SOFT_BROWSERGEN);
0310: setValue(AVAILKEYSTORE, 0, SecConst.TOKEN_SOFT_BROWSERGEN
0311: + ";" + SecConst.TOKEN_SOFT_P12 + ";"
0312: + SecConst.TOKEN_SOFT_JKS + ";"
0313: + SecConst.TOKEN_SOFT_PEM);
0314:
0315: // Do not use hard token issuers by default.
0316: setUse(AVAILTOKENISSUER, 0, false);
0317: setUse(STARTTIME, 0, false);
0318: setUse(ENDTIME, 0, false);
0319: setUse(ALLOWEDREQUESTS, 0, false);
0320: }
0321: }
0322:
0323: public void addField(String parameter) {
0324: addField(getParameterNumber(parameter));
0325: }
0326:
0327: /**
0328: * Function that adds a field to the profile.
0329: *
0330: * @param paramter is the field and one of the field constants.
0331: */
0332: public void addField(int parameter) {
0333: int size = getNumberOfField(parameter);
0334: setValue(parameter, size, "");
0335: setRequired(parameter, size, false);
0336: setUse(parameter, size, true);
0337: setModifyable(parameter, size, true);
0338: String param = getParameter(parameter);
0339: ArrayList dns = DnComponents.getDnProfileFields();
0340: if (dns.contains(param)) {
0341: ArrayList fieldorder = (ArrayList) data
0342: .get(SUBJECTDNFIELDORDER);
0343: fieldorder.add(new Integer((NUMBERBOUNDRARY * parameter)
0344: + size));
0345: Collections.sort(fieldorder);
0346: }
0347: ArrayList altNames = DnComponents.getAltNameFields();
0348: if (altNames.contains(param)) {
0349: ArrayList fieldorder = (ArrayList) data
0350: .get(SUBJECTALTNAMEFIELDORDER);
0351: fieldorder.add(new Integer((NUMBERBOUNDRARY * parameter)
0352: + size));
0353: }
0354: ArrayList dirAttrs = DnComponents.getDirAttrFields();
0355: if (dirAttrs.contains(param)) {
0356: ArrayList fieldorder = (ArrayList) data
0357: .get(SUBJECTDIRATTRFIELDORDER);
0358: fieldorder.add(new Integer((NUMBERBOUNDRARY * parameter)
0359: + size));
0360: }
0361: incrementFieldnumber(parameter);
0362: }
0363:
0364: public void removeField(String parameter, int number) {
0365: removeField(getParameterNumber(parameter), number);
0366: }
0367:
0368: /**
0369: * Function that removes a field from the end entity profile.
0370: *
0371: * @param parameter is the field to remove.
0372: * @param number is the number of field.
0373: */
0374: public void removeField(int parameter, int number) {
0375: // Remove field and move all fileds above.
0376: int size = getNumberOfField(parameter);
0377:
0378: if (size > 0) {
0379: for (int n = number; n < size - 1; n++) {
0380: setValue(parameter, n, getValue(parameter, n + 1));
0381: setRequired(parameter, n, isRequired(parameter, n + 1));
0382: setUse(parameter, n, getUse(parameter, n + 1));
0383: setModifyable(parameter, n, isModifyable(parameter,
0384: n + 1));
0385: }
0386:
0387: String param = getParameter(parameter);
0388: // Remove last element from Subject DN order list.
0389: ArrayList dns = DnComponents.getDnProfileFields();
0390: if (dns.contains(param)) {
0391: ArrayList fieldorder = (ArrayList) data
0392: .get(SUBJECTDNFIELDORDER);
0393: int value = (NUMBERBOUNDRARY * parameter) + size - 1;
0394: for (int i = 0; i < fieldorder.size(); i++) {
0395: if (value == ((Integer) fieldorder.get(i))
0396: .intValue()) {
0397: fieldorder.remove(i);
0398: break;
0399: }
0400: }
0401: }
0402: // Remove last element from Subject AltName order list.
0403: ArrayList altNames = DnComponents.getAltNameFields();
0404: if (altNames.contains(param)) {
0405: ArrayList fieldorder = (ArrayList) data
0406: .get(SUBJECTALTNAMEFIELDORDER);
0407: int value = (NUMBERBOUNDRARY * parameter) + size - 1; //number;
0408: for (int i = 0; i < fieldorder.size(); i++) {
0409: if (value == ((Integer) fieldorder.get(i))
0410: .intValue()) {
0411: fieldorder.remove(i);
0412: break;
0413: }
0414: }
0415: }
0416: // Remove last element from Subject DirAttr order list.
0417: ArrayList dirAttrs = DnComponents.getDirAttrFields();
0418: if (dirAttrs.contains(param)) {
0419: ArrayList fieldorder = (ArrayList) data
0420: .get(SUBJECTDIRATTRFIELDORDER);
0421: int value = (NUMBERBOUNDRARY * parameter) + size - 1; //number;
0422: for (int i = 0; i < fieldorder.size(); i++) {
0423: if (value == ((Integer) fieldorder.get(i))
0424: .intValue()) {
0425: fieldorder.remove(i);
0426: break;
0427: }
0428: }
0429: }
0430: // Remove last element of the type from hashmap
0431: data.remove(new Integer((VALUE * FIELDBOUNDRARY)
0432: + (NUMBERBOUNDRARY * (size - 1)) + parameter));
0433: data.remove(new Integer((USE * FIELDBOUNDRARY)
0434: + (NUMBERBOUNDRARY * (size - 1)) + parameter));
0435: data.remove(new Integer((ISREQUIRED * FIELDBOUNDRARY)
0436: + (NUMBERBOUNDRARY * (size - 1)) + parameter));
0437: data.remove(new Integer((MODIFYABLE * FIELDBOUNDRARY)
0438: + (NUMBERBOUNDRARY * (size - 1)) + parameter));
0439:
0440: decrementFieldnumber(parameter);
0441: }
0442: }
0443:
0444: /**
0445: * Function that returns the number of one kind of field.
0446: *
0447: */
0448: public int getNumberOfField(String parameter) {
0449: return getNumberOfField(getParameterNumber(parameter));
0450: }
0451:
0452: public int getNumberOfField(int parameter) {
0453: ArrayList arr = (ArrayList) data.get(NUMBERARRAY);
0454: // This is an automatic upgrade function, if we have dynamically added new fields
0455: if (parameter >= arr.size()) {
0456: String msg = intres.getLocalizedMessage(
0457: "ra.eeprofileaddfield", new Integer(parameter));
0458: log.debug(msg);
0459: for (int i = arr.size(); i <= parameter; i++) {
0460: arr.add(new Integer(0));
0461: }
0462: data.put(NUMBERARRAY, arr);
0463: }
0464: return ((Integer) arr.get(parameter)).intValue();
0465: }
0466:
0467: public void setValue(int parameter, int number, String value) {
0468: if (value != null) {
0469: value = value.trim();
0470: data.put(new Integer((VALUE * FIELDBOUNDRARY)
0471: + (NUMBERBOUNDRARY * number) + parameter), value);
0472: } else {
0473: data.put(new Integer((VALUE * FIELDBOUNDRARY)
0474: + (NUMBERBOUNDRARY * number) + parameter), "");
0475: }
0476: }
0477:
0478: public void setValue(String parameter, int number, String value) {
0479: setValue(getParameterNumber(parameter), number, value);
0480: }
0481:
0482: public void setUse(int parameter, int number, boolean use) {
0483: data.put(new Integer((USE * FIELDBOUNDRARY)
0484: + (NUMBERBOUNDRARY * number) + parameter), Boolean
0485: .valueOf(use));
0486: }
0487:
0488: public void setUse(String parameter, int number, boolean use) {
0489: setUse(getParameterNumber(parameter), number, use);
0490: }
0491:
0492: public void setRequired(int parameter, int number,
0493: boolean isrequired) {
0494: data.put(new Integer((ISREQUIRED * FIELDBOUNDRARY)
0495: + (NUMBERBOUNDRARY * number) + parameter), Boolean
0496: .valueOf(isrequired));
0497: }
0498:
0499: public void setRequired(String parameter, int number,
0500: boolean isrequired) {
0501: setRequired(getParameterNumber(parameter), number, isrequired);
0502: }
0503:
0504: public void setModifyable(int parameter, int number,
0505: boolean changeable) {
0506: data.put(new Integer((MODIFYABLE * FIELDBOUNDRARY)
0507: + (NUMBERBOUNDRARY * number) + parameter), Boolean
0508: .valueOf(changeable));
0509: }
0510:
0511: public void setModifyable(String parameter, int number,
0512: boolean changeable) {
0513: setModifyable(getParameterNumber(parameter), number, changeable);
0514: }
0515:
0516: public String getValue(int parameter, int number) {
0517: String returnval = (String) data.get(new Integer(
0518: (VALUE * FIELDBOUNDRARY) + (NUMBERBOUNDRARY * number)
0519: + parameter));
0520: if (returnval != null)
0521: return returnval;
0522: return "";
0523: }
0524:
0525: public String getValue(String parameter, int number) {
0526: return getValue(getParameterNumber(parameter), number);
0527: }
0528:
0529: public boolean getUse(int parameter, int number) {
0530: Boolean returnval = (Boolean) data.get(new Integer(
0531: (USE * FIELDBOUNDRARY) + (NUMBERBOUNDRARY * number)
0532: + parameter));
0533: if (returnval != null)
0534: return returnval.booleanValue();
0535: return false;
0536: }
0537:
0538: public boolean getUse(String parameter, int number) {
0539: return getUse(getParameterNumber(parameter), number);
0540: }
0541:
0542: public boolean isRequired(int parameter, int number) {
0543: Boolean returnval = (Boolean) data.get(new Integer(
0544: (ISREQUIRED * FIELDBOUNDRARY)
0545: + (NUMBERBOUNDRARY * number) + parameter));
0546: if (returnval != null)
0547: return returnval.booleanValue();
0548: return false;
0549: }
0550:
0551: public boolean isRequired(String parameter, int number) {
0552: return isRequired(getParameterNumber(parameter), number);
0553: }
0554:
0555: public boolean isModifyable(int parameter, int number) {
0556: Boolean returnval = (Boolean) data.get(new Integer(
0557: (MODIFYABLE * FIELDBOUNDRARY)
0558: + (NUMBERBOUNDRARY * number) + parameter));
0559: if (returnval != null)
0560: return returnval.booleanValue();
0561: return false;
0562: }
0563:
0564: public boolean isModifyable(String parameter, int number) {
0565: return isModifyable(getParameterNumber(parameter), number);
0566: }
0567:
0568: public int getSubjectDNFieldOrderLength() {
0569: return ((ArrayList) data.get(SUBJECTDNFIELDORDER)).size();
0570: }
0571:
0572: public int getSubjectAltNameFieldOrderLength() {
0573: return ((ArrayList) data.get(SUBJECTALTNAMEFIELDORDER)).size();
0574: }
0575:
0576: public int getSubjectDirAttrFieldOrderLength() {
0577: return ((ArrayList) data.get(SUBJECTDIRATTRFIELDORDER)).size();
0578: }
0579:
0580: /** returns two int : the first is the DN field which is a constant in DN field extractor,
0581: * the second is in which order the attribute is, 0 is first OU and 1 can mean second OU (if OU is specified in the first value).
0582: *
0583: */
0584: public int[] getSubjectDNFieldsInOrder(int index) {
0585: int[] returnval = new int[2];
0586: ArrayList fieldorder = (ArrayList) data
0587: .get(SUBJECTDNFIELDORDER);
0588: returnval[NUMBER] = ((Integer) fieldorder.get(index))
0589: .intValue()
0590: % NUMBERBOUNDRARY;
0591: returnval[FIELDTYPE] = ((Integer) fieldorder.get(index))
0592: .intValue()
0593: / NUMBERBOUNDRARY;
0594:
0595: return returnval;
0596: }
0597:
0598: public int[] getSubjectAltNameFieldsInOrder(int index) {
0599: int[] returnval = new int[2];
0600: ArrayList fieldorder = (ArrayList) data
0601: .get(SUBJECTALTNAMEFIELDORDER);
0602: returnval[NUMBER] = ((Integer) fieldorder.get(index))
0603: .intValue()
0604: % NUMBERBOUNDRARY;
0605: returnval[FIELDTYPE] = ((Integer) fieldorder.get(index))
0606: .intValue()
0607: / NUMBERBOUNDRARY;
0608:
0609: return returnval;
0610: }
0611:
0612: public int[] getSubjectDirAttrFieldsInOrder(int index) {
0613: int[] returnval = new int[2];
0614: ArrayList fieldorder = (ArrayList) data
0615: .get(SUBJECTDIRATTRFIELDORDER);
0616: returnval[NUMBER] = ((Integer) fieldorder.get(index))
0617: .intValue()
0618: % NUMBERBOUNDRARY;
0619: returnval[FIELDTYPE] = ((Integer) fieldorder.get(index))
0620: .intValue()
0621: / NUMBERBOUNDRARY;
0622:
0623: return returnval;
0624: }
0625:
0626: /** Gets a Collection of available CA Ids (as Strings).
0627: * Use String.valueOf(caidstring) to get the int value of the CA id.
0628: *
0629: * @return a Collection of String, where the string is an integer.
0630: */
0631: public Collection getAvailableCAs() {
0632: ArrayList availablecaids = new ArrayList();
0633: availablecaids.addAll(Arrays.asList(getValue(AVAILCAS, 0)
0634: .split(SPLITCHAR)));
0635: return availablecaids;
0636: }
0637:
0638: /** Gets a Collection of available certificate profile ids
0639: * Use String.valueOf(caidstring) to get the int value
0640: *
0641: * @return a Collection of String, where the string is an integer.
0642: */
0643: public Collection getAvailableCertificateProfileIds() {
0644: ArrayList profiles = new ArrayList();
0645: String list = getValue(AVAILCERTPROFILES, 0);
0646: if (list != null) {
0647: profiles.addAll(Arrays.asList(list.split(SPLITCHAR)));
0648: }
0649: return profiles;
0650: }
0651:
0652: public int getDefaultCA() {
0653: int ret = -1;
0654: String str = getValue(DEFAULTCA, 0);
0655: if (str != null) {
0656: ret = Integer.valueOf(str);
0657: }
0658: return ret;
0659: }
0660:
0661: public boolean useAutoGeneratedPasswd() {
0662: return !this .getUse(EndEntityProfile.PASSWORD, 0);
0663: }
0664:
0665: public String getAutoGeneratedPasswd() {
0666: return PasswordGeneratorFactory.getInstance(
0667: PasswordGeneratorFactory.PASSWORDTYPE_LETTERSANDDIGITS)
0668: .getNewPassword(8, 8);
0669: }
0670:
0671: // User notifications - begin
0672: public List getUserNotifications() {
0673: List l = (List) data.get(USERNOTIFICATIONS);
0674: if (l == null) {
0675: l = new ArrayList();
0676: }
0677: return l;
0678: }
0679:
0680: public void addUserNotification(UserNotification notification) {
0681: if (data.get(USERNOTIFICATIONS) == null) {
0682: setUserNotifications(new ArrayList(0));
0683: }
0684: ((List) data.get(USERNOTIFICATIONS)).add(notification);
0685: }
0686:
0687: public void setUserNotifications(List notifications) {
0688: if (notifications == null) {
0689: data.put(USERNOTIFICATIONS, new ArrayList(0));
0690: } else {
0691: data.put(USERNOTIFICATIONS, notifications);
0692: }
0693: }
0694:
0695: public void removeUserNotification(UserNotification notification) {
0696: if (data.get(USERNOTIFICATIONS) != null) {
0697: ((List) data.get(USERNOTIFICATIONS)).remove(notification);
0698: }
0699: }
0700:
0701: // User notifications - end
0702:
0703: /**
0704: * @return indicationg if the keyreccovered certificate should be reused or not.
0705: */
0706: public boolean getReUseKeyRevoceredCertificate() {
0707: if (data.get(REUSECERTIFICATE) == null) {
0708: return false;
0709: }
0710:
0711: return ((Boolean) data.get(REUSECERTIFICATE)).booleanValue();
0712: }
0713:
0714: public void setReUseKeyRevoceredCertificate(boolean reuse) {
0715: data.put(REUSECERTIFICATE, new Boolean(reuse));
0716: }
0717:
0718: /**
0719: * @return indicationg if the profile checks should be reversed or not.
0720: * default is false.
0721: */
0722: public boolean getReverseFieldChecks() {
0723: if (data.get(REVERSEFFIELDCHECKS) == null) {
0724: return false;
0725: }
0726:
0727: return ((Boolean) data.get(REVERSEFFIELDCHECKS)).booleanValue();
0728: }
0729:
0730: public void setReverseFieldChecks(boolean reverse) {
0731: data.put(REVERSEFFIELDCHECKS, new Boolean(reverse));
0732: }
0733:
0734: /**
0735: * @return indicationg printing of userdata should be done
0736: * default is false.
0737: */
0738: public boolean getUsePrinting() {
0739: if (data.get(PRINTINGUSE) == null) {
0740: return false;
0741: }
0742:
0743: return ((Boolean) data.get(PRINTINGUSE)).booleanValue();
0744: }
0745:
0746: public void setUsePrinting(boolean use) {
0747: data.put(PRINTINGUSE, new Boolean(use));
0748: }
0749:
0750: /**
0751: * @return indicationg printing of userdata should be done
0752: * default is false.
0753: */
0754: public boolean getPrintingDefault() {
0755: if (data.get(PRINTINGDEFAULT) == null) {
0756: return false;
0757: }
0758:
0759: return ((Boolean) data.get(PRINTINGDEFAULT)).booleanValue();
0760: }
0761:
0762: public void setPrintingDefault(boolean printDefault) {
0763: data.put(PRINTINGDEFAULT, new Boolean(printDefault));
0764: }
0765:
0766: /**
0767: * @return indicationg printing of userdata should be done
0768: * default is false.
0769: */
0770: public boolean getPrintingRequired() {
0771: if (data.get(PRINTINGREQUIRED) == null) {
0772: return false;
0773: }
0774: return ((Boolean) data.get(PRINTINGREQUIRED)).booleanValue();
0775: }
0776:
0777: public void setPrintingRequired(boolean printRequired) {
0778: data.put(PRINTINGREQUIRED, new Boolean(printRequired));
0779: }
0780:
0781: /**
0782: * @return the number of copies that should be printed
0783: * default is 1.
0784: */
0785: public int getPrintedCopies() {
0786: if (data.get(PRINTINGCOPIES) == null) {
0787: return 1;
0788: }
0789:
0790: return ((Integer) data.get(PRINTINGCOPIES)).intValue();
0791: }
0792:
0793: public void setPrintedCopies(int copies) {
0794: data.put(PRINTINGCOPIES, new Integer(copies));
0795: }
0796:
0797: /**
0798: * @return the name of the printer that should be used
0799: */
0800: public String getPrinterName() {
0801: if (data.get(PRINTINGPRINTERNAME) == null) {
0802: return "";
0803: }
0804:
0805: return (String) data.get(PRINTINGPRINTERNAME);
0806: }
0807:
0808: public void setPrinterName(String printerName) {
0809: data.put(PRINTINGPRINTERNAME, printerName);
0810: }
0811:
0812: /**
0813: * @return filename of the uploaded
0814: */
0815: public String getPrinterSVGFileName() {
0816: if (data.get(PRINTINGSVGFILENAME) == null) {
0817: return "";
0818: }
0819:
0820: return (String) data.get(PRINTINGSVGFILENAME);
0821: }
0822:
0823: public void setPrinterSVGFileName(String printerSVGFileName) {
0824: data.put(PRINTINGSVGFILENAME, printerSVGFileName);
0825: }
0826:
0827: /**
0828: * @return the data of the SVG file, if no content have
0829: * been uploaded null is returned
0830: */
0831: public String getPrinterSVGData() {
0832: if (data.get(PRINTINGSVGDATA) == null) {
0833: return null;
0834: }
0835:
0836: return new String(Base64.decode(((String) data
0837: .get(PRINTINGSVGDATA)).getBytes()));
0838: }
0839:
0840: public void setPrinterSVGData(String sVGData) {
0841: data.put(PRINTINGSVGDATA, new String(Base64.encode(sVGData
0842: .getBytes())));
0843: }
0844:
0845: public void doesUserFullfillEndEntityProfile(String username,
0846: String password, String dn, String subjectaltname,
0847: String subjectdirattr, String email,
0848: int certificateprofileid, boolean clearpwd,
0849: boolean administrator, boolean keyrecoverable,
0850: boolean sendnotification, int tokentype,
0851: int hardwaretokenissuerid, int caid, ExtendedInformation ei)
0852: throws UserDoesntFullfillEndEntityProfile {
0853:
0854: if (useAutoGeneratedPasswd()) {
0855: if (password != null)
0856: throw new UserDoesntFullfillEndEntityProfile(
0857: "Autogenerated password must have password==null");
0858: } else {
0859: if (!isModifyable(PASSWORD, 0)) {
0860: if (!password.equals(getValue(PASSWORD, 0)))
0861: throw new UserDoesntFullfillEndEntityProfile(
0862: "Password didn't match requirement of it's profile.");
0863: } else if (isRequired(PASSWORD, 0)) {
0864: if (password == null || password.trim().equals(""))
0865: throw new UserDoesntFullfillEndEntityProfile(
0866: "Password cannot be empty or null.");
0867: }
0868: }
0869:
0870: if (!getUse(CLEARTEXTPASSWORD, 0) && clearpwd)
0871: throw new UserDoesntFullfillEndEntityProfile(
0872: "Clearpassword (used in batch proccessing) cannot be used.");
0873:
0874: if (isRequired(CLEARTEXTPASSWORD, 0)) {
0875: if (getValue(CLEARTEXTPASSWORD, 0).equals(TRUE)
0876: && !clearpwd)
0877: throw new UserDoesntFullfillEndEntityProfile(
0878: "Clearpassword (used in batch proccessing) cannot be false.");
0879: if (getValue(CLEARTEXTPASSWORD, 0).equals(FALSE)
0880: && clearpwd)
0881: throw new UserDoesntFullfillEndEntityProfile(
0882: "Clearpassword (used in batch proccessing) cannot be true.");
0883: }
0884:
0885: doesUserFullfillEndEntityProfileWithoutPassword(username, dn,
0886: subjectaltname, subjectdirattr, email,
0887: certificateprofileid, administrator, keyrecoverable,
0888: sendnotification, tokentype, hardwaretokenissuerid,
0889: caid, ei);
0890:
0891: }
0892:
0893: public void doesUserFullfillEndEntityProfileWithoutPassword(
0894: String username, String dn, String subjectaltname,
0895: String subjectdirattr, String email,
0896: int certificateprofileid, boolean administrator,
0897: boolean keyrecoverable, boolean sendnotification,
0898: int tokentype, int hardwaretokenissuerid, int caid,
0899: ExtendedInformation ei)
0900: throws UserDoesntFullfillEndEntityProfile {
0901: DNFieldExtractor subjectdnfields = new DNFieldExtractor(dn,
0902: DNFieldExtractor.TYPE_SUBJECTDN);
0903: if (subjectdnfields.isIllegal()) {
0904: throw new UserDoesntFullfillEndEntityProfile(
0905: "Subject DN is illegal.");
0906: }
0907: DNFieldExtractor subjectaltnames = new DNFieldExtractor(
0908: subjectaltname, DNFieldExtractor.TYPE_SUBJECTALTNAME);
0909: if (subjectaltnames.isIllegal()) {
0910: throw new UserDoesntFullfillEndEntityProfile(
0911: "Subject alt names are illegal.");
0912: }
0913: DNFieldExtractor subjectdirattrs = new DNFieldExtractor(
0914: subjectdirattr, DNFieldExtractor.TYPE_SUBJECTDIRATTR);
0915: if (subjectdirattrs.isIllegal()) {
0916: throw new UserDoesntFullfillEndEntityProfile(
0917: "Subject directory attributes are illegal.");
0918: }
0919:
0920: // Check that no other than supported dn fields exists in the subject dn.
0921: if (subjectdnfields.existsOther())
0922: throw new UserDoesntFullfillEndEntityProfile(
0923: "Unsupported Subject DN Field found in:" + dn);
0924:
0925: if (subjectaltnames.existsOther())
0926: throw new UserDoesntFullfillEndEntityProfile(
0927: "Unsupported Subject Alternate Name Field found in:"
0928: + subjectaltname);
0929:
0930: if (subjectdirattrs.existsOther())
0931: throw new UserDoesntFullfillEndEntityProfile(
0932: "Unsupported Subject Directory Attribute Field found in:"
0933: + subjectdirattr);
0934:
0935: checkIfAllRequiredFieldsExists(subjectdnfields,
0936: subjectaltnames, subjectdirattrs, username, email);
0937:
0938: // Make sure that there are enough fields to cover all required in profile
0939: checkIfForIllegalNumberOfFields(subjectdnfields,
0940: subjectaltnames, subjectdirattrs);
0941:
0942: // Check contents of username.
0943: checkIfDataFullfillProfile(USERNAME, 0, username, "Username",
0944: null);
0945:
0946: // Check Email address.
0947: if (email == null)
0948: email = "";
0949: checkIfDomainFullfillProfile(EMAIL, 0, email, "Email");
0950:
0951: // Make sure that every value has a corresponding field in the entity profile
0952: checkIfFieldsMatch(subjectdnfields,
0953: DNFieldExtractor.TYPE_SUBJECTDN, email);
0954: checkIfFieldsMatch(subjectaltnames,
0955: DNFieldExtractor.TYPE_SUBJECTALTNAME, email);
0956:
0957: // Check contents of Subject Directory Attributes fields.
0958: HashMap subjectdirattrnumbers = subjectdirattrs
0959: .getNumberOfFields();
0960: Integer[] dirattrids = DNFieldExtractor
0961: .getUseFields(DNFieldExtractor.TYPE_SUBJECTDIRATTR);
0962: for (int i = 0; i < dirattrids.length; i++) {
0963: Integer dirattrid = dirattrids[i];
0964: int nof = ((Integer) subjectdirattrnumbers.get(dirattrid))
0965: .intValue();
0966: for (int j = 0; j < nof; j++) {
0967: checkForIllegalChars(subjectdirattrs.getField(dirattrid
0968: .intValue(), j));
0969: if (dirattrid.intValue() == DNFieldExtractor.COUNTRYOFCITIZENSHIP) {
0970: checkIfISO3166FullfillProfile(
0971: DnComponents.COUNTRYOFCITIZENSHIP, j,
0972: subjectdirattrs.getField(dirattrid
0973: .intValue(), j),
0974: "COUNTRYOFCITIZENSHIP");
0975: } else if (dirattrid.intValue() == DNFieldExtractor.COUNTRYOFRESIDENCE) {
0976: checkIfISO3166FullfillProfile(
0977: DnComponents.COUNTRYOFRESIDENCE, j,
0978: subjectdirattrs.getField(dirattrid
0979: .intValue(), j),
0980: "COUNTRYOFRESIDENCE");
0981: } else if (dirattrid.intValue() == DNFieldExtractor.DATEOFBIRTH) {
0982: checkIfDateFullfillProfile(
0983: DnComponents.DATEOFBIRTH, j,
0984: subjectdirattrs.getField(dirattrid
0985: .intValue(), j), "DATEOFBIRTH");
0986: } else if (dirattrid.intValue() == DNFieldExtractor.GENDER) {
0987: checkIfGenderFullfillProfile(DnComponents.GENDER,
0988: j, subjectdirattrs.getField(dirattrid
0989: .intValue(), j), "GENDER");
0990: } else {
0991: checkIfDataFullfillProfile(DnComponents
0992: .dnIdToProfileName(dirattrid.intValue()),
0993: j, subjectdirattrs.getField(dirattrid
0994: .intValue(), j), DnComponents
0995: .getErrTextFromDnId(dirattrid
0996: .intValue()), email);
0997: }
0998: }
0999: }
1000:
1001: // Check for administrator flag.
1002: if (!getUse(ADMINISTRATOR, 0) && administrator)
1003: throw new UserDoesntFullfillEndEntityProfile(
1004: "Administrator cannot be set.");
1005:
1006: if (isRequired(ADMINISTRATOR, 0)) {
1007: if (getValue(ADMINISTRATOR, 0).equals(TRUE)
1008: && !administrator)
1009: throw new UserDoesntFullfillEndEntityProfile(
1010: "Administrator flag is required.");
1011: if (getValue(ADMINISTRATOR, 0).equals(FALSE)
1012: && administrator)
1013: throw new UserDoesntFullfillEndEntityProfile(
1014: "Administrator flag cannot be set in current end entity profile.");
1015: }
1016: // Check for keyrecoverable flag.
1017: if (!getUse(KEYRECOVERABLE, 0) && keyrecoverable)
1018: throw new UserDoesntFullfillEndEntityProfile(
1019: "Key Recoverable cannot be used.");
1020:
1021: if (isRequired(KEYRECOVERABLE, 0)) {
1022: if (getValue(KEYRECOVERABLE, 0).equals(TRUE)
1023: && !keyrecoverable)
1024: throw new UserDoesntFullfillEndEntityProfile(
1025: "Key Recoverable is required.");
1026: if (getValue(KEYRECOVERABLE, 0).equals(FALSE)
1027: && keyrecoverable)
1028: throw new UserDoesntFullfillEndEntityProfile(
1029: "Key Recoverable cannot be set in current end entity profile.");
1030: }
1031:
1032: // Check for send notification flag.
1033: if (!getUse(SENDNOTIFICATION, 0) && sendnotification)
1034: throw new UserDoesntFullfillEndEntityProfile(
1035: "Email notification cannot be used.");
1036:
1037: if (isRequired(SENDNOTIFICATION, 0)) {
1038: if (getValue(SENDNOTIFICATION, 0).equals(TRUE)
1039: && !sendnotification)
1040: throw new UserDoesntFullfillEndEntityProfile(
1041: "Email notification is required.");
1042: if (getValue(SENDNOTIFICATION, 0).equals(FALSE)
1043: && sendnotification)
1044: throw new UserDoesntFullfillEndEntityProfile(
1045: "Email notification cannot be set in current end entity profile.");
1046: }
1047:
1048: // Check if certificate profile is among available certificate profiles.
1049: String[] availablecertprofiles;
1050: try {
1051: availablecertprofiles = getValue(AVAILCERTPROFILES, 0)
1052: .split(SPLITCHAR);
1053: } catch (Exception e) {
1054: throw new UserDoesntFullfillEndEntityProfile(
1055: "Error parsing end entity profile.");
1056: }
1057: if (availablecertprofiles == null)
1058: throw new UserDoesntFullfillEndEntityProfile(
1059: "Error Available certificate profiles is null.");
1060: boolean found = false;
1061: for (int i = 0; i < availablecertprofiles.length; i++) {
1062: if (Integer.parseInt(availablecertprofiles[i]) == certificateprofileid)
1063: found = true;
1064: }
1065:
1066: if (!found)
1067: throw new UserDoesntFullfillEndEntityProfile(
1068: "Couldn't find certificate profile ("
1069: + certificateprofileid
1070: + ") among available certificate profiles.");
1071:
1072: // Check if tokentype is among available token types.
1073: String[] availablesofttokentypes;
1074: try {
1075: availablesofttokentypes = getValue(AVAILKEYSTORE, 0).split(
1076: SPLITCHAR);
1077: } catch (Exception e) {
1078: throw new UserDoesntFullfillEndEntityProfile(
1079: "Error parsing end entity profile.");
1080: }
1081: if (availablesofttokentypes == null)
1082: throw new UserDoesntFullfillEndEntityProfile(
1083: "Error available token types is null.");
1084: found = false;
1085: for (int i = 0; i < availablesofttokentypes.length; i++) {
1086: if (Integer.parseInt(availablesofttokentypes[i]) == tokentype)
1087: found = true;
1088: }
1089:
1090: // If soft token check for hardwaretoken issuer id = 0.
1091: if (tokentype <= SecConst.TOKEN_SOFT) {
1092: if (hardwaretokenissuerid != 0)
1093: throw new UserDoesntFullfillEndEntityProfile(
1094: "Soft tokens cannot have a hardware token issuer.");
1095: }
1096: // If Hard token type check if hardware token issuer is among available hardware token issuers.
1097: if (tokentype > SecConst.TOKEN_SOFT
1098: && getUse(AVAILTOKENISSUER, 0)) { // Hardware token.
1099: String[] availablehardtokenissuers;
1100: try {
1101: availablehardtokenissuers = getValue(AVAILTOKENISSUER,
1102: 0).split(SPLITCHAR);
1103: } catch (Exception e) {
1104: throw new UserDoesntFullfillEndEntityProfile(
1105: "Error parsing end entity profile.");
1106: }
1107: if (availablehardtokenissuers == null)
1108: throw new UserDoesntFullfillEndEntityProfile(
1109: "Error available hard token issuers is null.");
1110: found = false;
1111: for (int i = 0; i < availablehardtokenissuers.length; i++) {
1112: if (Integer.parseInt(availablehardtokenissuers[i]) == hardwaretokenissuerid)
1113: found = true;
1114: }
1115:
1116: if (!found)
1117: throw new UserDoesntFullfillEndEntityProfile(
1118: "Couldn't find hard token issuers among available hard token issuers.");
1119: }
1120:
1121: // Check if ca id is among available ca ids.
1122: String[] availablecaids;
1123: try {
1124: availablecaids = getValue(AVAILCAS, 0).split(SPLITCHAR);
1125: } catch (Exception e) {
1126: throw new UserDoesntFullfillEndEntityProfile(
1127: "Error parsing end entity profile.");
1128: }
1129: if (availablecaids == null)
1130: throw new UserDoesntFullfillEndEntityProfile(
1131: "Error End Entity Profiles Available CAs is null.");
1132: found = false;
1133: for (int i = 0; i < availablecaids.length; i++) {
1134: int tmp = Integer.parseInt(availablecaids[i]);
1135: if (tmp == caid || tmp == SecConst.ALLCAS)
1136: found = true;
1137: }
1138:
1139: if (!found)
1140: throw new UserDoesntFullfillEndEntityProfile(
1141: "Couldn't find CA ("
1142: + caid
1143: + ") among End Entity Profiles Available CAs.");
1144:
1145: // Check if time constraints are valid
1146: String startTime = null;
1147: String endTime = null;
1148: if (ei != null) {
1149: startTime = ei.getCustomData(EndEntityProfile.STARTTIME);
1150: endTime = ei.getCustomData(EndEntityProfile.ENDTIME);
1151: }
1152: Date now = new Date();
1153: Date startTimeDate = null;
1154: if (getUse(STARTTIME, 0) && startTime != null
1155: && !startTime.equals("")) {
1156: if (startTime.matches("^\\d+:\\d?\\d:\\d?\\d$")) {
1157: String[] startTimeArray = startTime.split(":");
1158: if (Long.parseLong(startTimeArray[0]) < 0
1159: || Long.parseLong(startTimeArray[1]) < 0
1160: || Long.parseLong(startTimeArray[2]) < 0) {
1161: throw new UserDoesntFullfillEndEntityProfile(
1162: "Cannot use negtive relative time.");
1163: }
1164:
1165: long relative = (Long.parseLong(startTimeArray[0]) * 24
1166: * 60 + Long.parseLong(startTimeArray[1]) * 60 + Long
1167: .parseLong(startTimeArray[2])) * 60 * 1000;
1168: startTimeDate = new Date(now.getTime() + relative);
1169: } else {
1170: try {
1171: startTimeDate = DateFormat.getDateTimeInstance(
1172: DateFormat.MEDIUM, DateFormat.SHORT,
1173: Locale.US).parse(startTime);
1174: } catch (ParseException e) {
1175: }
1176: }
1177: }
1178: if (getUse(STARTTIME, 0) && startTimeDate == null) {
1179: throw new UserDoesntFullfillEndEntityProfile(
1180: "Invalid start time format.");
1181: }
1182: Date endTimeDate = null;
1183: if (getUse(ENDTIME, 0) && endTime != null
1184: && !endTime.equals("")) {
1185: if (endTime.matches("^\\d+:\\d?\\d:\\d?\\d$")) {
1186: String[] endTimeArray = endTime.split(":");
1187: if (Long.parseLong(endTimeArray[0]) < 0
1188: || Long.parseLong(endTimeArray[1]) < 0
1189: || Long.parseLong(endTimeArray[2]) < 0) {
1190: throw new UserDoesntFullfillEndEntityProfile(
1191: "Cannot use negtive relative time.");
1192: }
1193: long relative = (Long.parseLong(endTimeArray[0]) * 24
1194: * 60 + Long.parseLong(endTimeArray[1]) * 60 + Long
1195: .parseLong(endTimeArray[2])) * 60 * 1000;
1196: endTimeDate = new Date(startTimeDate.getTime()
1197: + relative);
1198: } else {
1199: try {
1200: endTimeDate = DateFormat.getDateTimeInstance(
1201: DateFormat.MEDIUM, DateFormat.SHORT,
1202: Locale.US).parse(endTime);
1203: } catch (ParseException e) {
1204: }
1205: }
1206: }
1207: if (getUse(ENDTIME, 0) && endTimeDate == null) {
1208: throw new UserDoesntFullfillEndEntityProfile(
1209: "Invalid end time format.");
1210: }
1211: if (getUse(STARTTIME, 0) && getUse(ENDTIME, 0)
1212: && !startTimeDate.before(endTimeDate)) {
1213: throw new UserDoesntFullfillEndEntityProfile(
1214: "Dates must be in right order. "
1215: + startTime
1216: + " "
1217: + endTime
1218: + " "
1219: + DateFormat.getDateTimeInstance(
1220: DateFormat.MEDIUM,
1221: DateFormat.SHORT, Locale.US)
1222: .format(startTimeDate)
1223: + " "
1224: + DateFormat.getDateTimeInstance(
1225: DateFormat.MEDIUM,
1226: DateFormat.SHORT, Locale.US)
1227: .format(endTimeDate));
1228: }
1229:
1230: String allowedRequests = null;
1231: if (ei != null) {
1232: allowedRequests = ei
1233: .getCustomData(EndEntityProfile.ALLOWEDREQUESTS);
1234: }
1235: if ((allowedRequests != null) && !getUse(ALLOWEDREQUESTS, 0)) {
1236: throw new UserDoesntFullfillEndEntityProfile(
1237: "Allowed requests used, but not permitted by profile.");
1238: }
1239:
1240: } // doesUserFullfillEndEntityProfile
1241:
1242: /**
1243: * This function tries to match each field in the profile to a corresponding field in the DN/AN/AD-fields.
1244: * Can not be used for DNFieldExtractor.TYPE_SUBJECTDIRATTR yet.
1245: *
1246: * @param fields
1247: * @param type One of DNFieldExtractor.TYPE_SUBJECTDN, DNFieldExtractor.TYPE_SUBJECTALTNAME
1248: * @param email The end entity's email address
1249: * @throws UserDoesntFullfillEndEntityProfile
1250: */
1251: private void checkIfFieldsMatch(DNFieldExtractor fields, int type,
1252: String email) throws UserDoesntFullfillEndEntityProfile {
1253: final int REQUIRED_FIELD = 2;
1254: final int NONMODIFYABLE_FIELD = 1;
1255: final int MATCHED_FIELD = -1;
1256: Integer[] dnids = DNFieldExtractor.getUseFields(type);
1257: // For each type of field
1258: for (int i = 0; i < dnids.length; i++) {
1259: int dnid = dnids[i].intValue();
1260: int profileID = DnComponents.dnIdToProfileId(dnid);
1261: int dnFieldExtractorID = DnComponents
1262: .profileIdToDnId(profileID);
1263: int nof = fields.getNumberOfFields(dnFieldExtractorID);
1264: int numberOfProfileFields = getNumberOfField(profileID);
1265: if (nof == 0 && numberOfProfileFields == 0) {
1266: continue; // Nothing to see here..
1267: }
1268: // Create array with all entries of that type
1269: String[] subjectsToProcess = new String[nof];
1270: for (int j = 0; j < nof; j++) {
1271: String fieldValue = fields.getField(dnFieldExtractorID,
1272: j);
1273: // Only keep domain for comparison of RFC822NAME, DNEMAIL and UPN fields
1274: if (DnComponents.RFC822NAME.equals(DnComponents
1275: .dnIdToProfileName(dnid))
1276: || DnComponents.DNEMAIL.equals(DnComponents
1277: .dnIdToProfileName(dnid))
1278: || DnComponents.UPN.equals(DnComponents
1279: .dnIdToProfileName(dnid))) {
1280: if (fieldValue.indexOf('@') == -1) {
1281: throw new UserDoesntFullfillEndEntityProfile(
1282: DnComponents.dnIdToProfileName(dnid)
1283: + " does not seem to be in something@somthingelse format.");
1284: }
1285: fieldValue = fieldValue.split("@")[1];
1286: }
1287: subjectsToProcess[j] = fieldValue;
1288: }
1289: // Create array with profile values 3 = required and non-mod, 2 = required, 1 = non-modifiable, 0 = neither
1290: int[] profileCrossOffList = new int[numberOfProfileFields];
1291: for (int j = 0; j < getNumberOfField(profileID); j++) {
1292: profileCrossOffList[j] += (isModifyable(profileID, j) ? 0
1293: : NONMODIFYABLE_FIELD)
1294: + (isRequired(profileID, j) ? REQUIRED_FIELD
1295: : 0);
1296: }
1297: // Start by matching email strings
1298: if (DnComponents.RFC822NAME.equals(DnComponents
1299: .dnIdToProfileName(dnid))
1300: || DnComponents.DNEMAIL.equals(DnComponents
1301: .dnIdToProfileName(dnid))) {
1302: for (int k = 3; k >= 0; k--) {
1303: // For every value in profile
1304: for (int l = 0; l < profileCrossOffList.length; l++) {
1305: if (profileCrossOffList[l] == k) {
1306: // Match with every value in field-array
1307: for (int m = 0; m < subjectsToProcess.length; m++) {
1308: if (subjectsToProcess[m] != null
1309: && profileCrossOffList[l] != MATCHED_FIELD) {
1310: if (!(!getUse(profileID, l) && DnComponents.RFC822NAME
1311: .equals(DnComponents
1312: .dnIdToProfileName(dnid)))) {
1313: if (fields.getField(
1314: dnFieldExtractorID, m)
1315: .equals(email)) {
1316: subjectsToProcess[m] = null;
1317: profileCrossOffList[l] = MATCHED_FIELD;
1318: }
1319: }
1320: }
1321: }
1322: }
1323: }
1324: }
1325: }
1326: // For every field of this type in profile (start with required and non-modifiable, 2 + 1)
1327: for (int k = 3; k >= 0; k--) {
1328: // For every value in profile
1329: for (int l = 0; l < profileCrossOffList.length; l++) {
1330: if (profileCrossOffList[l] == k) {
1331: // Match with every value in field-array
1332: for (int m = 0; m < subjectsToProcess.length; m++) {
1333: if (subjectsToProcess[m] != null
1334: && profileCrossOffList[l] != MATCHED_FIELD) {
1335: // Match actual value if required + non-modifiable or non-modifiable
1336: if ((k == (REQUIRED_FIELD + NONMODIFYABLE_FIELD) || k == (NONMODIFYABLE_FIELD))) {
1337: // Try to match with all possible values
1338: String[] fixedValues = getValue(
1339: profileID, l).split(
1340: SPLITCHAR);
1341: for (int n = 0; n < fixedValues.length; n++) {
1342: if (subjectsToProcess[m] != null
1343: && subjectsToProcess[m]
1344: .equals(fixedValues[n])) {
1345: // Remove matched pair
1346: subjectsToProcess[m] = null;
1347: profileCrossOffList[l] = MATCHED_FIELD;
1348: }
1349: }
1350: // Otherwise just match present fields
1351: } else {
1352: // Remove matched pair
1353: subjectsToProcess[m] = null;
1354: profileCrossOffList[l] = MATCHED_FIELD;
1355: }
1356: }
1357: }
1358: }
1359: }
1360: }
1361: // If not all fields in profile were found
1362: for (int j = 0; j < nof; j++) {
1363: if (subjectsToProcess[j] != null) {
1364: throw new UserDoesntFullfillEndEntityProfile(
1365: "End entity profile does not contain matching field for "
1366: + DnComponents
1367: .dnIdToProfileName(dnid)
1368: + " with value \""
1369: + subjectsToProcess[j] + "\".");
1370: }
1371: }
1372: // If not all required fields in profile were found in subject
1373: for (int j = 0; j < getNumberOfField(profileID); j++) {
1374: if (profileCrossOffList[j] >= REQUIRED_FIELD) {
1375: throw new UserDoesntFullfillEndEntityProfile(
1376: "Data does not contain required "
1377: + DnComponents
1378: .dnIdToProfileName(dnid)
1379: + " field.");
1380: }
1381: }
1382: }
1383: } // checkIfFieldsMatch
1384:
1385: public void doesPasswordFulfillEndEntityProfile(String password,
1386: boolean clearpwd) throws UserDoesntFullfillEndEntityProfile {
1387:
1388: boolean fullfillsprofile = true;
1389: if (useAutoGeneratedPasswd()) {
1390: if (password != null)
1391: throw new UserDoesntFullfillEndEntityProfile(
1392: "Autogenerated password must have password==null");
1393: } else {
1394: if (!isModifyable(EndEntityProfile.PASSWORD, 0)) {
1395: if (!password.equals(getValue(
1396: EndEntityProfile.PASSWORD, 0)))
1397: fullfillsprofile = false;
1398: } else if (isRequired(EndEntityProfile.PASSWORD, 0)) {
1399: if ((!clearpwd && password == null)
1400: || (password != null && password.trim().equals(
1401: "")))
1402: fullfillsprofile = false;
1403: }
1404: }
1405:
1406: if (clearpwd
1407: && isRequired(EndEntityProfile.CLEARTEXTPASSWORD, 0)
1408: && getValue(EndEntityProfile.CLEARTEXTPASSWORD, 0)
1409: .equals(EndEntityProfile.FALSE)) {
1410: fullfillsprofile = false;
1411: }
1412:
1413: if (!fullfillsprofile)
1414: throw new UserDoesntFullfillEndEntityProfile(
1415: "Password doesn't fullfill profile.");
1416: }
1417:
1418: public Object clone() throws CloneNotSupportedException {
1419: EndEntityProfile clone = new EndEntityProfile();
1420: HashMap clonedata = (HashMap) clone.saveData();
1421:
1422: Iterator i = (data.keySet()).iterator();
1423: while (i.hasNext()) {
1424: Object key = i.next();
1425: clonedata.put(key, data.get(key));
1426: }
1427:
1428: clone.loadData(clonedata);
1429: return clone;
1430: }
1431:
1432: /** Implemtation of UpgradableDataHashMap function getLatestVersion */
1433: public float getLatestVersion() {
1434: return LATEST_VERSION;
1435: }
1436:
1437: /** Implemtation of UpgradableDataHashMap function upgrade. */
1438: public void upgrade() {
1439: log.debug(">upgrade");
1440: if (Float.compare(LATEST_VERSION, getVersion()) != 0) {
1441: String msg = intres.getLocalizedMessage(
1442: "ra.eeprofileupgrade", new Float(getVersion()));
1443: log.info(msg);
1444: // New version of the class, upgrade
1445: if (getVersion() < 1) {
1446: ArrayList numberarray = (ArrayList) data
1447: .get(NUMBERARRAY);
1448: while (numberarray.size() < 37) {
1449: numberarray.add(new Integer(0));
1450: }
1451: data.put(NUMBERARRAY, numberarray);
1452: }
1453: if (getVersion() < 2) {
1454: ArrayList numberarray = (ArrayList) data
1455: .get(NUMBERARRAY);
1456: while (numberarray.size() < 39) {
1457: numberarray.add(new Integer(0));
1458: }
1459: data.put(NUMBERARRAY, numberarray);
1460:
1461: addField(AVAILCAS);
1462: addField(DEFAULTCA);
1463: setRequired(AVAILCAS, 0, true);
1464: setRequired(DEFAULTCA, 0, true);
1465: }
1466: if (getVersion() < 3) {
1467: // These fields have been removed in version 8, no need for this upgrade
1468: //setNotificationSubject("");
1469: //setNotificationSender("");
1470: //setNotificationMessage("");
1471: }
1472:
1473: if (getVersion() < 4) {
1474: ArrayList numberoffields = (ArrayList) data
1475: .get(NUMBERARRAY);
1476: for (int i = numberoffields.size(); i < dataConstants
1477: .size(); i++) {
1478: numberoffields.add(new Integer(0));
1479: }
1480: data.put(NUMBERARRAY, numberoffields);
1481: }
1482: // Support for DirectoryName altname field in profile version 5
1483: if (getVersion() < 5) {
1484: addField(DnComponents.DIRECTORYNAME);
1485: setValue(DnComponents.DIRECTORYNAME, 0, "");
1486: setRequired(DnComponents.DIRECTORYNAME, 0, false);
1487: setUse(DnComponents.DIRECTORYNAME, 0, true);
1488: setModifyable(DnComponents.DIRECTORYNAME, 0, true);
1489: }
1490: // Support for Subject Directory Attributes field in profile version 6
1491: if (getVersion() < 6) {
1492: ArrayList numberoffields = (ArrayList) data
1493: .get(NUMBERARRAY);
1494: for (int i = numberoffields.size(); i < dataConstants
1495: .size(); i++) {
1496: numberoffields.add(new Integer(0));
1497: }
1498: data.put(NUMBERARRAY, numberoffields);
1499: data.put(SUBJECTDIRATTRFIELDORDER, new ArrayList());
1500:
1501: for (int i = getParameterNumber(DnComponents.DATEOFBIRTH); i <= getParameterNumber(DnComponents.COUNTRYOFRESIDENCE); i++) {
1502: addField(getParameter(i));
1503: setValue(getParameter(i), 0, "");
1504: setRequired(getParameter(i), 0, false);
1505: setUse(getParameter(i), 0, false);
1506: setModifyable(getParameter(i), 0, true);
1507: }
1508: }
1509: // Support for Start Time and End Time field in profile version 7
1510: if (getVersion() < 7) {
1511: ArrayList numberoffields = (ArrayList) data
1512: .get(NUMBERARRAY);
1513: for (int i = numberoffields.size(); i < dataConstants
1514: .size(); i++) {
1515: numberoffields.add(new Integer(0));
1516: }
1517: data.put(NUMBERARRAY, numberoffields);
1518: addField(STARTTIME);
1519: setValue(STARTTIME, 0, "");
1520: setRequired(STARTTIME, 0, false);
1521: setUse(STARTTIME, 0, false);
1522: setModifyable(STARTTIME, 0, true);
1523: addField(ENDTIME);
1524: setValue(ENDTIME, 0, "");
1525: setRequired(ENDTIME, 0, false);
1526: setUse(ENDTIME, 0, false);
1527: setModifyable(ENDTIME, 0, true);
1528: }
1529: // Notifications is now a more general mechanism in version 8
1530: if (getVersion() < 8) {
1531: log.debug("Upgrading User Notifications");
1532: if (data.get(UserNotification.NOTIFICATIONSENDER) != null) {
1533: UserNotification not = new UserNotification();
1534: not.setNotificationSender((String) data
1535: .get(UserNotification.NOTIFICATIONSENDER));
1536: if (data.get(UserNotification.NOTIFICATIONSUBJECT) != null) {
1537: not
1538: .setNotificationSubject((String) data
1539: .get(UserNotification.NOTIFICATIONSUBJECT));
1540: }
1541: if (data.get(UserNotification.NOTIFICATIONMESSAGE) != null) {
1542: not
1543: .setNotificationMessage((String) data
1544: .get(UserNotification.NOTIFICATIONMESSAGE));
1545: }
1546: // Add the statuschanges we used to send notifications about
1547: String events = UserNotification.EVENTS_EDITUSER;
1548: not.setNotificationEvents(events);
1549: // The old recipients where always the user
1550: not
1551: .setNotificationRecipient(UserNotification.RCPT_USER);
1552:
1553: addUserNotification(not);
1554: }
1555: }
1556: // Support for allowed requests in profile version 9
1557: if (getVersion() < 9) {
1558: ArrayList numberoffields = (ArrayList) data
1559: .get(NUMBERARRAY);
1560: for (int i = numberoffields.size(); i < dataConstants
1561: .size(); i++) {
1562: numberoffields.add(new Integer(0));
1563: }
1564: data.put(NUMBERARRAY, numberoffields);
1565: addField(ALLOWEDREQUESTS);
1566: setValue(ALLOWEDREQUESTS, 0, "");
1567: setRequired(ALLOWEDREQUESTS, 0, false);
1568: setUse(ALLOWEDREQUESTS, 0, false);
1569: setModifyable(ALLOWEDREQUESTS, 0, true);
1570: }
1571:
1572: data.put(VERSION, new Float(LATEST_VERSION));
1573: }
1574: log.debug("<upgrade");
1575: }
1576:
1577: public static boolean isFieldImplemented(int field) {
1578: String f = getParameter(field);
1579: if (f == null) {
1580: log
1581: .info("isFieldImplemented got call for non-implemented field: "
1582: + field);
1583: return false;
1584: }
1585: return isFieldImplemented(f);
1586: }
1587:
1588: public static boolean isFieldImplemented(String field) {
1589: boolean ret = true;
1590: if (field.equals(DnComponents.OTHERNAME)
1591: || field.equals(DnComponents.X400ADDRESS)
1592: || field.equals(DnComponents.EDIPARTNAME)
1593: || field.equals(DnComponents.REGISTEREDID)) {
1594: log
1595: .info("isFieldImplemented got call for non-implemented field: "
1596: + field);
1597: ret = false;
1598: }
1599: return ret;
1600: }
1601:
1602: public static boolean isFieldOfType(int fieldNumber,
1603: String fieldString) {
1604: boolean ret = false;
1605: int number = getParameterNumber(fieldString);
1606: if (fieldNumber == number) {
1607: ret = true;
1608: }
1609: return ret;
1610: }
1611:
1612: //
1613: // Private Methods
1614: //
1615:
1616: /**
1617: * Verify that the field contains an address and that data of non-modifyable domain-fields is available in profile
1618: * Used for email, upn and rfc822 fields
1619: *
1620: */
1621: private void checkIfDomainFullfillProfile(String field, int number,
1622: String nameAndDomain, String text)
1623: throws UserDoesntFullfillEndEntityProfile {
1624:
1625: if (!nameAndDomain.trim().equals("")
1626: && nameAndDomain.indexOf('@') == -1)
1627: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1628: + text + "(" + nameAndDomain
1629: + "). There must be a '@' character in the field.");
1630:
1631: String domain = nameAndDomain.substring(nameAndDomain
1632: .indexOf('@') + 1);
1633:
1634: // All fields except RFC822NAME has to be empty if not used flag is set.
1635: if (!DnComponents.RFC822NAME.equals(field)
1636: && !getUse(field, number)
1637: && !nameAndDomain.trim().equals("")) {
1638: throw new UserDoesntFullfillEndEntityProfile(text
1639: + " cannot be used in end entity profile.");
1640: }
1641:
1642: if (!isModifyable(field, number) && !nameAndDomain.equals("")) {
1643: String[] values;
1644: try {
1645: values = getValue(field, number).split(SPLITCHAR);
1646: } catch (Exception e) {
1647: throw new UserDoesntFullfillEndEntityProfile(
1648: "Error parsing end entity profile.");
1649: }
1650: boolean exists = false;
1651: for (int i = 0; i < values.length; i++) {
1652: if (domain.equals(values[i].trim()))
1653: exists = true;
1654: }
1655: if (!exists)
1656: throw new UserDoesntFullfillEndEntityProfile(
1657: "Field "
1658: + text
1659: + " data didn't match requirement of end entity profile.");
1660: }
1661: }
1662:
1663: private void checkForIllegalChars(String str)
1664: throws UserDoesntFullfillEndEntityProfile {
1665: if (StringTools.hasSqlStripChars(str)) {
1666: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1667: + str + ". Contains illegal characters.");
1668: }
1669: }
1670:
1671: /**
1672: * Used for iso 3166 country codes
1673: *
1674: */
1675: private void checkIfISO3166FullfillProfile(String field,
1676: int number, String country, String text)
1677: throws UserDoesntFullfillEndEntityProfile {
1678:
1679: if (!country.trim().equals("") && country.trim().length() != 2)
1680: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1681: + text + ". Must be of length two.");
1682:
1683: if (!getUse(field, number) && !country.trim().equals(""))
1684: throw new UserDoesntFullfillEndEntityProfile(text
1685: + " cannot be used in end entity profile.");
1686:
1687: if (!isModifyable(field, number) && !country.trim().equals("")) {
1688: String[] values;
1689: try {
1690: values = getValue(field, number).split(SPLITCHAR);
1691: } catch (Exception e) {
1692: throw new UserDoesntFullfillEndEntityProfile(
1693: "Error parsing end entity profile.");
1694: }
1695: boolean exists = false;
1696: for (int i = 0; i < values.length; i++) {
1697: if (country.equals(values[i].trim()))
1698: exists = true;
1699: }
1700: if (!exists)
1701: throw new UserDoesntFullfillEndEntityProfile(
1702: "Field "
1703: + text
1704: + " data didn't match requirement of end entity profile.");
1705: }
1706: }
1707:
1708: /**
1709: * Used to check if it is an M or an F
1710: *
1711: */
1712: private void checkIfGenderFullfillProfile(String field, int number,
1713: String gender, String text)
1714: throws UserDoesntFullfillEndEntityProfile {
1715:
1716: if (!gender.trim().equals("")
1717: && !(gender.equalsIgnoreCase("m") || gender
1718: .equalsIgnoreCase("f")))
1719: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1720: + text + ". Must be M or F.");
1721:
1722: if (!getUse(field, number) && !gender.trim().equals(""))
1723: throw new UserDoesntFullfillEndEntityProfile(text
1724: + " cannot be used in end entity profile.");
1725:
1726: if (!isModifyable(field, number) && !gender.trim().equals("")) {
1727: String[] values;
1728: try {
1729: values = getValue(field, number).split(SPLITCHAR);
1730: } catch (Exception e) {
1731: throw new UserDoesntFullfillEndEntityProfile(
1732: "Error parsing end entity profile.");
1733: }
1734: boolean exists = false;
1735: for (int i = 0; i < values.length; i++) {
1736: if (gender.equals(values[i].trim()))
1737: exists = true;
1738: }
1739: if (!exists)
1740: throw new UserDoesntFullfillEndEntityProfile(
1741: "Field "
1742: + text
1743: + " data didn't match requirement of end entity profile.");
1744: }
1745: }
1746:
1747: /**
1748: * Used for date strings, should be YYYYMMDD
1749: *
1750: */
1751: private void checkIfDateFullfillProfile(String field, int number,
1752: String date, String text)
1753: throws UserDoesntFullfillEndEntityProfile {
1754:
1755: if (!date.trim().equals("") && date.trim().length() != 8)
1756: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1757: + text + ". Must be of length eight.");
1758: if (!date.trim().equals("")
1759: && !StringUtils.isNumeric(date.trim()))
1760: throw new UserDoesntFullfillEndEntityProfile("Invalid "
1761: + text + ". Must be only numbers.");
1762:
1763: if (!getUse(field, number) && !date.trim().equals(""))
1764: throw new UserDoesntFullfillEndEntityProfile(text
1765: + " cannot be used in end entity profile.");
1766:
1767: if (!isModifyable(field, number) && !date.trim().equals("")) {
1768: String[] values;
1769: try {
1770: values = getValue(field, number).split(SPLITCHAR);
1771: } catch (Exception e) {
1772: throw new UserDoesntFullfillEndEntityProfile(
1773: "Error parsing end entity profile.");
1774: }
1775: boolean exists = false;
1776: for (int i = 0; i < values.length; i++) {
1777: if (date.equals(values[i].trim()))
1778: exists = true;
1779: }
1780: if (!exists)
1781: throw new UserDoesntFullfillEndEntityProfile(
1782: "Field "
1783: + text
1784: + " data didn't match requirement of end entity profile.");
1785: }
1786: }
1787:
1788: /**
1789: * Verifies that non-modifyable data is available in profile.
1790: * @throws UserDoesntFullfillEndEntityProfile
1791: */
1792: private void checkIfDataFullfillProfile(String field, int number,
1793: String data, String text, String email)
1794: throws UserDoesntFullfillEndEntityProfile {
1795:
1796: if (data == null && !field.equals(EMAIL))
1797: throw new UserDoesntFullfillEndEntityProfile("Field "
1798: + text + " cannot be null.");
1799:
1800: if (data != null)
1801: if (!getUse(field, number) && !data.trim().equals(""))
1802: throw new UserDoesntFullfillEndEntityProfile(text
1803: + " cannot be used in end entity profile.");
1804:
1805: if (field.equals(DnComponents.DNEMAIL)) {
1806: if (isRequired(field, number)) {
1807: if (!data.trim().equals(email.trim()))
1808: throw new UserDoesntFullfillEndEntityProfile(
1809: "Field " + text
1810: + " data didn't match Email field.");
1811: }
1812: } else if (field.equals(DnComponents.RFC822NAME)
1813: && isRequired(field, number) && getUse(field, number)) {
1814: if (!data.trim().equals(email.trim())) {
1815: throw new UserDoesntFullfillEndEntityProfile("Field "
1816: + text + " data didn't match Email field.");
1817: }
1818: } else {
1819: if (!isModifyable(field, number)) {
1820: String[] values;
1821: try {
1822: values = getValue(field, number).split(SPLITCHAR);
1823: } catch (Exception e) {
1824: throw new UserDoesntFullfillEndEntityProfile(
1825: "Error parsing end entity profile.");
1826: }
1827: boolean exists = false;
1828: for (int i = 0; i < values.length; i++) {
1829: if (data.equals(values[i].trim()))
1830: exists = true;
1831: }
1832: if (!exists)
1833: throw new UserDoesntFullfillEndEntityProfile(
1834: "Field "
1835: + text
1836: + " data didn't match requirement of end entity profile.");
1837: }
1838: }
1839: }
1840:
1841: private void checkIfAllRequiredFieldsExists(
1842: DNFieldExtractor subjectdnfields,
1843: DNFieldExtractor subjectaltnames,
1844: DNFieldExtractor subjectdirattrs, String username,
1845: String email) throws UserDoesntFullfillEndEntityProfile {
1846: int size;
1847:
1848: // Check if Username exists.
1849: if (isRequired(USERNAME, 0)) {
1850: if (username == null || username.trim().equals(""))
1851: throw new UserDoesntFullfillEndEntityProfile(
1852: "Username cannot be empty or null.");
1853: }
1854:
1855: // Check if required Email fields exists.
1856: if (isRequired(EMAIL, 0)) {
1857: if (email == null || email.trim().equals(""))
1858: throw new UserDoesntFullfillEndEntityProfile(
1859: "Email address cannot be empty or null.");
1860: }
1861:
1862: // Check if all required subjectdn fields exists.
1863: String[] dnfields = getSubjectDNProfileFields();
1864: Integer[] dnFieldExtractorIds = (Integer[]) DnComponents
1865: .getDnDnIds().toArray(new Integer[0]);
1866: for (int i = 0; i < dnfields.length; i++) {
1867: if (getReverseFieldChecks()) {
1868: int nof = subjectdnfields
1869: .getNumberOfFields(dnFieldExtractorIds[i]
1870: .intValue());
1871: int numRequiredFields = getNumberOfRequiredFields(dnfields[i]);
1872: if (nof < numRequiredFields) {
1873: throw new UserDoesntFullfillEndEntityProfile(
1874: "Subject DN field '" + dnfields[i]
1875: + "' must exist.");
1876: }
1877: } else {
1878: size = getNumberOfField(dnfields[i]);
1879: for (int j = 0; j < size; j++) {
1880: if (isRequired(dnfields[i], j))
1881: if (subjectdnfields.getField(
1882: dnFieldExtractorIds[i].intValue(), j)
1883: .trim().equals(""))
1884: throw new UserDoesntFullfillEndEntityProfile(
1885: "Subject DN field '" + dnfields[i]
1886: + "' must exist.");
1887: }
1888: }
1889: }
1890:
1891: // Check if all required subject alternate name fields exists.
1892: String[] altnamefields = getSubjectAltnameProfileFields();
1893: Integer[] altNameFieldExtractorIds = (Integer[]) DnComponents
1894: .getAltNameDnIds().toArray(new Integer[0]);
1895: for (int i = 0; i < altnamefields.length; i++) {
1896: if (getReverseFieldChecks()) {
1897: int nof = subjectaltnames
1898: .getNumberOfFields(altNameFieldExtractorIds[i]
1899: .intValue());
1900: int numRequiredFields = getNumberOfRequiredFields(altnamefields[i]);
1901: if (nof < numRequiredFields) {
1902: throw new UserDoesntFullfillEndEntityProfile(
1903: "Subject Alternative Name field '"
1904: + altnamefields[i]
1905: + "' must exist.");
1906: }
1907: } else {
1908: // Only verify fields that are actually used
1909: // size = getNumberOfField(altnamefields[i]);
1910: size = subjectaltnames
1911: .getNumberOfFields(altNameFieldExtractorIds[i]
1912: .intValue());
1913: for (int j = 0; j < size; j++) {
1914: if (isRequired(altnamefields[i], j))
1915: if (subjectaltnames.getField(
1916: altNameFieldExtractorIds[i].intValue(),
1917: j).trim().equals(""))
1918: throw new UserDoesntFullfillEndEntityProfile(
1919: "Subject Alterntive Name field '"
1920: + altnamefields[i]
1921: + "' must exist.");
1922: }
1923: }
1924: }
1925:
1926: // Check if all required subject directory attribute fields exists.
1927: String[] dirattrfields = getSubjectDirAttrProfileFields();
1928: Integer[] dirAttrFieldExtractorIds = (Integer[]) DnComponents
1929: .getDirAttrDnIds().toArray(new Integer[0]);
1930: for (int i = 0; i < dirattrfields.length; i++) {
1931: size = getNumberOfField(dirattrfields[i]);
1932: for (int j = 0; j < size; j++) {
1933: if (isRequired(dirattrfields[i], j))
1934: if (subjectdirattrs.getField(
1935: dirAttrFieldExtractorIds[i].intValue(), j)
1936: .trim().equals(""))
1937: throw new UserDoesntFullfillEndEntityProfile(
1938: "Subject Directory Attribute field '"
1939: + dirattrfields[i]
1940: + "' must exist.");
1941: }
1942: }
1943:
1944: }
1945:
1946: /**
1947: * Method calculating the number of required fields of on kind that is configured for this profile.
1948: * @param field, one of the field constants
1949: * @return The number of required fields of that kind.
1950: */
1951: private int getNumberOfRequiredFields(String field) {
1952: int retval = 0;
1953: int size = getNumberOfField(field);
1954: for (int j = 0; j < size; j++) {
1955: if (isRequired(field, j)) {
1956: retval++;
1957: }
1958: }
1959:
1960: return retval;
1961: }
1962:
1963: private void checkIfForIllegalNumberOfFields(
1964: DNFieldExtractor subjectdnfields,
1965: DNFieldExtractor subjectaltnames,
1966: DNFieldExtractor subjectdirattrs)
1967: throws UserDoesntFullfillEndEntityProfile {
1968:
1969: // Check number of subjectdn fields.
1970: String[] dnfields = getSubjectDNProfileFields();
1971: Integer[] dnFieldExtractorIds = (Integer[]) DnComponents
1972: .getDnDnIds().toArray(new Integer[0]);
1973: for (int i = 0; i < dnfields.length; i++) {
1974: if (getNumberOfField(dnfields[i]) < subjectdnfields
1975: .getNumberOfFields(dnFieldExtractorIds[i]
1976: .intValue()))
1977: throw new UserDoesntFullfillEndEntityProfile(
1978: "Wrong number of " + dnfields[i]
1979: + " fields in Subject DN.");
1980: }
1981:
1982: // Check number of subject alternate name fields.
1983: String[] altnamefields = getSubjectAltnameProfileFields();
1984: Integer[] altNameFieldExtractorIds = (Integer[]) DnComponents
1985: .getAltNameDnIds().toArray(new Integer[0]);
1986: for (int i = 0; i < altnamefields.length; i++) {
1987: if (getNumberOfField(altnamefields[i]) < subjectaltnames
1988: .getNumberOfFields(altNameFieldExtractorIds[i]
1989: .intValue()))
1990: throw new UserDoesntFullfillEndEntityProfile(
1991: "Wrong number of "
1992: + altnamefields[i]
1993: + " fields in Subject Alternative Name.");
1994: }
1995:
1996: // Check number of subject directory attribute fields.
1997: String[] dirattrfields = getSubjectDirAttrProfileFields();
1998: Integer[] dirAttrFieldExtractorIds = (Integer[]) DnComponents
1999: .getDirAttrDnIds().toArray(new Integer[0]);
2000: for (int i = 0; i < dirattrfields.length; i++) {
2001: if (getNumberOfField(dirattrfields[i]) < subjectdirattrs
2002: .getNumberOfFields(dirAttrFieldExtractorIds[i]
2003: .intValue()))
2004: throw new UserDoesntFullfillEndEntityProfile(
2005: "Wrong number of "
2006: + dirattrfields[i]
2007: + " fields in Subject Directory Attributes.");
2008: }
2009: }
2010:
2011: /** methods for mapping the DN, AltName, DirAttr constants from string->number
2012: *
2013: */
2014: private static int getParameterNumber(String parameter) {
2015: Integer number = (Integer) dataConstants.get(parameter);
2016: if (number != null) {
2017: return number.intValue();
2018: }
2019: log.error("No parameter number for " + parameter);
2020: return -1;
2021: }
2022:
2023: /** methods for mapping the DN, AltName, DirAttr constants from number->string
2024: *
2025: */
2026: private static String getParameter(int parameterNumber) {
2027: Set set = dataConstants.entrySet();
2028: Iterator iter = set.iterator();
2029: String ret = null;
2030: while (iter.hasNext() && ret == null) {
2031: Map.Entry entry = (Map.Entry) iter.next();
2032: Integer val = (Integer) entry.getValue();
2033: if (val.intValue() == parameterNumber) {
2034: ret = (String) entry.getKey();
2035: }
2036: }
2037: if (ret == null) {
2038: log.error("No parameter for " + parameterNumber);
2039: }
2040: return ret;
2041: }
2042:
2043: private void incrementFieldnumber(int parameter) {
2044: ArrayList numberarray = (ArrayList) data.get(NUMBERARRAY);
2045: numberarray.set(parameter, new Integer(((Integer) numberarray
2046: .get(parameter)).intValue() + 1));
2047: }
2048:
2049: private void decrementFieldnumber(int parameter) {
2050: ArrayList numberarray = (ArrayList) data.get(NUMBERARRAY);
2051: numberarray.set(parameter, new Integer(((Integer) numberarray
2052: .get(parameter)).intValue() - 1));
2053: }
2054:
2055: // Private Constants.
2056: private static final int FIELDBOUNDRARY = 10000;
2057: private static final int NUMBERBOUNDRARY = 100;
2058:
2059: public static String[] getSubjectDNProfileFields() {
2060: return (String[]) DnComponents.getDnProfileFields().toArray(
2061: new String[0]);
2062: }
2063:
2064: public static String[] getSubjectAltnameProfileFields() {
2065: return (String[]) DnComponents.getAltNameFields().toArray(
2066: new String[0]);
2067: }
2068:
2069: public static String[] getSubjectDirAttrProfileFields() {
2070: return (String[]) DnComponents.getDirAttrFields().toArray(
2071: new String[0]);
2072: }
2073:
2074: private static final String NUMBERARRAY = "NUMBERARRAY";
2075: private static final String SUBJECTDNFIELDORDER = "SUBJECTDNFIELDORDER";
2076: private static final String SUBJECTALTNAMEFIELDORDER = "SUBJECTALTNAMEFIELDORDER";
2077: private static final String SUBJECTDIRATTRFIELDORDER = "SUBJECTDIRATTRFIELDORDER";
2078:
2079: private static final String USERNOTIFICATIONS = "USERNOTIFICATIONS";
2080:
2081: private static final String REUSECERTIFICATE = "REUSECERTIFICATE";
2082: private static final String REVERSEFFIELDCHECKS = "REVERSEFFIELDCHECKS";
2083:
2084: private static final String PRINTINGUSE = "PRINTINGUSE";
2085: private static final String PRINTINGDEFAULT = "PRINTINGDEFAULT";
2086: private static final String PRINTINGREQUIRED = "PRINTINGREQUIRED";
2087: private static final String PRINTINGCOPIES = "PRINTINGCOPIES";
2088: private static final String PRINTINGPRINTERNAME = "PRINTINGPRINTERNAME";
2089: private static final String PRINTINGSVGFILENAME = "PRINTINGSVGFILENAME";
2090: private static final String PRINTINGSVGDATA = "PRINTINGSVGDATA";
2091: // Private fields.
2092:
2093: }
|