- private static final String AAF_DATA_DIR = "aaf_data_dir";
- private static final String PROPERTY_IS_REQUIRED = " property is Required";
- // Package on Purpose
- final String domain;
- final String atDomain;
- final String realm;
-
- private final String NAME,mailHost,mailFrom;
-
- public DefaultOrg(Env env, String realm) throws OrganizationException {
- this.realm = realm;
- domain=FQI.reverseDomain(realm);
- atDomain = '@'+domain;
- String s;
- NAME=env.getProperty(realm + ".name","Default Organization");
- mailHost = env.getProperty(s=(realm + ".mailHost"), null);
- if(mailHost==null) {
- throw new OrganizationException(s + PROPERTY_IS_REQUIRED);
- }
- mailFrom = env.getProperty(s=(realm + ".mailFrom"), null);
- if(mailFrom==null) {
- throw new OrganizationException(s + PROPERTY_IS_REQUIRED);
- }
-
- System.getProperties().setProperty("mail.smtp.host",mailHost);
- System.getProperties().setProperty("mail.user", mailFrom);
- // Get the default Session object.
- session = Session.getDefaultInstance(System.getProperties());
-
- try {
- String defFile;
- String temp=env.getProperty(defFile = (getClass().getName()+".file"));
- File fIdentities=null;
- if(temp==null) {
- temp = env.getProperty(AAF_DATA_DIR);
- if(temp!=null) {
- env.warn().log(defFile, "is not defined. Using default: ",temp+"/identities.dat");
- File dir = new File(temp);
- fIdentities=new File(dir,"identities.dat");
- if(!fIdentities.exists()) {
- env.warn().log("No",fIdentities.getCanonicalPath(),"exists. Creating.");
- if(!dir.exists()) {
- dir.mkdirs();
- }
- fIdentities.createNewFile();
- }
- }
- } else {
- fIdentities = new File(temp);
- if(!fIdentities.exists()) {
- String dataDir = env.getProperty(AAF_DATA_DIR);
- if(dataDir!=null) {
- fIdentities = new File(dataDir,temp);
- }
- }
- }
-
- if(fIdentities!=null && fIdentities.exists()) {
- identities = new Identities(fIdentities);
- } else {
- throw new OrganizationException(fIdentities.getCanonicalPath() + " does not exist.");
- }
- } catch (IOException e) {
- throw new OrganizationException(e);
- }
- }
-
- // Implement your own Delegation System
- static final List<String> NULL_DELEGATES = new ArrayList<String>();
-
- public Identities identities;
- private boolean dryRun;
- private Session session;
- public enum Types {Employee, Contractor, Application, NotActive};
- private final static Set<String> typeSet;
-
- static {
- typeSet = new HashSet<String>();
- for(Types t : Types.values()) {
- typeSet.add(t.name());
- }
- }
-
- private static final EmailWarnings emailWarnings = new DefaultOrgWarnings();
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public String getRealm() {
- return realm;
- }
-
- @Override
- public String getDomain() {
- return domain;
- }
-
- @Override
- public DefaultOrgIdentity getIdentity(AuthzTrans trans, String id) throws OrganizationException {
- int at = id.indexOf('@');
- return new DefaultOrgIdentity(trans,at<0?id:id.substring(0, at),this);
- }
-
- // Note: Return a null if found; return a String Message explaining why not found.
- @Override
- public String isValidID(final AuthzTrans trans, final String id) {
- try {
- DefaultOrgIdentity u = getIdentity(trans,id);
- return (u==null||!u.isFound())?id + "is not an Identity in " + getName():null;
- } catch (OrganizationException e) {
- return getName() + " could not lookup " + id + ": " + e.getLocalizedMessage();
- }
- }
- // Possible ID Pattern
- // private static final Pattern ID_PATTERN=Pattern.compile("([\\w.-]+@[\\w.-]+).{4-13}");
- // Another one: ID_PATTERN = "(a-z[a-z0-9]{5-8}@.*).{4-13}";
-
- @Override
- public boolean isValidCred(final AuthzTrans trans, final String id) {
- // have domain?
- int at = id.indexOf('@');
- String sid;
- if(at > 0) {
- // Use this to prevent passwords to any but THIS domain.
-// if(!id.regionMatches(at+1, domain, 0, id.length()-at-1)) {
-// return false;
-// }
- sid = id.substring(0,at);
- } else {
- sid = id;
- }
- // We'll validate that it exists, rather than check patterns.
-
- return isValidID(trans, sid)==null;
- // Check Pattern (if checking existing is too long)
- // if(id.endsWith(SUFFIX) && ID_PATTERN.matcher(id).matches()) {
- // return true;
- // }
- // return false;
- }
-
- private static final String SPEC_CHARS = "!@#$%^*-+?/,:;.";
- private static final Pattern PASS_PATTERN=Pattern.compile("((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[" + SPEC_CHARS +"]).{6,20})");
- /**
- * Attribution: from mkyong.com
- * ( # Start of group
- * (?=.*\d) # must contains one digit from 0-9
- * (?=.*[a-z]) # must contains one lowercase characters
- * (?=.*[A-Z]) # must contains one uppercase characters
- * (?=.*[@#$%]) # must contains one special symbols in the list SPEC_CHARS
- * . # match anything with previous condition checking
- * {6,20} # length at least 6 characters and maximum of 20
- * ) # End of group
- */
- @Override
- public String isValidPassword(final AuthzTrans trans, final String user, final String password, final String... prev) {
- for(String p : prev) {
- if(password.contains(p)) { // A more sophisticated algorithm might be better.
- return "Password too similar to previous passwords";
- }
- }
- // If you have an Organization user/Password scheme, replace the following
- if(PASS_PATTERN.matcher(password).matches()) {
- return "";
- }
- return "Password does not match " + NAME + " Password Standards";
- }
-
- private static final String[] rules = new String[] {
- "Passwords must contain one digit from 0-9",
- "Passwords must contain one lowercase character",
- "Passwords must contain one uppercase character",
- "Passwords must contain one special symbols in the list \""+ SPEC_CHARS + '"',
- "Passwords must be between 6 and 20 chars in length"
- };
-
- @Override
- public String[] getPasswordRules() {
- return rules;
- }
-
- @Override
- public Set<String> getIdentityTypes() {
- return typeSet;
- }
-
- @Override
- public Response notify(AuthzTrans trans, Notify type, String url, String[] identities, String[] ccs, String summary, Boolean urgent) {
- String system = trans.getProperty("CASS_ENV", "");
-
- ArrayList<String> toList = new ArrayList<String>();
- Identity identity;
- if (identities != null) {
- for (String user : identities) {
- try {
- identity = getIdentity(trans, user);
- if (identity == null) {
- trans.error().log(
- "Failure to obtain User " + user + " for "
- + getName());
- } else {
- toList.add(identity.email());
- }
- } catch (Exception e) {
- trans.error().log(
- e,
- "Failure to obtain User " + user + " for "
- + getName());
- }
- }
- }
-
- if (toList.isEmpty()) {
- trans.error().log("No Users listed to email");
- return Response.ERR_NotificationFailure;
- }
-
- ArrayList<String> ccList = new ArrayList<String>();
-
- // If we're sending an urgent email, CC the user's supervisor
- //
- if (urgent) {
- trans.info().log("urgent msg for: " + identities[0]);
- try {
- List<Identity> supervisors = getApprovers(trans, identities[0]);
- for (Identity us : supervisors) {
- trans.info().log("supervisor: " + us.email());
- ccList.add(us.email());
- }
- } catch (Exception e) {
- trans.error().log(e,
- "Failed to find supervisor for " + identities[0]);
- }
- }
-
- if (ccs != null) {
- for (String user : ccs) {
- try {
- identity = getIdentity(trans, user);
- ccList.add(identity.email());
- } catch (Exception e) {
- trans.error().log(
- e,
- "Failure to obtain User " + user + " for "
- + getName());
- }
- }
- }
-
- if (summary == null) {
- summary = "";
- }
-
- switch (type) {
- case Approval:
- try {
- sendEmail(trans, toList, ccList,
- "AAF Approval Notification "
- + (system.length() == 0 ? "" : "(ENV: "
- + system + ")"),
- "AAF is the "
- + NAME
- + "System for Fine-Grained Authorizations. You are being asked to Approve"
- + (system.length() == 0 ? "" : " in the "
- + system + " environment")
- + " before AAF Actions can be taken.\n\n"
- + "Please follow this link: \n\n\t" + url
- + "\n\n" + summary, urgent);
- } catch (Exception e) {
- trans.error().log(e, "Failure to send Email");
- return Response.ERR_NotificationFailure;
- }
- break;
- case PasswordExpiration:
- try {
- sendEmail(trans,
- toList,
- ccList,
- "AAF Password Expiration Warning "
- + (system.length() == 0 ? "" : "(ENV: "
- + system + ")"),
- "AAF is the "
- + NAME
- + " System for Authorizations.\n\nOne or more passwords will expire soon or have expired"
- + (system.length() == 0 ? "" : " in the "
- + system + " environment")
- + ".\n\nPasswords expired for more than 30 days without action are subject to deletion.\n\n"
- + "Please follow each link to add a New Password with Expiration Date. Either are valid until expiration. "
- + "Use this time to change the passwords on your system. If issues, reply to this email.\n\n"
- + summary, urgent);
- } catch (Exception e) {
- trans.error().log(e, "Failure to send Email");
- return Response.ERR_NotificationFailure;
- }
- break;
-
- case RoleExpiration:
- try {
- sendEmail(
- trans,
- toList,
- ccList,
- "AAF Role Expiration Warning "
- + (system.length() == 0 ? "" : "(ENV: "
- + system + ")"),
- "AAF is the "
- + NAME
- + " System for Authorizations. One or more roles will expire soon"
- + (system.length() == 0 ? "" : " in the "
- + system + " environment")
- + ".\n\nRoles expired for more than 30 days are subject to deletion."
- + "Please follow this link the GUI Command line, and either 'extend' or 'del' the user in the role.\n"
- + "If issues, reply to this email.\n\n\t" + url
- + "\n\n" + summary, urgent);
- } catch (Exception e) {
- trans.error().log(e, "Failure to send Email");
- return Response.ERR_NotificationFailure;
- }
- break;
- default:
- return Response.ERR_NotImplemented;
- }
- return Response.OK;
- }
-
- @Override
- public int sendEmail(AuthzTrans trans, List<String> toList, List<String> ccList, String subject, String body,
- Boolean urgent) throws OrganizationException {
- int status = 1;
-
- List<String> to = new ArrayList<String>();
- for(String em : toList) {
- if(em.indexOf('@')<0) {
- to.add(new DefaultOrgIdentity(trans, em, this).email());
- } else {
- to.add(em);
- }
- }
-
- List<String> cc = new ArrayList<String>();
- if(ccList!=null && !ccList.isEmpty()) {
- for(String em : ccList) {
- if(em.indexOf('@')<0) {
- cc.add(new DefaultOrgIdentity(trans, em, this).email());
- } else {
- cc.add(em);
- }
- }
- }
-
-
- // for now, I want all emails so we can see what goes out. Remove later
- if (!ccList.contains(mailFrom)) {
- ccList.add(mailFrom);
- }
-
- try {
- // Create a default MimeMessage object.
- MimeMessage message = new MimeMessage(session);
-
- // Set From: header field of the header.
- message.setFrom(new InternetAddress(mailFrom));
-
- if (!dryRun) {
- // Set To: header field of the header. This is a required field
- // and calling module should make sure that it is not null or
- // blank
- message.addRecipients(Message.RecipientType.TO,getAddresses(to));
-
- // Set CC: header field of the header.
- if ((ccList != null) && (ccList.size() > 0)) {
- message.addRecipients(Message.RecipientType.CC,getAddresses(cc));
- }
-
- // Set Subject: header field
- message.setSubject(subject);
-
- if (urgent) {
- message.addHeader("X-Priority", "1");
- }
-
- // Now set the actual message
- message.setText(body);
- } else {
- // override recipients
- message.addRecipients(Message.RecipientType.TO,
- InternetAddress.parse(mailFrom));
-
- // Set Subject: header field
- message.setSubject("[TESTMODE] " + subject);
-
- if (urgent) {
- message.addHeader("X-Priority", "1");
- }
-
- ArrayList<String> newBody = new ArrayList<String>();
-
- Address temp[] = getAddresses(to);
- String headerString = "TO:\t" + InternetAddress.toString(temp) + "\n";