| | |
| | | @Override |
| | | public void run() |
| | | { |
| | | for (PersistentSearch psearch : wfe.getPersistentSearches()) |
| | | for (PersistentSearch psearch : backend.getPersistentSearches()) |
| | | { |
| | | psearch.processModify(modifiedEntry, currentEntry); |
| | | } |
| | |
| | | Control c = iter.next(); |
| | | String oid = c.getOID(); |
| | | |
| | | if (oid.equals(OID_LDAP_ASSERTION)) |
| | | if (OID_LDAP_ASSERTION.equals(oid)) |
| | | { |
| | | LDAPAssertionRequestControl assertControl = |
| | | getRequestControl(LDAPAssertionRequestControl.DECODER); |
| | |
| | | de.getMessageObject())); |
| | | } |
| | | } |
| | | else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED)) |
| | | else if (OID_LDAP_NOOP_OPENLDAP_ASSIGNED.equals(oid)) |
| | | { |
| | | noOp = true; |
| | | } |
| | | else if (oid.equals(OID_PERMISSIVE_MODIFY_CONTROL)) |
| | | else if (OID_PERMISSIVE_MODIFY_CONTROL.equals(oid)) |
| | | { |
| | | permissiveModify = true; |
| | | } |
| | | else if (oid.equals(OID_LDAP_READENTRY_PREREAD)) |
| | | else if (OID_LDAP_READENTRY_PREREAD.equals(oid)) |
| | | { |
| | | preReadRequest = getRequestControl(LDAPPreReadRequestControl.DECODER); |
| | | } |
| | | else if (oid.equals(OID_LDAP_READENTRY_POSTREAD)) |
| | | else if (OID_LDAP_READENTRY_POSTREAD.equals(oid)) |
| | | { |
| | | if (c instanceof LDAPPostReadRequestControl) |
| | | { |
| | |
| | | iter.set(postReadRequest); |
| | | } |
| | | } |
| | | else if (oid.equals(OID_PROXIED_AUTH_V1)) |
| | | else if (OID_PROXIED_AUTH_V1.equals(oid)) |
| | | { |
| | | // Log usage of legacy proxy authz V1 control. |
| | | addAdditionalLogItem(AdditionalLogItem.keyOnly(getClass(), |
| | |
| | | setAuthorizationEntry(authorizationEntry); |
| | | setProxiedAuthorizationDN(getDN(authorizationEntry)); |
| | | } |
| | | else if (oid.equals(OID_PROXIED_AUTH_V2)) |
| | | else if (OID_PROXIED_AUTH_V2.equals(oid)) |
| | | { |
| | | // The requester must have the PROXIED_AUTH privilege in order to |
| | | // be able to use this control. |
| | |
| | | setAuthorizationEntry(authorizationEntry); |
| | | setProxiedAuthorizationDN(getDN(authorizationEntry)); |
| | | } |
| | | else if (oid.equals(OID_PASSWORD_POLICY_CONTROL)) |
| | | else if (OID_PASSWORD_POLICY_CONTROL.equals(oid)) |
| | | { |
| | | pwPolicyControlRequested = true; |
| | | } |
| | |
| | | // See if the attribute is one which controls the privileges available for |
| | | // a user. If it is, then the client must have the PRIVILEGE_CHANGE |
| | | // privilege. |
| | | if (t.hasName(OP_ATTR_PRIVILEGE_NAME)) |
| | | if (t.hasName(OP_ATTR_PRIVILEGE_NAME) |
| | | && !clientConnection.hasPrivilege(Privilege.PRIVILEGE_CHANGE, this)) |
| | | { |
| | | if (! clientConnection.hasPrivilege(Privilege.PRIVILEGE_CHANGE, this)) |
| | | { |
| | | throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS, |
| | | ERR_MODIFY_CHANGE_PRIVILEGE_INSUFFICIENT_PRIVILEGES.get()); |
| | | } |
| | | throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS, |
| | | ERR_MODIFY_CHANGE_PRIVILEGE_INSUFFICIENT_PRIVILEGES.get()); |
| | | } |
| | | |
| | | // If the modification is not updating the password attribute, |
| | |
| | | numPasswords = passwordsToAdd; |
| | | } |
| | | |
| | | // If there were multiple password values, then make sure that's |
| | | // OK. |
| | | if ((!isInternalOperation()) |
| | | && (!pwPolicyState.getAuthenticationPolicy() |
| | | .isAllowMultiplePasswordValues()) && (passwordsToAdd > 1)) |
| | | // If there were multiple password values, then make sure that's OK. |
| | | final PasswordPolicy authPolicy = pwPolicyState.getAuthenticationPolicy(); |
| | | if (!isInternalOperation() |
| | | && !authPolicy.isAllowMultiplePasswordValues() |
| | | && passwordsToAdd > 1) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | |
| | | { |
| | | if (pwPolicyState.passwordIsPreEncoded(v.getValue())) |
| | | { |
| | | if ((!isInternalOperation()) |
| | | && !pwPolicyState.getAuthenticationPolicy() |
| | | .isAllowPreEncodedPasswords()) |
| | | if (!isInternalOperation() |
| | | && !authPolicy.isAllowPreEncodedPasswords()) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | |
| | | } |
| | | else |
| | | { |
| | | if (m.getModificationType() == ModificationType.ADD) |
| | | if (m.getModificationType() == ModificationType.ADD |
| | | // Make sure that the password value does not already exist. |
| | | && pwPolicyState.passwordMatches(v.getValue())) |
| | | { |
| | | // Make sure that the password value doesn't already exist. |
| | | if (pwPolicyState.passwordMatches(v.getValue())) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.PASSWORD_IN_HISTORY; |
| | | throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS, |
| | | ERR_MODIFY_PASSWORD_EXISTS.get()); |
| | | } |
| | | pwpErrorType = PasswordPolicyErrorType.PASSWORD_IN_HISTORY; |
| | | throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS, |
| | | ERR_MODIFY_PASSWORD_EXISTS.get()); |
| | | } |
| | | |
| | | if (newPasswords == null) |
| | |
| | | else |
| | | { |
| | | List<Attribute> attrList = currentEntry.getAttribute(pwAttr.getAttributeType()); |
| | | if ((attrList == null) || (attrList.isEmpty())) |
| | | if (attrList == null || attrList.isEmpty()) |
| | | { |
| | | throw new DirectoryException(ResultCode.NO_SUCH_ATTRIBUTE, |
| | | ERR_MODIFY_NO_EXISTING_VALUES.get()); |
| | |
| | | .decodeAuthPassword(av.getValue().toString()); |
| | | PasswordStorageScheme<?> scheme = DirectoryServer |
| | | .getAuthPasswordStorageScheme(components[0].toString()); |
| | | if (scheme != null) |
| | | if (scheme != null |
| | | && scheme.authPasswordMatches(v.getValue(), components[1] |
| | | .toString(), components[2].toString())) |
| | | { |
| | | if (scheme.authPasswordMatches(v.getValue(), components[1] |
| | | .toString(), components[2].toString())) |
| | | { |
| | | builder.add(av); |
| | | found = true; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (av.equals(v)) |
| | | { |
| | | builder.add(v); |
| | | builder.add(av); |
| | | found = true; |
| | | } |
| | | } |
| | | else if (av.equals(v)) |
| | | { |
| | | builder.add(v); |
| | | found = true; |
| | | } |
| | | } |
| | | else |
| | | else if (UserPasswordSyntax.isEncoded(av.getValue())) |
| | | { |
| | | if (UserPasswordSyntax.isEncoded(av.getValue())) |
| | | String[] components = UserPasswordSyntax.decodeUserPassword(av |
| | | .getValue().toString()); |
| | | PasswordStorageScheme<?> scheme = DirectoryServer |
| | | .getPasswordStorageScheme(toLowerCase(components[0])); |
| | | if (scheme != null |
| | | && scheme.passwordMatches(v.getValue(), ByteString.valueOf(components[1]))) |
| | | { |
| | | String[] components = UserPasswordSyntax.decodeUserPassword(av |
| | | .getValue().toString()); |
| | | PasswordStorageScheme<?> scheme = DirectoryServer |
| | | .getPasswordStorageScheme(toLowerCase(components[0])); |
| | | if (scheme != null) |
| | | { |
| | | if (scheme.passwordMatches(v.getValue(), ByteString.valueOf( |
| | | components[1]))) |
| | | { |
| | | builder.add(av); |
| | | found = true; |
| | | } |
| | | } |
| | | builder.add(av); |
| | | found = true; |
| | | } |
| | | else |
| | | { |
| | | if (av.equals(v)) |
| | | { |
| | | builder.add(v); |
| | | found = true; |
| | | } |
| | | } |
| | | } |
| | | else if (av.equals(v)) |
| | | { |
| | | builder.add(v); |
| | | found = true; |
| | | } |
| | | } |
| | | } |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | lowerName = toLowerCase(v.getValue().toString()); |
| | | lowerName = toLowerCase(name); |
| | | } |
| | | |
| | | ObjectClass oc = DirectoryServer.getObjectClass(lowerName); |
| | |
| | | AttributeBuilder builder = new AttributeBuilder(a, true); |
| | | for (AttributeValue existingValue : a) |
| | | { |
| | | String s = existingValue.getValue().toString(); |
| | | final String value = existingValue.getValue().toString(); |
| | | long currentValue; |
| | | try |
| | | { |
| | | currentValue = Long.parseLong(s); |
| | | currentValue = Long.parseLong(value); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | ERR_MODIFY_INCREMENT_REQUIRES_INTEGER_VALUE.get(String |
| | | .valueOf(entryDN), a.getName(), |
| | | existingValue.getValue().toString()), |
| | | ERR_MODIFY_INCREMENT_REQUIRES_INTEGER_VALUE.get( |
| | | String.valueOf(entryDN), a.getName(), value), |
| | | e); |
| | | } |
| | | |
| | |
| | | public void performAdditionalPasswordChangedProcessing() |
| | | throws DirectoryException |
| | | { |
| | | if (pwPolicyState == null) |
| | | { |
| | | // Account not managed locally so nothing to do. |
| | | return; |
| | | } |
| | | |
| | | if (!passwordChanged) |
| | | if (!passwordChanged |
| | | || pwPolicyState == null) // Account not managed locally |
| | | { |
| | | // Nothing to do. |
| | | return; |
| | |
| | | |
| | | |
| | | // If any of the password values should be validated, then do so now. |
| | | if (selfChange || !authPolicy.isSkipValidationForAdministrators()) |
| | | if (newPasswords != null |
| | | && (selfChange || !authPolicy.isSkipValidationForAdministrators())) |
| | | { |
| | | if (newPasswords != null) |
| | | HashSet<ByteString> clearPasswords = new HashSet<ByteString>(pwPolicyState.getClearPasswords()); |
| | | if (currentPasswords != null) |
| | | { |
| | | HashSet<ByteString> clearPasswords = new HashSet<ByteString>(); |
| | | clearPasswords.addAll(pwPolicyState.getClearPasswords()); |
| | | |
| | | if (currentPasswords != null) |
| | | if (clearPasswords.isEmpty()) |
| | | { |
| | | if (clearPasswords.isEmpty()) |
| | | for (AttributeValue v : currentPasswords) |
| | | { |
| | | for (AttributeValue v : currentPasswords) |
| | | { |
| | | clearPasswords.add(v.getValue()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // NOTE: We can't rely on the fact that Set doesn't allow |
| | | // duplicates because technically it's possible that the values |
| | | // aren't duplicates if they are ASN.1 elements with different types |
| | | // (like 0x04 for a standard universal octet string type versus 0x80 |
| | | // for a simple password in a bind operation). So we have to |
| | | // manually check for duplicates. |
| | | for (AttributeValue v : currentPasswords) |
| | | { |
| | | ByteString pw = v.getValue(); |
| | | |
| | | boolean found = false; |
| | | for (ByteString s : clearPasswords) |
| | | { |
| | | if (s.equals(pw)) |
| | | { |
| | | found = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (! found) |
| | | { |
| | | clearPasswords.add(pw); |
| | | } |
| | | } |
| | | clearPasswords.add(v.getValue()); |
| | | } |
| | | } |
| | | |
| | | for (AttributeValue v : newPasswords) |
| | | else |
| | | { |
| | | MessageBuilder invalidReason = new MessageBuilder(); |
| | | if (! pwPolicyState.passwordIsAcceptable(this, modifiedEntry, |
| | | v.getValue(), clearPasswords, invalidReason)) |
| | | // NOTE: We can't rely on the fact that Set doesn't allow |
| | | // duplicates because technically it's possible that the values |
| | | // aren't duplicates if they are ASN.1 elements with different types |
| | | // (like 0x04 for a standard universal octet string type versus 0x80 |
| | | // for a simple password in a bind operation). So we have to |
| | | // manually check for duplicates. |
| | | for (AttributeValue v : currentPasswords) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | | ERR_MODIFY_PW_VALIDATION_FAILED.get(invalidReason)); |
| | | clearPasswords.add(v.getValue()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (AttributeValue v : newPasswords) |
| | | { |
| | | MessageBuilder invalidReason = new MessageBuilder(); |
| | | if (! pwPolicyState.passwordIsAcceptable(this, modifiedEntry, |
| | | v.getValue(), clearPasswords, invalidReason)) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | | ERR_MODIFY_PW_VALIDATION_FAILED.get(invalidReason)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we should check the password history, then do so now. |
| | | if (pwPolicyState.maintainHistory()) |
| | | if (newPasswords != null && pwPolicyState.maintainHistory()) |
| | | { |
| | | if (newPasswords != null) |
| | | for (AttributeValue v : newPasswords) |
| | | { |
| | | for (AttributeValue v : newPasswords) |
| | | if (pwPolicyState.isPasswordInHistory(v.getValue()) |
| | | && (selfChange || !authPolicy.isSkipValidationForAdministrators())) |
| | | { |
| | | if (pwPolicyState.isPasswordInHistory(v.getValue()) |
| | | && (selfChange || !authPolicy.isSkipValidationForAdministrators())) |
| | | { |
| | | pwpErrorType = PasswordPolicyErrorType.PASSWORD_IN_HISTORY; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | | ERR_MODIFY_PW_IN_HISTORY.get()); |
| | | } |
| | | pwpErrorType = PasswordPolicyErrorType.PASSWORD_IN_HISTORY; |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | | ERR_MODIFY_PW_IN_HISTORY.get()); |
| | | } |
| | | |
| | | pwPolicyState.updatePasswordHistory(); |
| | | } |
| | | |
| | | pwPolicyState.updatePasswordHistory(); |
| | | } |
| | | |
| | | |
| | |
| | | return; |
| | | } |
| | | |
| | | if (!(passwordChanged || enabledStateChanged || wasLocked)) |
| | | if (!passwordChanged && !enabledStateChanged && !wasLocked) |
| | | { |
| | | // Account managed locally, but unchanged, so nothing to do. |
| | | return; |