These changes implement a new ACI bind rule keyword "ssf".
This keyword allows users to control the level of access based on the
security level of the connection.
issue: https://opends.dev.java.net/issues/show_bug.cgi?id=3497
Web page: https://www.opends.org/wiki/page/SSFBindRule
2 files added
12 files modified
| | |
| | | SEVERE_WARN_ACI_ATTRIBUTE_NOT_INDEXED_96=Backend %s does not have a \ |
| | | presence index defined for attribute type %s. Access control initialization \ |
| | | may take a very long time to complete in this backend |
| | | SEVERE_WARN_ACI_SYNTAX_INVALID_SSF_FORMAT_97=The provided Access Control \ |
| | | Instruction (ACI) bind rule SSF expression "%s" failed to parse for \ |
| | | the following reason: "%s" |
| | | SEVERE_WARN_ACI_SYNTAX_INVALID_SSF_RANGE_98=The provided Access Control \ |
| | | Instruction (ACI) bind rule ssf expression value "%s" is not in the \ |
| | | valid range. A valid ssf value is in the range of 1 to 1024 |
| | | SEVERE_WARN_ACI_SYNTAX_INVALID_TIMEOFDAY_FORMAT_99=The provided Access Control \ |
| | | Instruction (ACI) bind rule timeofday expression "%s" failed to parse for \ |
| | | the following reason: "%s" |
| | |
| | | * already disconnected the client. |
| | | */ |
| | | public abstract boolean writeData(ByteBuffer clearData); |
| | | |
| | | /** |
| | | * Return the Security Strength Factor. |
| | | * |
| | | * @return The SSF. |
| | | */ |
| | | public abstract int getSSF(); |
| | | } |
| | | |
| | |
| | | else |
| | | evalAllAttributes &= ~v; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public int getCurrentSSF() { |
| | | return clientConnection.getConnectionSecurityProvider().getSSF(); |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * Check if the remote client is bound anonymously. |
| | | * @return True if client is bound anonymously. |
| | | * @return {@code true} if client is bound anonymously. |
| | | */ |
| | | public boolean isAnonymousUser(); |
| | | |
| | |
| | | * @param authMethod The required authentication method. |
| | | * @param saslMech The required SASL mechanism if the authentication method |
| | | * is SASL. |
| | | * |
| | | * @return An evaluation result indicating whether the client connection |
| | | * has been authenticated using the required authentication method. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * Get the address of the bound connection. |
| | | * @return The address of the bound connection. |
| | | * @return The address of the bound connection. |
| | | */ |
| | | public InetAddress getRemoteAddress(); |
| | | |
| | | /** |
| | | * Return true if this is an add operation, needed by the userattr |
| | | * Return true if this is an add operation needed by the userattr |
| | | * USERDN parent inheritance level 0 processing. |
| | | * @return True if this is an add operation. |
| | | * |
| | | * @return {@code true} if this is an add operation. |
| | | */ |
| | | public boolean isAddOperation(); |
| | | |
| | |
| | | * ClientConnection.isMemberOf() method, which checks authorization |
| | | * DN membership in the specified group. |
| | | * @param group The group to check membership in. |
| | | * @return True if the authorization DN of the operation is a |
| | | * @return {@code true} if the authorization DN of the operation is a |
| | | * member of the specified group. |
| | | */ |
| | | public boolean isMemberOf(Group<?> group); |
| | | |
| | | /** |
| | | * Returns true if the hashtable of ACIs that matched the targattrfilters |
| | | * keyword evaluation is empty. Used by geteffectiverights evaluation to |
| | | * determine the access value to put in the "write" rights evaluation field. |
| | | * keyword evaluation is empty. Used in a geteffectiverights control |
| | | * evaluation to determine the access value to put in the "write" rights |
| | | * evaluation field. |
| | | * |
| | | * @return True if there were not any ACIs that matched targattrfilters |
| | | * keyword evaluation. |
| | | * @return {@code true} if there were not any ACIs that matched |
| | | * targattrfilters keyword evaluation. |
| | | */ |
| | | public boolean isTargAttrFilterMatchAciEmpty(); |
| | | |
| | | /** |
| | | * The context maintains a hashtable of ACIs that matched the targattrfilters |
| | | * keyword evaluation. The hasTargAttrFiltersMatchAci method returns true if |
| | | * the specified ACI is contained in that hashtable. Used by |
| | | * geteffectiverights evaluation to determine the access value to put in the |
| | | * "write" rights evaluation field. |
| | | * the specified ACI is contained in that hashtable. Used in a |
| | | * geteffectiverights control evaluation to determine the access value to put |
| | | * in the "write" rights evaluation field. |
| | | * |
| | | * @param aci The ACI that to evaluate if it contains a match during |
| | | * targattrfilters keyword evaluation. |
| | | * |
| | | * @return True if a specified ACI matched targattrfilters evaluation. |
| | | * @return {@code true} if a specified ACI matched targattrfilters evaluation. |
| | | */ |
| | | public boolean hasTargAttrFiltersMatchAci(Aci aci); |
| | | |
| | | /** |
| | | * Return true if an ACI that evaluated to deny or allow has an |
| | | * targattrfilters keyword. Used by geteffectiverights |
| | | * targattrfilters keyword. Used by geteffectiverights control |
| | | * evaluation to determine the access value to put in the "write" rights |
| | | * evaluation field. |
| | | * |
| | | * @param flag The integer value specifying either a deny or allow, but not |
| | | * both. |
| | | * |
| | | * @return True if the ACI that evaluated to |
| | | * @return {@code true} if the ACI has an targetattrfilters keyword. |
| | | */ |
| | | public boolean hasTargAttrFiltersMatchOp(int flag); |
| | | |
| | | /** |
| | | * Returns true if the evaluation context is being used in a |
| | | * geteffectiverights evaluation. |
| | | * Returns {@code true} if the evaluation context is being used in a |
| | | * geteffectiverights control evaluation. |
| | | * |
| | | * @return True if the evaluation context is being used in a |
| | | * geteffectiverights evaluation. |
| | | * @return {@code true} if the evaluation context is being used in a |
| | | * geteffectiverights control evaluation. |
| | | */ |
| | | public boolean isGetEffectiveRightsEval(); |
| | | |
| | | /** |
| | | * Set the name of the ACI that last matched a targattrfilters rule. Used |
| | | * in geteffectiverights targattrfilters "write" rights evaluation. |
| | | * in geteffectiverights control targattrfilters "write" evaluation. |
| | | * |
| | | * @param name The ACI name string matching the targattrfilters rule. |
| | | */ |
| | |
| | | /** |
| | | * Set a flag that specifies that a ACI that evaluated to either deny or |
| | | * allow contains a targattrfilters keyword. Used by geteffectiverights |
| | | * evaluation to determine the access value to put in the "write" rights |
| | | * evaluation field. |
| | | * control evaluation to determine the access value to put in the "write" |
| | | * rights evaluation field. |
| | | * |
| | | * @param flag Either the integer value representing an allow or a deny, |
| | | * but not both. |
| | |
| | | |
| | | /** |
| | | * Set the reason the last access evaluation was evaluated the way it |
| | | * was. Used by geteffectiverights evaluation to eventually build the |
| | | * was. Used by geteffectiverights control evaluation to eventually build the |
| | | * summary string. |
| | | * |
| | | * @param reason The enumeration representing the reason of the last access |
| | |
| | | |
| | | /** |
| | | * Return the reason the last access evaluation was evaluated the way it |
| | | * was. Used by geteffectiverights evaluation to build the summary string. |
| | | * was. Used by geteffectiverights control evaluation to build the summary |
| | | * string. |
| | | * |
| | | * @return The enumeration representing the reason of the last access |
| | | * evaluation. |
| | |
| | | |
| | | /** |
| | | * Set the ACI that decided that last access evaluation. Used by |
| | | * geteffectiverights evaluation to the build summary string. |
| | | * geteffectiverights control evaluation to the build summary string. |
| | | * |
| | | * @param aci The ACI that decided the last access evaluation. |
| | | */ |
| | |
| | | * |
| | | * @param rights The rights mask to check. |
| | | * |
| | | * @return True if the evaluation context contains a access right set. |
| | | * @return {@code true} if the evaluation context contains a access right set. |
| | | */ |
| | | public boolean hasRights(int rights); |
| | | |
| | | /** |
| | | * Return the name of the ACI that decided the last access evaluation. Used |
| | | * by geteffectiverights evaluation to build the summmary string. |
| | | * by geteffectiverights control evaluation to build the summary string. |
| | | * |
| | | * @return The name of the ACI that decided the last access evaluation. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * Return true if a evaluation context is being used in proxied authorization |
| | | * evaluation. |
| | | * control evaluation. |
| | | * |
| | | * @return True if evaluation context is being used in proxied authorization |
| | | * evaluation. |
| | | * @return {@code true} if evaluation context is being used in proxied |
| | | * authorization control evaluation. |
| | | */ |
| | | public boolean isProxiedAuthorization(); |
| | | |
| | |
| | | |
| | | /** |
| | | * Set the value of the summary string to the specified string. |
| | | * Used in geteffectiverights evaluation to build summary string. |
| | | * Used in get effective rights evaluation to build summary string. |
| | | * |
| | | * @param summary The string to set the summary string to |
| | | */ |
| | | public void setEvalSummary(String summary); |
| | | |
| | | /** |
| | | * Return the access evaluation summary string. Used by the geteffectiverights |
| | | * evaluation when a aclRightsInfo attribute was specified in a search. |
| | | * Return the access evaluation summary string. Used in a geteffectiverights |
| | | * control evaluation when an aclRightsInfo attribute was specified in a |
| | | * search request. |
| | | * |
| | | * @return The string describing the access evaluation. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * Return a string representation of the current right being evaluated. |
| | | * Used in geteffectiverights evaluation to build summary string. |
| | | * Used in geteffectiverights control evaluation to build summary string. |
| | | * |
| | | * @return String representation of the current right being evaluated. |
| | | */ |
| | |
| | | |
| | | /** |
| | | * Return the name of the ACI that last matched a targattrfilters rule. Used |
| | | * in geteffectiverights evaluation. |
| | | * in geteffectiverights control evaluation. |
| | | * |
| | | * @return The name of the ACI that last matched a targattrfilters rule. |
| | | * @return The name of the ACI that last matched a targattrfilters rule. |
| | | */ |
| | | public String getTargAttrFiltersAciName(); |
| | | |
| | |
| | | * This method is used to replace the current resource entry with that saved |
| | | * entry and back. |
| | | * |
| | | * @param val Specifies if the saved entry should be used or not. True if it |
| | | * should be used, false if the original resource entry should be used. |
| | | * @param val Specifies if the saved entry should be used or not. {@code true} |
| | | * if it should be used, {@code false} if the original resource entry should |
| | | * be used. |
| | | * |
| | | */ |
| | | public void useFullResourceEntry(boolean val); |
| | | |
| | | |
| | | /** |
| | | * Return the current SSF (Security Strength Factor) of the underlying |
| | | * connection. |
| | | * |
| | | * @return The current SSF of the connection. |
| | | */ |
| | | public int getCurrentSSF(); |
| | | } |
| | |
| | | rule = UserAttr.decode(expr, op); |
| | | break; |
| | | } |
| | | case SSF: |
| | | { |
| | | rule = SSF.decode(expr, op); |
| | | break; |
| | | } |
| | | default: { |
| | | Message message = WARN_ACI_SYNTAX_INVALID_BIND_RULE_KEYWORD.get( |
| | | keyword.toString()); |
| | |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * authmethod. |
| | | */ |
| | | AUTHMETHOD ("authmethod"); |
| | | AUTHMETHOD ("authmethod"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * ssf. |
| | | */ |
| | | SSF("ssf"); |
| | | |
| | | /* |
| | | * The keyword name. |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import org.opends.messages.Message; |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | /** |
| | | * The class represents the ssf keyword in a bind rule.SSF stands for |
| | | * security strength factor. |
| | | * |
| | | */ |
| | | public class SSF implements KeywordBindRule { |
| | | |
| | | /* |
| | | * Enumeration representing the bind rule operation type. |
| | | */ |
| | | private EnumBindRuleType type=null; |
| | | |
| | | private static final int MAX_KEY_BITS=1024; |
| | | private int ssf; |
| | | |
| | | private SSF(int ssf, EnumBindRuleType type) { |
| | | this.ssf = ssf; |
| | | this.type = type; |
| | | } |
| | | |
| | | /** |
| | | * Create SSF instance using the specified expression string and bind rule |
| | | * type enumeration. |
| | | * @param expr The expression string. |
| | | * @param type The bind rule type enumeration. |
| | | * @return A SSF instance. |
| | | * @throws AciException If the SSF instance cannot be created. |
| | | */ |
| | | static SSF |
| | | decode(String expr, EnumBindRuleType type) throws AciException { |
| | | int valueAsInt = 0; |
| | | try { |
| | | valueAsInt = Integer.parseInt(expr); |
| | | } catch (NumberFormatException nfe) { |
| | | Message message = |
| | | WARN_ACI_SYNTAX_INVALID_SSF_FORMAT.get(expr, nfe.getMessage()); |
| | | throw new AciException(message); |
| | | } |
| | | if ((valueAsInt <= 0) || (valueAsInt > MAX_KEY_BITS)) { |
| | | Message message = WARN_ACI_SYNTAX_INVALID_SSF_RANGE.get(expr); |
| | | throw new AciException(message); |
| | | } |
| | | return new SSF(valueAsInt, type); |
| | | } |
| | | |
| | | /** |
| | | * Evaluate the specified evaluation context. |
| | | * @param evalCtx The evaluation context to evaluate. |
| | | * |
| | | * @return An evaluation result enumeration containing the result of the |
| | | * context evaluation. |
| | | */ |
| | | public EnumEvalResult evaluate(AciEvalContext evalCtx) { |
| | | EnumEvalResult matched=EnumEvalResult.FALSE; |
| | | int currentSSF = evalCtx.getCurrentSSF(); |
| | | switch (type) { |
| | | case EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF == ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | |
| | | case NOT_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF != ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | |
| | | case LESS_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF <= ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | |
| | | case LESS_BINDRULE_TYPE: |
| | | if (currentSSF < ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | |
| | | case GREATER_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF >= ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | |
| | | case GREATER_BINDRULE_TYPE: |
| | | if (currentSSF > ssf) |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | return matched.getRet(type, false); |
| | | } |
| | | } |
| | |
| | | */ |
| | | public static TimeOfDay decode(String expr, EnumBindRuleType type) |
| | | throws AciException { |
| | | int valueAsInt = 0; |
| | | if (!Pattern.matches(timeofdayRegex, expr)) |
| | | { |
| | | Message message = WARN_ACI_SYNTAX_INVALID_TIMEOFDAY.get(expr); |
| | | throw new AciException(message); |
| | | } |
| | | int valueAsInt = Integer.parseInt(expr); |
| | | try { |
| | | valueAsInt = Integer.parseInt(expr); |
| | | } catch (NumberFormatException nfe) { |
| | | Message message = |
| | | WARN_ACI_SYNTAX_INVALID_TIMEOFDAY_FORMAT.get(expr, nfe.getMessage()); |
| | | throw new AciException(message); |
| | | } |
| | | if ((valueAsInt < 0) || (valueAsInt > 2359)) |
| | | { |
| | | Message message = WARN_ACI_SYNTAX_INVALID_TIMEOFDAY_RANGE.get(expr); |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Always returns 0, there is no cipher used. |
| | | * @return Returns 0 always. |
| | | */ |
| | | public int getSSF() { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | |
| | | private String serverFQDN; |
| | | |
| | | //The SASL mechanism name. |
| | | private final String mech; |
| | | private final String mechanism; |
| | | |
| | | //The authorization entry used in the authentication. |
| | | private Entry authEntry=null; |
| | |
| | | * @param saslProps The properties to use in creating the SASL server. |
| | | * @param serverFQDN The fully qualified domain name to use in creating the |
| | | * SASL server. |
| | | * @param mech The SASL mechanism name. |
| | | * @param mechanism The SASL mechanism name. |
| | | * @param identityMapper The identity mapper to use in mapping identities. |
| | | * |
| | | * @throws SaslException If the SASL server can not be instantiated. |
| | | */ |
| | | private SASLContext(HashMap<String, String>saslProps, String serverFQDN, |
| | | String mech, IdentityMapper<?> identityMapper) |
| | | String mechanism, IdentityMapper<?> identityMapper) |
| | | throws SaslException { |
| | | this.identityMapper = identityMapper; |
| | | this.mech = mech; |
| | | this.mechanism = mechanism; |
| | | this.saslProps = saslProps; |
| | | this.serverFQDN = serverFQDN; |
| | | if(mech.equals(SASL_MECHANISM_DIGEST_MD5)) { |
| | | if(mechanism.equals(SASL_MECHANISM_DIGEST_MD5)) { |
| | | initSASLServer(); |
| | | } |
| | | } |
| | |
| | | * @param saslProps The properties to use in creating the SASL server. |
| | | * @param serverFQDN The fully qualified domain name to use in creating the |
| | | * SASL server. |
| | | * @param mech The SASL mechanism name. |
| | | * @param mechanism The SASL mechanism name. |
| | | * @param identityMapper The identity mapper to use in mapping identities. |
| | | * @return A fully instantiated SASL context to use in processing a SASL |
| | | * bind for the GSSAPI or DIGEST-MD5 mechanisms. |
| | |
| | | */ |
| | | public static |
| | | SASLContext createSASLContext(HashMap<String,String>saslProps, |
| | | String serverFQDN, String mech, |
| | | String serverFQDN, String mechanism, |
| | | IdentityMapper<?> identityMapper) throws SaslException { |
| | | return (new SASLContext(saslProps,serverFQDN, mech, identityMapper)); |
| | | return (new SASLContext(saslProps,serverFQDN, mechanism, identityMapper)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initialize the SASL server using parameters specified in the |
| | | * constructor. |
| | | * |
| | | * @throws SaslException If the SASL server can not be instantiated. |
| | | */ |
| | | private void initSASLServer() throws SaslException { |
| | | this.saslServer = Sasl.createSaslServer(mech, SASL_DEFAULT_PROTOCOL, |
| | | serverFQDN, saslProps, this); |
| | | this.saslServer = Sasl.createSaslServer(mechanism, SASL_DEFAULT_PROTOCOL, |
| | | serverFQDN, saslProps, this); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Unwrap the specified byte array using the provided offset and length |
| | | * values. Used only when the SASL server has negotiated |
| | | * confidentiality/integrity processing. |
| | | * confidentiality or integrity processing. |
| | | * |
| | | * @param bytes The byte array to unwrap. |
| | | * @param offset The offset in the array. |
| | |
| | | return Integer.parseInt(sizeStr); |
| | | } |
| | | |
| | | /** |
| | | * Return the Security Strength Factor of the cipher if the QOP property |
| | | * is confidentiality, or, 1 if it is integrity. |
| | | * |
| | | * @return The SSF of the cipher used during confidentiality or |
| | | * integrity processing. |
| | | */ |
| | | int getSSF() { |
| | | int ssf = 0; |
| | | String qop = (String) saslServer.getNegotiatedProperty(Sasl.QOP); |
| | | if(qop.equalsIgnoreCase(integrity)) { |
| | | ssf = 1; |
| | | } else { |
| | | String negStrength = |
| | | (String) saslServer.getNegotiatedProperty(Sasl.STRENGTH); |
| | | if(negStrength.equalsIgnoreCase("low")) |
| | | ssf = 40; |
| | | else if (negStrength.equalsIgnoreCase("medium")) |
| | | ssf = 56; |
| | | else |
| | | ssf = 128; |
| | | } |
| | | return ssf; |
| | | } |
| | | |
| | | /** |
| | | * Return true if the bind has been completed. If the context is supporting |
| | | * confidentiality/integrity, the security provider will need to check |
| | | * if the context has completed its handshakes with the client and is |
| | | * ready to process confidentiality/integrity messages. |
| | | * Return {@code true} if the bind has been completed. If the context is |
| | | * supporting confidentiality or integrity, the security provider will need |
| | | * to check if the context has completed the handshake with the client |
| | | * and is ready to process confidentiality or integrity messages. |
| | | * |
| | | * @return {@code true} if the handshaking is complete, |
| | | * {@code false} if further handshaking is needed. |
| | | * @return {@code true} if the handshaking is complete. |
| | | */ |
| | | boolean isBindComplete() { |
| | | return saslServer.isComplete(); |
| | |
| | | |
| | | /** |
| | | * Return true if the SASL server has negotiated with the client to support |
| | | * confidentiality/integrity. |
| | | * confidentiality or integrity. |
| | | * |
| | | * @return {@code true} if the context support |
| | | * confidentiality/integrity, or, {@code false} otherwise. |
| | | * @return {@code true} if the context supports confidentiality or |
| | | * integrity. |
| | | */ |
| | | private boolean isConfidentialIntegrity() { |
| | | boolean ret = false; |
| | |
| | | * |
| | | * @param authInfo The authentication information to use in the check. |
| | | * @return {@code true} if the authentication information has |
| | | * PROXIED_AUTH privileges, {@code false} otherwise. |
| | | * PROXIED_AUTH privileges. |
| | | */ |
| | | private boolean |
| | | hasPrivilege(AuthenticationInfo authInfo) { |
| | |
| | | * |
| | | * @param authInfo The authentication information to check access on. |
| | | * @return {@code true} if the authentication information has |
| | | * proxy access, {@code false} otherwise. |
| | | * proxy access. |
| | | */ |
| | | private boolean |
| | | hasPermission(AuthenticationInfo authInfo) { |
| | |
| | | authorizeCallback((AuthorizeCallback) callback); |
| | | } else { |
| | | Message message = |
| | | INFO_SASL_UNSUPPORTED_CALLBACK.get(mech, |
| | | INFO_SASL_UNSUPPORTED_CALLBACK.get(mechanism, |
| | | String.valueOf(callback)); |
| | | throw new UnsupportedCallbackException(callback, |
| | | message.toString()); |
| | |
| | | clearPasswords = pwPolicyState.getClearPasswords(); |
| | | if ((clearPasswords == null) || clearPasswords.isEmpty()) { |
| | | setCallbackMsg( |
| | | ERR_SASL_NO_REVERSIBLE_PASSWORDS.get(mech, |
| | | ERR_SASL_NO_REVERSIBLE_PASSWORDS.get(mechanism, |
| | | String.valueOf(authEntry.getDN()))); |
| | | return; |
| | | } |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | setCallbackMsg(ERR_SASL_CANNOT_GET_REVERSIBLE_PASSWORDS.get( |
| | | String.valueOf(authEntry.getDN()),mech, |
| | | String.valueOf(authEntry.getDN()),mechanism, |
| | | String.valueOf(e))); |
| | | return; |
| | | } |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | setCallbackMsg(ERR_SASL_CANNOT_DECODE_USERNAME_AS_DN.get( |
| | | mech, |
| | | mechanism, |
| | | userName, e.getMessageObject())); |
| | | return; |
| | | } |
| | | if (userDN.isNullDN()) { |
| | | setCallbackMsg(ERR_SASL_USERNAME_IS_NULL_DN.get( |
| | | mech)); |
| | | mechanism)); |
| | | return; |
| | | } |
| | | DN rootDN = DirectoryServer.getActualRootBindDN(userDN); |
| | |
| | | if (lowerUserName.startsWith("u:")) { |
| | | if (lowerUserName.equals("u:")) { |
| | | setCallbackMsg(ERR_SASL_ZERO_LENGTH_USERNAME.get( |
| | | mech,mech)); |
| | | mechanism,mechanism)); |
| | | return; |
| | | } |
| | | entryID = userName.substring(2); |
| | |
| | | * The method performs all GSSAPI processing. It is run as the context of |
| | | * the login context performed by the GSSAPI mechanism handler. See comments |
| | | * for processing overview. |
| | | * @return {@code true} if the authentication processing was successful, |
| | | * or, {@code false} otherwise. |
| | | * @return {@code true} if the authentication processing was successful. |
| | | */ |
| | | public Boolean run() { |
| | | ClientConnection clientConn = bindOp.getClientConnection(); |
| | |
| | | bindOp.setSASLAuthUserEntry(authEntry); |
| | | AuthenticationInfo authInfo = |
| | | new AuthenticationInfo(authEntry, authzEntry, |
| | | mech, |
| | | mechanism, |
| | | DirectoryServer.isRootDN(authEntry.getDN())); |
| | | bindOp.setAuthenticationInfo(authInfo); |
| | | //If confidentiality/integrity has been negotiated then |
| | |
| | | //negotiated, dispose of the SASL server. |
| | | if(isConfidentialIntegrity()) { |
| | | SASLSecurityProvider secProvider = |
| | | new SASLSecurityProvider(clientConn, mech, this); |
| | | new SASLSecurityProvider(clientConn, mechanism, this); |
| | | LDAPClientConnection ldapConn = |
| | | (LDAPClientConnection) clientConn; |
| | | ldapConn.setSASLConnectionSecurityProvider(secProvider); |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | Message msg = |
| | | ERR_SASL_PROTOCOL_ERROR.get(mech, getExceptionMessage(e)); |
| | | ERR_SASL_PROTOCOL_ERROR.get(mechanism, getExceptionMessage(e)); |
| | | handleError(msg); |
| | | return false; |
| | | } |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | Message msg = |
| | | ERR_SASL_PROTOCOL_ERROR.get(mech, getExceptionMessage(e)); |
| | | ERR_SASL_PROTOCOL_ERROR.get(mechanism, getExceptionMessage(e)); |
| | | handleError(msg); |
| | | } |
| | | } |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | Message msg = |
| | | ERR_SASL_PROTOCOL_ERROR.get(mech,getExceptionMessage(e)); |
| | | ERR_SASL_PROTOCOL_ERROR.get(mechanism,getExceptionMessage(e)); |
| | | handleError(msg); |
| | | } |
| | | } |
| | |
| | | if ((clientCredentials == null) || |
| | | (clientCredentials.value().length == 0)) { |
| | | Message msg = |
| | | ERR_SASL_NO_CREDENTIALS.get(mech, mech); |
| | | ERR_SASL_NO_CREDENTIALS.get(mechanism, mechanism); |
| | | handleError(msg); |
| | | return; |
| | | } |
| | |
| | | bindOp.setSASLAuthUserEntry(authEntry); |
| | | AuthenticationInfo authInfo = |
| | | new AuthenticationInfo(authEntry, authzEntry, |
| | | mech, |
| | | mechanism, |
| | | DirectoryServer.isRootDN(authEntry.getDN())); |
| | | bindOp.setAuthenticationInfo(authInfo); |
| | | //If confidentiality/integrity has been negotiated, then create a |
| | |
| | | //use in later processing. |
| | | if(isConfidentialIntegrity()) { |
| | | SASLSecurityProvider secProvider = |
| | | new SASLSecurityProvider(clientConn, mech, this); |
| | | new SASLSecurityProvider(clientConn, mechanism, this); |
| | | LDAPClientConnection ldapConn = |
| | | (LDAPClientConnection) clientConn; |
| | | ldapConn.setSASLConnectionSecurityProvider(secProvider); |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | Message msg = |
| | | ERR_SASL_PROTOCOL_ERROR.get(mech, getExceptionMessage(e)); |
| | | ERR_SASL_PROTOCOL_ERROR.get(mechanism, getExceptionMessage(e)); |
| | | handleError(msg); |
| | | } |
| | | } |
| | |
| | | public boolean isActive() { |
| | | return saslContext.isBindComplete(); |
| | | } |
| | | |
| | | /** |
| | | * Return the cipher Security Strength Function of the cipher used in the |
| | | * SSAL context. |
| | | * |
| | | * @return The cipher SSF of the cipher used in the SASL context. |
| | | */ |
| | | public int getSSF() { |
| | | return saslContext.getSSF(); |
| | | } |
| | | } |
| | |
| | | import java.nio.ByteBuffer; |
| | | import java.nio.channels.SocketChannel; |
| | | import java.security.cert.Certificate; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.SSLEngine; |
| | | import javax.net.ssl.SSLEngineResult; |
| | |
| | | */ |
| | | private static final DebugTracer TRACER = getTracer(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * The SSL context name that should be used for this TLS connection security |
| | | * provider. |
| | | */ |
| | | private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS"; |
| | | |
| | | |
| | | |
| | | // The buffer that will be used when reading clear-text data. |
| | | private ByteBuffer clearInBuffer; |
| | | |
| | |
| | | // The set of protocols to allow. |
| | | private String[] enabledProtocols; |
| | | |
| | | //Map of cipher phrases to effective key size (bits). Taken from the |
| | | //following RFCs: 5289, 4346, 3268,4132 and 4162. |
| | | private static final Map<String, Integer> cipherMap; |
| | | |
| | | static { |
| | | cipherMap = new LinkedHashMap<String, Integer>(); |
| | | cipherMap.put("_WITH_AES_256_CBC_", new Integer(256)); |
| | | cipherMap.put("_WITH_CAMELLIA_256_CBC_", new Integer(256)); |
| | | cipherMap.put("_WITH_AES_256_GCM_", new Integer(256)); |
| | | cipherMap.put("_WITH_3DES_EDE_CBC_", new Integer(168)); |
| | | cipherMap.put("_WITH_AES_128_GCM_", new Integer(128)); |
| | | cipherMap.put("_WITH_SEED_CBC_", new Integer(128)); |
| | | cipherMap.put("_WITH_CAMELLIA_128_CBC_", new Integer(128)); |
| | | cipherMap.put("_WITH_AES_128_CBC_", new Integer(128)); |
| | | cipherMap.put("_WITH_IDEA_CBC_", new Integer(128)); |
| | | cipherMap.put("_WITH_DES_CBC_", new Integer(56)); |
| | | cipherMap.put("_WITH_RC2_CBC_40_", new Integer(40)); |
| | | cipherMap.put("_WITH_RC4_40_", new Integer(40)); |
| | | cipherMap.put("_WITH_DES40_CBC_", new Integer(40)); |
| | | cipherMap.put("_WITH_NULL_", new Integer(0)); |
| | | }; |
| | | |
| | | |
| | | /** |
| | |
| | | |
| | | // Create an SSL session based on the configured key and trust stores in the |
| | | // Directory Server. |
| | | KeyManagerProvider keyManagerProvider = |
| | | KeyManagerProvider<?> keyManagerProvider = |
| | | DirectoryServer.getKeyManagerProvider( |
| | | clientConnection.getKeyManagerProviderDN()); |
| | | if (keyManagerProvider == null) |
| | |
| | | keyManagerProvider = new NullKeyManagerProvider(); |
| | | } |
| | | |
| | | TrustManagerProvider trustManagerProvider = |
| | | TrustManagerProvider<?> trustManagerProvider = |
| | | DirectoryServer.getTrustManagerProvider( |
| | | clientConnection.getTrustManagerProviderDN()); |
| | | if (trustManagerProvider == null) |
| | |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return the Security Strength FActor of the cipher used in the current |
| | | * TLS session. |
| | | * |
| | | * @return The cipher SSF used in the current TLS session. |
| | | */ |
| | | |
| | | public int getSSF() { |
| | | int cipherKeySSF = 0; |
| | | String cipherString = sslEngine.getSession().getCipherSuite(); |
| | | for(Map.Entry<String, Integer> mapEntry : cipherMap.entrySet()) { |
| | | if(cipherString.indexOf(mapEntry.getKey()) >= 0) { |
| | | cipherKeySSF = mapEntry.getValue().intValue(); |
| | | break; |
| | | } |
| | | } |
| | | return cipherKeySSF; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.ldap.LDAPResultCode; |
| | | import org.opends.server.tools.LDAPModify; |
| | | import org.opends.server.tools.LDAPSearch; |
| | | import org.opends.server.tools.LDAPDelete; |
| | |
| | | import org.testng.Assert; |
| | | |
| | | import java.io.*; |
| | | import java.util.Hashtable; |
| | | import java.util.Map; |
| | | import java.util.HashMap; |
| | | import java.util.ArrayList; |
| | | |
| | | import javax.naming.Context; |
| | | import javax.naming.NamingException; |
| | | import javax.naming.NoPermissionException; |
| | | import javax.naming.directory.AttributeModificationException; |
| | | import javax.naming.directory.BasicAttribute; |
| | | import javax.naming.directory.DirContext; |
| | | import javax.naming.directory.InitialDirContext; |
| | | import javax.naming.directory.ModificationItem; |
| | | import javax.naming.ldap.InitialLdapContext; |
| | | import javax.naming.ldap.LdapContext; |
| | | import javax.naming.ldap.StartTlsRequest; |
| | | import javax.naming.ldap.StartTlsResponse; |
| | | |
| | | |
| | | @Test(groups = {"precommit", "dseecompat"}, sequential = true) |
| | | public abstract class AciTestCase extends DirectoryServerTestCase { |
| | |
| | | ldapModify(argList.toArray(args), rc); |
| | | } |
| | | |
| | | protected void JNDIModify(Hashtable<?, ?> env, String name, |
| | | String attr, String val, int rc) { |
| | | try { |
| | | DirContext ctx = new InitialDirContext(env); |
| | | ModificationItem[] mods = new ModificationItem[1 ]; |
| | | mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, |
| | | new BasicAttribute(attr, val)); |
| | | ctx.modifyAttributes(name, mods); |
| | | ctx.close(); |
| | | } catch (NoPermissionException npe) { |
| | | Assert.assertEquals(LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, rc, |
| | | "Returned error: " + npe.getMessage()); |
| | | return; |
| | | } catch (NamingException ex) { |
| | | Assert.assertEquals(-1, rc, "Returned error: " + ex.getMessage()); |
| | | } |
| | | Assert.assertEquals(LDAPResultCode.SUCCESS, rc, ""); |
| | | } |
| | | |
| | | private void ldapModify(String[] args, int rc) { |
| | | oStream.reset(); |
| | | int retVal =LDAPModify.mainModify(args, false, oStream, oStream); |
| | |
| | | } |
| | | return attrMap; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | /** |
| | | * Unit test to test the ssf ACI bind rule keyword. |
| | | */ |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import java.util.Hashtable; |
| | | |
| | | import javax.naming.Context; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.protocols.ldap.LDAPResultCode; |
| | | import org.testng.annotations.*; |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | |
| | | public class SSFTestCase extends AciTestCase { |
| | | |
| | | private static final String newUser="uid=new.user,ou=People,o=test"; |
| | | private static final String descriptionStr = "description of user.1"; |
| | | private static final String factory = "com.sun.jndi.ldap.LdapCtxFactory"; |
| | | private static final String pwdPolicy = "Aci Temp Policy"; |
| | | private static final String pwdPolicyDN = |
| | | "cn=" + pwdPolicy + ",cn=Password Policies,cn=config"; |
| | | |
| | | private static final String[] newEntry = new String[] { |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: new.user", |
| | | "givenName: New", |
| | | "sn: User", |
| | | "cn: New User", |
| | | "mail: new.user@test.com", |
| | | "ds-pwp-password-policy-dn:" + pwdPolicyDN |
| | | }; |
| | | |
| | | private static final |
| | | String integrityACI = "(targetattr=\"" + "*" + "\")" + |
| | | "(version 3.0; acl \"integrity aci\";" + |
| | | "allow(all) (userdn=\"ldap:///self\" and ssf = \"1\");)"; |
| | | |
| | | private static final |
| | | String greaterIntegrityACI = "(targetattr=\"" + "*" + "\")" + |
| | | "(version 3.0; acl \"greater integrity aci\";" + |
| | | "allow(all) (userdn=\"ldap:///self\" and ssf > \"1\");)"; |
| | | |
| | | |
| | | private static final |
| | | String medStrengthACI = "(targetattr=\"" + "*" + "\")" + |
| | | "(version 3.0; acl \"56 bit key aci\";" + |
| | | "allow(all) (userdn=\"ldap:///self\" and ssf = \"56\");)"; |
| | | |
| | | |
| | | private static final |
| | | String hiStrengthACI = "(targetattr=\"" + "*" + "\")" + |
| | | "(version 3.0; acl \"128 bit key aci\";" + |
| | | "allow(all) (userdn=\"ldap:///self\" and ssf = \"128\");)"; |
| | | |
| | | |
| | | private static final |
| | | String hiPlusStrengthACI = "(targetattr=\"" + "*" + "\")" + |
| | | "(version 3.0; acl \"greater 128 bit aci\";" + |
| | | "allow(all) (userdn=\"ldap:///self\" and ssf > \"128\");)"; |
| | | |
| | | |
| | | @BeforeClass |
| | | public void setupClass() throws Exception { |
| | | TestCaseUtils.startServer(); |
| | | TestCaseUtils.dsconfig( |
| | | "create-password-policy", |
| | | "--policy-name", pwdPolicy, |
| | | "--set", "password-attribute:userPassword", |
| | | "--set", "default-password-storage-scheme: Clear" |
| | | ); |
| | | TestCaseUtils.dsconfig( |
| | | "set-sasl-mechanism-handler-prop", |
| | | "--handler-name", "DIGEST-MD5", |
| | | "--set", "server-fqdn:localhost"); |
| | | deleteAttrFromAdminEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI); |
| | | String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN, |
| | | G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL, E_EXTEND_OP); |
| | | LDIFAdminModify(aciLdif, DIR_MGR_DN, PWD); |
| | | addEntries("o=test"); |
| | | String newUserLDIF=makeAddEntryLDIF(newUser, newEntry); |
| | | LDIFAdd(newUserLDIF, DIR_MGR_DN, PWD, null, LDAPResultCode.SUCCESS); |
| | | String pwdILDIF = |
| | | makeAddLDIF("userpassword", newUser, "password"); |
| | | LDIFModify(pwdILDIF, DIR_MGR_DN, PWD); |
| | | } |
| | | |
| | | @AfterClass(alwaysRun = true) |
| | | public void tearDown() throws Exception { |
| | | String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN, |
| | | G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL, |
| | | E_EXTEND_OP); |
| | | LDIFAdminModify(aciLdif, DIR_MGR_DN, PWD); |
| | | TestCaseUtils.dsconfig( |
| | | "delete-password-policy", |
| | | "--policy-name", pwdPolicy |
| | | ); |
| | | TestCaseUtils.dsconfig( |
| | | "set-sasl-mechanism-handler-prop", |
| | | "--handler-name", "DIGEST-MD5", |
| | | "--reset", "server-fqdn", |
| | | "--reset", "quality-of-protection"); |
| | | |
| | | } |
| | | |
| | | //Valid ssf statements. Not the complete ACI. |
| | | @DataProvider(name = "validStatements") |
| | | public Object[][] valids() { |
| | | return new Object[][] { |
| | | {"1"}, |
| | | {"40"}, |
| | | {"56"}, |
| | | {"128"}, |
| | | {"256"}, |
| | | {"129"}, |
| | | }; |
| | | } |
| | | |
| | | //Invalid ssf statements. Not the complete ACI. |
| | | @DataProvider(name = "invalidStatements") |
| | | public Object[][] invalids() { |
| | | return new Object[][] { |
| | | {"-1"}, |
| | | {"0"}, |
| | | {"not valid"}, |
| | | {"1025"}, |
| | | {"10000"}, |
| | | }; |
| | | } |
| | | |
| | | private EnumBindRuleType bindRuleType = EnumBindRuleType.EQUAL_BINDRULE_TYPE; |
| | | |
| | | /** |
| | | * Test valid ssf statements. |
| | | * |
| | | * @param statement The ssf statement to attempt to decode. |
| | | * @throws AciException If an unexpected result happens. |
| | | */ |
| | | @Test(dataProvider = "validStatements") |
| | | public void testValidStatements(String statement) throws AciException { |
| | | SSF.decode(statement, bindRuleType); |
| | | } |
| | | |
| | | /** |
| | | * Test invalid ssf statements. |
| | | * |
| | | * @param statement The ssf statement to attempt to decode. |
| | | * @throws Exception If an unexpected result happens. |
| | | */ |
| | | @Test(expectedExceptions= AciException.class, |
| | | dataProvider="invalidStatements") |
| | | public void testInvalidStatements(String statement) throws Exception { |
| | | try { |
| | | SSF.decode(statement, bindRuleType); |
| | | } catch (AciException e) { |
| | | throw e; |
| | | } catch (Exception e) { |
| | | System.out.println( |
| | | "Invalid ssf <" + statement + |
| | | "> threw wrong exception type."); |
| | | throw e; |
| | | } |
| | | throw new RuntimeException( |
| | | "Invalid ssf <" + statement + |
| | | "> did not throw an exception."); |
| | | } |
| | | |
| | | /** |
| | | * Test ssf bind rule using ssf value for integrity. |
| | | * |
| | | * @throws Exception If a test doesn't pass. |
| | | */ |
| | | @Test() |
| | | public void testIntegrity() throws Exception { |
| | | //set QOP to integrity. |
| | | TestCaseUtils.dsconfig( |
| | | "set-sasl-mechanism-handler-prop", |
| | | "--handler-name", "DIGEST-MD5", |
| | | "--set", "quality-of-protection:" + "integrity"); |
| | | |
| | | //Configure JNDI props. |
| | | Hashtable<String, String> env = new Hashtable<String, String>(); |
| | | env.put(Context.INITIAL_CONTEXT_FACTORY, factory); |
| | | int port = TestCaseUtils.getServerLdapPort(); |
| | | String url = "ldap://localhost:" + Integer.valueOf(port); |
| | | env.put(Context.PROVIDER_URL, url); |
| | | env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5"); |
| | | String principal = "dn:" + newUser; |
| | | env.put(Context.SECURITY_PRINCIPAL, principal); |
| | | env.put(Context.SECURITY_CREDENTIALS, "password"); |
| | | //Select integrity QOP. |
| | | env.put("javax.security.sasl.qop", "auth-int"); |
| | | //Add ACI with ssf > 1, should fail. |
| | | String addACILDIF = makeAddLDIF("aci", newUser, greaterIntegrityACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | //Add ACI with ssf = 1. |
| | | addACILDIF = makeAddLDIF("aci", newUser, integrityACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | //Should succeed. |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.SUCCESS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | deleteAttrFromEntry(newUser, "description"); |
| | | } |
| | | |
| | | /** |
| | | * Test confidentiality settings using DIGEST-MD5. |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public void testConfidentiality() throws Exception { |
| | | //set QOP to integrity. |
| | | TestCaseUtils.dsconfig( |
| | | "set-sasl-mechanism-handler-prop", |
| | | "--handler-name", "DIGEST-MD5", |
| | | "--set", "quality-of-protection:" + "confidentiality"); |
| | | Hashtable<String, String> env = new Hashtable<String, String>(); |
| | | env.put(Context.INITIAL_CONTEXT_FACTORY, factory); |
| | | int port = TestCaseUtils.getServerLdapPort(); |
| | | String url = "ldap://localhost:" + Integer.valueOf(port); |
| | | env.put(Context.PROVIDER_URL, url); |
| | | env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5"); |
| | | String principal = "dn:" + newUser; |
| | | env.put(Context.SECURITY_PRINCIPAL, principal); |
| | | env.put(Context.SECURITY_CREDENTIALS, "password"); |
| | | //Select integrity QOP. |
| | | env.put("javax.security.sasl.qop", "auth-conf"); |
| | | //Add ACI with ssf > 1, should succeed. |
| | | String addACILDIF = makeAddLDIF("aci", newUser, greaterIntegrityACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.SUCCESS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | deleteAttrFromEntry(newUser, "description"); |
| | | //Test medium strength. |
| | | addACILDIF = makeAddLDIF("aci", newUser, medStrengthACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | env.put("javax.security.sasl.strength", "medium"); |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.SUCCESS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | deleteAttrFromEntry(newUser, "description"); |
| | | //Test high strength. |
| | | addACILDIF = makeAddLDIF("aci", newUser, hiStrengthACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | env.put("javax.security.sasl.strength", "high"); |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.SUCCESS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | deleteAttrFromEntry(newUser, "description"); |
| | | //Fail DIGEST-MD5 only goes to 128. |
| | | addACILDIF = makeAddLDIF("aci", newUser, hiPlusStrengthACI); |
| | | LDIFModify(addACILDIF, DIR_MGR_DN, PWD); |
| | | env.put("javax.security.sasl.strength", "high"); |
| | | JNDIModify(env, newUser, "description", descriptionStr, |
| | | LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS); |
| | | deleteAttrFromEntry(newUser, "aci"); |
| | | deleteAttrFromEntry(newUser, "description"); |
| | | } |
| | | } |