CR-1602 (OPENDJ-883) Implement certificateExactMatch matching rule
7 files added
11 files modified
| | |
| | | # |
| | | # Copyright 2006-2010 Sun Microsystems, Inc. |
| | | # Portions Copyright 2010-2013 ForgeRock AS. |
| | | # Portions Copyright 2012-2013 Manuel Gaupp |
| | | # Portions Copyright 2012-2014 Manuel Gaupp |
| | | # |
| | | # |
| | | # This file contains the primary Directory Server configuration. It must not |
| | |
| | | ds-cfg-java-class: org.opends.server.schema.CaseIgnoreListSubstringMatchingRuleFactory |
| | | ds-cfg-enabled: true |
| | | |
| | | dn: cn=Certificate Exact Matching Rule,cn=Matching Rules,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-matching-rule |
| | | objectClass: ds-cfg-equality-matching-rule |
| | | cn: Certificate Exact Matching Rule |
| | | ds-cfg-java-class: org.opends.server.schema.CertificateExactMatchingRuleFactory |
| | | ds-cfg-enabled: true |
| | | |
| | | dn: cn=Collation Matching Rule,cn=Matching Rules,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-matching-rule |
| | |
| | | # |
| | | # Copyright 2006-2010 Sun Microsystems, Inc. |
| | | # Portions Copyright 2011-2012 ForgeRock AS |
| | | # Portions Copyright 2013 Manuel Gaupp |
| | | # Portions Copyright 2013-2014 Manuel Gaupp |
| | | # |
| | | # |
| | | # This file contains a core set of attribute type and objectlass definitions |
| | |
| | | attributeTypes: ( 2.5.4.35 NAME 'userPassword' |
| | | SYNTAX 1.3.6.1.4.1.26027.1.3.1 X-ORIGIN 'RFC 4519' ) |
| | | attributeTypes: ( 2.5.4.36 NAME 'userCertificate' |
| | | EQUALITY certificateExactMatch |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 X-ORIGIN 'RFC 4523' ) |
| | | attributeTypes: ( 2.5.4.37 NAME 'cACertificate' |
| | | EQUALITY certificateExactMatch |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 X-ORIGIN 'RFC 4523' ) |
| | | attributeTypes: ( 2.5.4.38 NAME 'authorityRevocationList' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 X-ORIGIN 'RFC 4523' ) |
| | |
| | | # |
| | | # Copyright 2006-2009 Sun Microsystems, Inc. |
| | | # Portions copyright 2013 ForgeRock AS |
| | | # Portions copyright 2013-2014 Manuel Gaupp |
| | | |
| | | |
| | | |
| | |
| | | MILD_ERR_CONNHANDLER_CONFIG_CHANGES_REQUIRE_RESTART_1516=The server received \ |
| | | configuration changes that require a restart of the %s connection handler \ |
| | | to take effect |
| | | MILD_ERR_GSER_PATTERN_NO_MATCH_1517=The GSER value does not contain a \ |
| | | String matching the pattern %s at the current position: %s |
| | | MILD_ERR_GSER_NO_VALID_SEPARATOR_1518=The GSER value does not contain a \ |
| | | separator at the current position: %s |
| | | MILD_ERR_GSER_NO_VALID_STRING_1519=The GSER value does not contain a valid \ |
| | | String value at the current position: %s |
| | | MILD_ERR_GSER_NO_VALID_INTEGER_1520=The GSER value does not contain a valid \ |
| | | integer value at the current position: %s |
| | | MILD_ERR_GSER_NO_VALID_IDENTIFIER_1521=The GSER value does not contain a \ |
| | | valid identifier at the current position: %s |
| | | MILD_ERR_GSER_SPACE_CHAR_EXPECTED_1522=The GSER value does not contain a \ |
| | | whitespace character at the current position: %s |
| | | MILD_ERR_GSER_NO_VALID_IDENTIFIEDCHOICE_1523=The GSER value does not \ |
| | | contain a valid IdentifiedChoiceValue at the current position: %s |
| | |
| | | # |
| | | # Copyright 2006-2010 Sun Microsystems, Inc. |
| | | # Portions Copyright 2011 ForgeRock AS |
| | | # Portions Copyright 2012 Manuel Gaupp |
| | | # Portions Copyright 2012-2014 Manuel Gaupp |
| | | |
| | | |
| | | # |
| | |
| | | is not a valid ISO 3166 country code |
| | | SEVERE_ERR_ATTR_SYNTAX_ILLEGAL_X_SCHEMA_FILE_334=The provided value "%s" is \ |
| | | not safe for X-SCHEMA-FILE |
| | | SEVERE_WARN_CERTIFICATE_MATCH_PARSE_ERROR_335=The value could not be parsed as \ |
| | | an X.509 certificate: "%s" |
| | | MILD_ERR_CERTIFICATE_MATCH_INVALID_DN_336=The provided value "%s" could \ |
| | | not be parsed as a valid distinguished name because an error occurred while \ |
| | | trying to parse the DN portion: %s |
| | | MILD_ERR_CERTIFICATE_MATCH_IDENTIFIER_NOT_FOUND_337=The identifier "%s" could \ |
| | | not be found at the correct position |
| | | MILD_ERR_CERTIFICATE_MATCH_EXPECTED_END_338=The GSER value contains additional \ |
| | | characters at the end of the assertion |
| | | MILD_ERR_CERTIFICATE_MATCH_GSER_INVALID_339=An error occured while parsing the \ |
| | | the GSER String: "%s" |
| | |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | * Portions Copyright 2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | import org.opends.messages.Message; |
| | |
| | | try |
| | | { |
| | | // Make a key from the normalized assertion value. |
| | | byte[] keyBytes = |
| | | equalityFilter.getAssertionValue().getNormalizedValue().toByteArray(); |
| | | EqualityMatchingRule equalityRule = equalityFilter.getAttributeType(). |
| | | getEqualityMatchingRule(); |
| | | byte[] keyBytes = equalityRule.normalizeAssertionValue(equalityFilter. |
| | | getAssertionValue().getValue()).toByteArray(); |
| | | DatabaseEntry key = new DatabaseEntry(keyBytes); |
| | | |
| | | if(debugBuffer != null) |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.controls; |
| | | import org.opends.messages.Message; |
| | |
| | | { |
| | | case EQUALITY_MATCH_TYPE: |
| | | if ((attributeType != null) && (type != null) && |
| | | attributeType.equals(type) && (assertionValue != null) && |
| | | attributeType.equals(type) && (rawAssertionValue != null) && |
| | | (value != null) && (equalityMatchingRule != null)) |
| | | { |
| | | try |
| | | { |
| | | return equalityMatchingRule.areEqual( |
| | | assertionValue.getNormalizedValue(), |
| | | equalityMatchingRule.normalizeAssertionValue(rawAssertionValue), |
| | | value.getNormalizedValue()); |
| | | } |
| | | catch (Exception e) |
| | |
| | | try |
| | | { |
| | | return equalityMatchingRule.areEqual( |
| | | assertionValue.getNormalizedValue(), |
| | | equalityMatchingRule.normalizeAssertionValue(rawAssertionValue), |
| | | value.getNormalizedValue()); |
| | | } |
| | | catch (Exception e) |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.protocols.asn1; |
| | | |
| | | |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.types.IdentifiedException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines an exception that may be thrown if a problem occurs while |
| | | * interacting with a GSER String. |
| | | */ |
| | | public final class GSERException |
| | | extends IdentifiedException |
| | | { |
| | | /** |
| | | * The serial version identifier required to satisfy the compiler because this |
| | | * class extends <CODE>java.lang.Exception</CODE>, which implements the |
| | | * <CODE>java.io.Serializable</CODE> interface. This value was generated |
| | | * using the <CODE>serialver</CODE> command-line utility included with the |
| | | * Java SDK. |
| | | */ |
| | | private static final long serialVersionUID = 3655637382448481369L; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new GSER exception with the provided message. |
| | | * |
| | | * @param message The message that explains the problem that occurred. |
| | | */ |
| | | public GSERException(Message message) |
| | | { |
| | | super(message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new GSER exception with the provided message and root |
| | | * cause. |
| | | * |
| | | * @param message The message that explains the problem that occurred. |
| | | * @param cause The exception that was caught to trigger this exception. |
| | | */ |
| | | public GSERException(Message message, Throwable cause) |
| | | { |
| | | super(message, cause); |
| | | } |
| | | } |
| | | |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.protocols.asn1; |
| | | |
| | | |
| | | |
| | | import java.math.BigInteger; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | import org.opends.messages.Message; |
| | | import static org.opends.messages.ProtocolMessages.*; |
| | | import static org.opends.server.util.Validator.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a parser for strings which are encoded using the |
| | | * Generic String Encoding Rules (GSER) defined in RFC 3641. |
| | | * |
| | | * @see <a href="http://tools.ietf.org/html/rfc3641">RFC 3641 - |
| | | * Generic String Encoding Rules (GSER) for ASN.1 Types |
| | | * </a> |
| | | */ |
| | | public class GSERParser |
| | | { |
| | | |
| | | private String gserValue; |
| | | |
| | | private int pos; |
| | | |
| | | private int length; |
| | | |
| | | /** |
| | | * Pattern to match an identifier defined in RFC 3641, section 3.4. |
| | | * <pre> |
| | | * An <identifier> conforms to the definition of an identifier in ASN.1 |
| | | * notation (Clause 11.3 of X.680 [8]). It begins with a lowercase |
| | | * letter and is followed by zero or more letters, digits, and hyphens. |
| | | * A hyphen is not permitted to be the last character, nor is it to be |
| | | * followed by another hyphen. The case of letters in an identifier is |
| | | * always significant. |
| | | * |
| | | * identifier = lowercase *alphanumeric *(hyphen 1*alphanumeric) |
| | | * alphanumeric = uppercase / lowercase / decimal-digit |
| | | * uppercase = %x41-5A ; "A" to "Z" |
| | | * lowercase = %x61-7A ; "a" to "z" |
| | | * decimal-digit = %x30-39 ; "0" to "9" |
| | | * hyphen = "-" |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_IDENTIFIER = Pattern |
| | | .compile("^([a-z]([A-Za-z0-9]|(-[A-Za-z0-9]))*)"); |
| | | |
| | | /** |
| | | * Pattern to match the identifier part (including the colon) of an |
| | | * IdentifiedChoiceValue defined in RFC 3641, section 3.12. |
| | | * <pre> |
| | | * IdentifiedChoiceValue = identifier ":" Value |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_CHOICE_IDENTIFIER = Pattern |
| | | .compile("^([a-z]([A-Za-z0-9]|(-[A-Za-z0-9]))*:)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match "sp", containing zero, one or more space characters. |
| | | * <pre> |
| | | * sp = *%x20 ; zero, one or more space characters |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_SP = Pattern.compile("^( *)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match "msp", containing at least one space character. |
| | | * <pre> |
| | | * msp = 1*%x20 ; one or more space characters |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_MSP = Pattern.compile("^( +)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match an Integer value. |
| | | */ |
| | | private static Pattern GSER_INTEGER = Pattern.compile("^(\\d+)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match a GSER StringValue, defined in RFC 3641, section 3.2: |
| | | * <pre> |
| | | * Any embedded double quotes in the resulting UTF-8 character string |
| | | * are escaped by repeating the double quote characters. |
| | | * |
| | | * [...] |
| | | * |
| | | * StringValue = dquote *SafeUTF8Character dquote |
| | | * dquote = %x22 ; " (double quote) |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_STRING = Pattern |
| | | .compile("^(\"([^\"]|(\"\"))*\")"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match the beginning of a GSER encoded Sequence. |
| | | * <pre> |
| | | * SequenceValue = ComponentList |
| | | * ComponentList = "{" [ sp NamedValue *( "," sp NamedValue) ] sp "}" |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_SEQUENCE_START = Pattern.compile("^(\\{)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match the end of a GSER encoded Sequence. |
| | | * <pre> |
| | | * SequenceValue = ComponentList |
| | | * ComponentList = "{" [ sp NamedValue *( "," sp NamedValue) ] sp "}" |
| | | * </pre> |
| | | */ |
| | | private static Pattern GSER_SEQUENCE_END = Pattern.compile("^(\\})"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Pattern to match the separator used in GSER encoded sequences. |
| | | */ |
| | | private static Pattern GSER_SEP = Pattern.compile("^(,)"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new GSER Parser. |
| | | * |
| | | * @param value the GSER encoded String value |
| | | */ |
| | | public GSERParser(String value) |
| | | { |
| | | ensureNotNull(value); |
| | | this.gserValue = value; |
| | | this.pos = 0; |
| | | this.length = value.length(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Determines if the GSER String contains at least one character to be read. |
| | | * |
| | | * @return <code>true</code> if there is at least one remaining character or |
| | | * <code>false</code> otherwise. |
| | | */ |
| | | public boolean hasNext() |
| | | { |
| | | return (pos < length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Determines if the remaining GSER String matches the provided pattern. |
| | | * |
| | | * @param pattern the pattern to search for |
| | | * |
| | | * @return <code>true</code> if the remaining string matches the pattern or |
| | | * <code>false</code> otherwise. |
| | | */ |
| | | private boolean hasNext(Pattern pattern) |
| | | { |
| | | if (!hasNext()) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | Matcher matcher = pattern.matcher(gserValue.substring(pos,length)); |
| | | |
| | | return matcher.find(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the String matched by the first capturing group of the pattern. |
| | | * The parser advances past the input matched by the first capturing group. |
| | | * |
| | | * @param pattern the pattern to search for |
| | | * |
| | | * @return the String matched by the first capturing group of the pattern |
| | | * |
| | | * @throws GSERException |
| | | * If no match could be found |
| | | */ |
| | | private String next(Pattern pattern) throws GSERException |
| | | { |
| | | Matcher matcher = pattern.matcher(gserValue.substring(pos,length)); |
| | | if (matcher.find() && matcher.groupCount() >= 1) |
| | | { |
| | | pos += matcher.end(1); |
| | | return matcher.group(1); |
| | | } |
| | | else |
| | | { |
| | | Message msg = ERR_GSER_PATTERN_NO_MATCH.get(pattern.pattern(), |
| | | gserValue.substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the input matched by the first capturing group. |
| | | * |
| | | * @param pattern the pattern to search for |
| | | * |
| | | * @throws GSERException |
| | | * If no match could be found |
| | | */ |
| | | private void skip(Pattern pattern) throws GSERException |
| | | { |
| | | Matcher matcher = pattern.matcher(gserValue.substring(pos,length)); |
| | | |
| | | if (matcher.find() && matcher.groupCount() >= 1) |
| | | { |
| | | pos += matcher.end(1); |
| | | } |
| | | else |
| | | { |
| | | Message msg = ERR_GSER_PATTERN_NO_MATCH.get(pattern.pattern(), |
| | | gserValue.substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the input matching zero, one or more space characters. |
| | | * |
| | | * @return reference to this GSERParser |
| | | * |
| | | * @throws GSERException |
| | | * If no match could be found |
| | | */ |
| | | public GSERParser skipSP() throws GSERException |
| | | { |
| | | skip(GSER_SP); |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the input matching one or more space characters. |
| | | * |
| | | * @return reference to this GSERParser |
| | | * |
| | | * @throws GSERException |
| | | * If no match could be found |
| | | */ |
| | | public GSERParser skipMSP() throws GSERException |
| | | { |
| | | skip(GSER_MSP); |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the input matching the start of a sequence and subsequent space |
| | | * characters. |
| | | * |
| | | * @return reference to this GSERParser |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the start of a sequence |
| | | */ |
| | | public GSERParser readStartSequence() throws GSERException |
| | | { |
| | | next(GSER_SEQUENCE_START); |
| | | skip(GSER_SP); |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the input matching the end of a sequence and preceding space |
| | | * characters. |
| | | * |
| | | * @return reference to this GSERParser |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the end of a sequence |
| | | */ |
| | | public GSERParser readEndSequence() throws GSERException |
| | | { |
| | | skip(GSER_SP); |
| | | next(GSER_SEQUENCE_END); |
| | | return this; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Skips the input matching the separator pattern (",") and subsequenct space |
| | | * characters. |
| | | * |
| | | * @return reference to this GSERParser |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the separator pattern. |
| | | */ |
| | | public GSERParser skipSeparator() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_SEP)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_SEPARATOR.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | skip(GSER_SEP); |
| | | skip(GSER_SP); |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the next element as a String. |
| | | * |
| | | * @return the input matching the String pattern |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the string pattern. |
| | | */ |
| | | public String nextString() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_STRING)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_STRING.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | |
| | | String str = next(GSER_STRING); |
| | | |
| | | // Strip leading and trailing dquotes; unescape double dquotes |
| | | return str.substring(1, str.length() - 1).replace("\"\"","\""); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the next element as an Integer. |
| | | * |
| | | * @return the input matching the integer pattern |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the integer pattern |
| | | */ |
| | | public int nextInteger() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_INTEGER)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_INTEGER.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | return Integer.valueOf(next(GSER_INTEGER)).intValue(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the next element as a BigInteger. |
| | | * |
| | | * @return the input matching the integer pattern |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the integer pattern |
| | | */ |
| | | public BigInteger nextBigInteger() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_INTEGER)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_INTEGER.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | return new BigInteger(next(GSER_INTEGER)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the identifier of the next NamedValue element. |
| | | * |
| | | * @return the identifier of the NamedValue element |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the identifier pattern of a |
| | | * NamedValue |
| | | */ |
| | | public String nextNamedValueIdentifier() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_IDENTIFIER)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_IDENTIFIER.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | String identifier = next(GSER_IDENTIFIER); |
| | | if (!hasNext(GSER_MSP)) |
| | | { |
| | | Message msg = ERR_GSER_SPACE_CHAR_EXPECTED.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | skipMSP(); |
| | | return identifier; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return the identifier of the next IdentifiedChoiceValue element. |
| | | * |
| | | * @return the identifier of the IdentifiedChoiceValue element |
| | | * |
| | | * @throws GSERException |
| | | * If the input does not match the identifier pattern of an |
| | | * IdentifiedChoiceValue |
| | | */ |
| | | public String nextChoiceValueIdentifier() throws GSERException |
| | | { |
| | | if (!hasNext(GSER_CHOICE_IDENTIFIER)) |
| | | { |
| | | Message msg = ERR_GSER_NO_VALID_IDENTIFIEDCHOICE.get(gserValue |
| | | .substring(pos,length)); |
| | | throw new GSERException(msg); |
| | | } |
| | | String identifier = next(GSER_CHOICE_IDENTIFIER); |
| | | |
| | | // Remove the colon at the end of the identifier |
| | | return identifier.substring(0, identifier.length() - 1); |
| | | } |
| | | |
| | | |
| | | } |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2012 ForgeRock AS |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.std.server.AttributeSyntaxCfg; |
| | | import org.opends.server.api.ApproximateMatchingRule; |
| | | import org.opends.server.api.AttributeSyntax; |
| | | import org.opends.server.api.EqualityMatchingRule; |
| | | import org.opends.server.api.OrderingMatchingRule; |
| | | import org.opends.server.api.SubstringMatchingRule; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteSequence; |
| | | |
| | | |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.messages.SchemaMessages.*; |
| | | import org.opends.messages.MessageBuilder; |
| | | import static org.opends.server.schema.SchemaConstants.*; |
| | | |
| | | |
| | | /** |
| | | * This class defines the Certificate Exact Assertion attribute syntax, |
| | | * which contains components for matching X.509 certificates. |
| | | */ |
| | | public class CertificateExactAssertionSyntax |
| | | extends AttributeSyntax<AttributeSyntaxCfg> |
| | | { |
| | | // The default equality matching rule for this syntax. |
| | | private EqualityMatchingRule defaultEqualityMatchingRule; |
| | | |
| | | // The default ordering matching rule for this syntax. |
| | | private OrderingMatchingRule defaultOrderingMatchingRule; |
| | | |
| | | // The default substring matching rule for this syntax. |
| | | private SubstringMatchingRule defaultSubstringMatchingRule; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this syntax. Note that the only thing that |
| | | * should be done here is to invoke the default constructor for the |
| | | * superclass. All initialization should be performed in the |
| | | * <CODE>initializeSyntax</CODE> method. |
| | | */ |
| | | public CertificateExactAssertionSyntax() |
| | | { |
| | | super(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeSyntax(AttributeSyntaxCfg configuration) |
| | | throws ConfigException |
| | | { |
| | | defaultEqualityMatchingRule = |
| | | DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_OID); |
| | | if (defaultEqualityMatchingRule == null) |
| | | { |
| | | logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get( |
| | | EMR_CASE_IGNORE_OID, SYNTAX_CERTIFICATE_EXACT_ASSERTION_NAME)); |
| | | } |
| | | |
| | | defaultOrderingMatchingRule = |
| | | DirectoryServer.getOrderingMatchingRule(OMR_CASE_IGNORE_OID); |
| | | if (defaultOrderingMatchingRule == null) |
| | | { |
| | | logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get( |
| | | OMR_CASE_IGNORE_OID, SYNTAX_CERTIFICATE_EXACT_ASSERTION_NAME)); |
| | | } |
| | | |
| | | defaultSubstringMatchingRule = |
| | | DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID); |
| | | if (defaultSubstringMatchingRule == null) |
| | | { |
| | | logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get( |
| | | SMR_CASE_IGNORE_OID, SYNTAX_CERTIFICATE_EXACT_ASSERTION_NAME)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public String getSyntaxName() |
| | | { |
| | | return SYNTAX_CERTIFICATE_EXACT_ASSERTION_NAME; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public String getOID() |
| | | { |
| | | return SYNTAX_CERTIFICATE_EXACT_ASSERTION_OID; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public String getDescription() |
| | | { |
| | | return SYNTAX_CERTIFICATE_EXACT_ASSERTION_DESCRIPTION; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public EqualityMatchingRule getEqualityMatchingRule() |
| | | { |
| | | return defaultEqualityMatchingRule; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public OrderingMatchingRule getOrderingMatchingRule() |
| | | { |
| | | return defaultOrderingMatchingRule; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public SubstringMatchingRule getSubstringMatchingRule() |
| | | { |
| | | return defaultSubstringMatchingRule; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ApproximateMatchingRule getApproximateMatchingRule() |
| | | { |
| | | // Approximate matching will not be allowed by default. |
| | | return null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean valueIsAcceptable(ByteSequence value, |
| | | MessageBuilder invalidReason) |
| | | { |
| | | // This method will never be called because this syntax is only used |
| | | // within assertions. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isBinary() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isHumanReadable() |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2006-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | | |
| | | |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.InputStream; |
| | | import java.math.BigInteger; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.CertificateFactory; |
| | | import java.security.cert.X509Certificate; |
| | | import javax.security.auth.x500.X500Principal; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.messages.SchemaMessages.*; |
| | | import static org.opends.server.schema.SchemaConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.api.EqualityMatchingRule; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.loggers.ErrorLogger; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.protocols.asn1.GSERException; |
| | | import org.opends.server.protocols.asn1.GSERParser; |
| | | import org.opends.server.types.ByteSequence; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringBuilder; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements the certificateExactMatch matching rule defined |
| | | * in X.509 and referenced in RFC 4523. |
| | | */ |
| | | class CertificateExactMatchingRule |
| | | extends EqualityMatchingRule |
| | | { |
| | | /** |
| | | * The GSER identifier for the serialNumber named value. |
| | | */ |
| | | private static final String GSER_ID_SERIALNUMBER = "serialNumber"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The GSER identifier for the issuer named value. |
| | | */ |
| | | private static final String GSER_ID_ISSUER = "issuer"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The GSER identifier for the rdnSequence IdentifiedChoiceValue. |
| | | */ |
| | | private static final String GSER_ID_RDNSEQUENCE = "rdnSequence"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The tracer object for the debug logger. |
| | | */ |
| | | private static final DebugTracer TRACER = getTracer(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this certificateExactMatch matching rule. |
| | | */ |
| | | public CertificateExactMatchingRule() |
| | | { |
| | | super(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<String> getAllNames() |
| | | { |
| | | return Collections.singleton(getName()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the common name for this matching rule. |
| | | * |
| | | * @return The common name for this matching rule, or <CODE>null</CODE> if |
| | | * it does not have a name. |
| | | */ |
| | | public String getName() |
| | | { |
| | | return EMR_CERTIFICATE_EXACT_NAME; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OID for this matching rule. |
| | | * |
| | | * @return The OID for this matching rule. |
| | | */ |
| | | public String getOID() |
| | | { |
| | | return EMR_CERTIFICATE_EXACT_OID; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the description for this matching rule. |
| | | * |
| | | * @return The description for this matching rule, or <CODE>null</CODE> if |
| | | * there is none. |
| | | */ |
| | | public String getDescription() |
| | | { |
| | | return EMR_CERTIFICATE_EXACT_DESCRIPTION; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OID of the syntax with which this matching rule is |
| | | * associated. |
| | | * |
| | | * @return The OID of the syntax with which this matching rule is associated. |
| | | */ |
| | | public String getSyntaxOID() |
| | | { |
| | | return SYNTAX_CERTIFICATE_EXACT_ASSERTION_OID; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the normalized form of the provided value, which is best suited |
| | | * for efficiently performing matching operations on that value. |
| | | * |
| | | * @param value The value to be normalized. |
| | | * |
| | | * @return The normalized version of the provided value. |
| | | * |
| | | * @throws DirectoryException If the provided value is invalid according to |
| | | * the associated attribute syntax. |
| | | */ |
| | | public ByteString normalizeValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | // The normalized form of this value is the GSER encoded .... |
| | | final BigInteger serialNumber; |
| | | final String dnstring; |
| | | String certificateIssuer; |
| | | |
| | | // Read the X.509 Certificate and extract serialNumber and issuerDN |
| | | try |
| | | { |
| | | CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); |
| | | InputStream inputStream = new ByteArrayInputStream(value.toByteArray()); |
| | | X509Certificate certValue = (X509Certificate) certFactory |
| | | .generateCertificate(inputStream); |
| | | |
| | | serialNumber = certValue.getSerialNumber(); |
| | | X500Principal issuer = certValue.getIssuerX500Principal(); |
| | | dnstring = issuer.getName(X500Principal.RFC2253); |
| | | } |
| | | catch (CertificateException ce) |
| | | { |
| | | // There seems to be a problem while parsing the certificate. |
| | | Message message = WARN_CERTIFICATE_MATCH_PARSE_ERROR.get(ce.getMessage()); |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugWarning(message.toString()); |
| | | } |
| | | |
| | | // return the raw bytes as a fall back |
| | | return value.toByteString(); |
| | | } |
| | | |
| | | // Normalize the DN |
| | | try |
| | | { |
| | | DN dn = DN.decode(dnstring); |
| | | certificateIssuer = dn.toNormalizedString(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize the DN for some reason. If we're supposed to use |
| | | // strict syntax enforcement, then throw an exception. Otherwise, log a |
| | | // message and just try our best. |
| | | Message message = ERR_CERTIFICATE_MATCH_INVALID_DN.get( |
| | | dnstring, getExceptionMessage(e)); |
| | | |
| | | switch (DirectoryServer.getSyntaxEnforcementPolicy()) |
| | | { |
| | | case REJECT: |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | case WARN: |
| | | ErrorLogger.logError(message); |
| | | |
| | | certificateIssuer= toLowerCase(dnstring); |
| | | break; |
| | | |
| | | default: |
| | | certificateIssuer= toLowerCase(dnstring); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // Create the encoded value |
| | | return createEncodedValue(serialNumber,certificateIssuer); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ByteString normalizeAssertionValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | // validate and normalize the GSER structure |
| | | // according to the definitions from RFC 4523, Appendix A.1 |
| | | final BigInteger serialNumber; |
| | | final String dnstring; |
| | | String certificateIssuer; |
| | | |
| | | final GSERParser parser; |
| | | String identifier; |
| | | |
| | | parser = new GSERParser(value.toString()); |
| | | |
| | | try |
| | | { |
| | | // the String starts with a sequence |
| | | parser.readStartSequence(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | // Assume the assertion value is a certificate and parse issuer and serial |
| | | // number. If the value is not even a certificate then the raw bytes will |
| | | // be returned. |
| | | return normalizeValue(value); |
| | | } |
| | | |
| | | try |
| | | { |
| | | // the first namedValue is serialNumber |
| | | identifier = parser.nextNamedValueIdentifier(); |
| | | if (!identifier.equals(GSER_ID_SERIALNUMBER)) |
| | | { |
| | | Message message = ERR_CERTIFICATE_MATCH_IDENTIFIER_NOT_FOUND |
| | | .get(GSER_ID_SERIALNUMBER); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | } |
| | | |
| | | // The value for the serialNumber |
| | | serialNumber = parser.nextBigInteger(); |
| | | |
| | | // separator |
| | | parser.skipSeparator(); |
| | | |
| | | // the next namedValue is issuer |
| | | identifier = parser.nextNamedValueIdentifier(); |
| | | if (!identifier.equals(GSER_ID_ISSUER)) |
| | | { |
| | | Message message = ERR_CERTIFICATE_MATCH_IDENTIFIER_NOT_FOUND |
| | | .get(GSER_ID_ISSUER); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | } |
| | | |
| | | // expecting "rdnSequence:" |
| | | identifier = parser.nextChoiceValueIdentifier(); |
| | | if (!identifier.equals(GSER_ID_RDNSEQUENCE)) |
| | | { |
| | | Message message = ERR_CERTIFICATE_MATCH_IDENTIFIER_NOT_FOUND |
| | | .get(GSER_ID_RDNSEQUENCE); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | } |
| | | |
| | | // now the issuer dn |
| | | dnstring = parser.nextString(); |
| | | |
| | | // Closing the Sequence |
| | | parser.readEndSequence(); |
| | | |
| | | // There should not be additional characters |
| | | if (parser.hasNext()) |
| | | { |
| | | Message message = ERR_CERTIFICATE_MATCH_EXPECTED_END.get(); |
| | | switch (DirectoryServer.getSyntaxEnforcementPolicy()) |
| | | { |
| | | case REJECT: |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | case WARN: |
| | | ErrorLogger.logError(message); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | Message message = ERR_CERTIFICATE_MATCH_GSER_INVALID.get( |
| | | getExceptionMessage(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | } |
| | | |
| | | // Normalize the DN |
| | | try |
| | | { |
| | | DN dn = DN.decode(dnstring); |
| | | certificateIssuer = dn.toNormalizedString(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize the DN for some reason. If we're supposed to use |
| | | // strict syntax enforcement, then throw an exception. Otherwise, log a |
| | | // message and just try our best. |
| | | Message message = ERR_CERTIFICATE_MATCH_INVALID_DN.get( |
| | | dnstring, getExceptionMessage(e)); |
| | | |
| | | switch (DirectoryServer.getSyntaxEnforcementPolicy()) |
| | | { |
| | | case REJECT: |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | case WARN: |
| | | ErrorLogger.logError(message); |
| | | |
| | | certificateIssuer= toLowerCase(dnstring); |
| | | break; |
| | | |
| | | default: |
| | | certificateIssuer= toLowerCase(dnstring); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // Create the encoded value |
| | | return createEncodedValue(serialNumber,certificateIssuer); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates the value containing serialNumber and issuer DN. |
| | | * |
| | | * @param serial the serialNumber |
| | | * @param issuerDN the issuer DN String |
| | | * |
| | | * @return the encoded ByteString |
| | | */ |
| | | private static ByteString createEncodedValue(BigInteger serial, |
| | | String issuerDN) |
| | | { |
| | | ByteStringBuilder builder = new ByteStringBuilder(); |
| | | builder.append(StaticUtils.getBytes(issuerDN)); |
| | | builder.append((byte) 0); // Separator |
| | | builder.append(serial.toByteArray()); |
| | | return builder.toByteString(); |
| | | } |
| | | |
| | | } |
| | | |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | |
| | | |
| | | package org.opends.server.schema; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import org.opends.server.api.MatchingRuleFactory; |
| | | import org.opends.server.admin.std.server.MatchingRuleCfg; |
| | | import org.opends.server.api.MatchingRule; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.InitializationException; |
| | | |
| | | /** |
| | | * This class is a factory class for |
| | | * {@link CertificateExactMatchingRule}. |
| | | */ |
| | | public final class CertificateExactMatchingRuleFactory |
| | | extends MatchingRuleFactory<MatchingRuleCfg> |
| | | { |
| | | //Associated Matching Rule. |
| | | private MatchingRule matchingRule; |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public final void initializeMatchingRule(MatchingRuleCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | matchingRule = new CertificateExactMatchingRule(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public final Collection<MatchingRule> getMatchingRules() |
| | | { |
| | | return Collections.singleton(matchingRule); |
| | | } |
| | | } |
| | |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2012 Forgerock AS |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | |
| | | throws ConfigException |
| | | { |
| | | defaultEqualityMatchingRule = |
| | | DirectoryServer.getEqualityMatchingRule(EMR_OCTET_STRING_OID); |
| | | DirectoryServer.getEqualityMatchingRule(EMR_CERTIFICATE_EXACT_OID); |
| | | if (defaultEqualityMatchingRule == null) |
| | | { |
| | | logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get( |
| | | EMR_OCTET_STRING_OID, SYNTAX_CERTIFICATE_NAME)); |
| | | EMR_CERTIFICATE_EXACT_OID, SYNTAX_CERTIFICATE_NAME)); |
| | | } |
| | | |
| | | defaultOrderingMatchingRule = |
| | |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2013 ForgeRock AS |
| | | * Portions copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The description for the certificateExactMatch equality matching rule. |
| | | */ |
| | | public static final String EMR_CERTIFICATE_EXACT_DESCRIPTION = |
| | | "X.509 Certificate Exact Match"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name for the certificateExactMatch equality matching rule. |
| | | */ |
| | | public static final String EMR_CERTIFICATE_EXACT_NAME = |
| | | "certificateExactMatch"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The OID for the certificateExactMatch equality matching rule. |
| | | */ |
| | | public static final String EMR_CERTIFICATE_EXACT_OID = "2.5.13.34"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name for the directoryStringFirstComponentMatch equality matching rule. |
| | | */ |
| | | public static final String EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME = |
| | |
| | | |
| | | |
| | | /** |
| | | * The description for the certificate exact assertion attribute syntax. |
| | | */ |
| | | public static final String SYNTAX_CERTIFICATE_EXACT_ASSERTION_DESCRIPTION = |
| | | "X.509 Certificate Exact Assertion"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name for the certificate exact assertion attribute syntax. |
| | | */ |
| | | public static final String SYNTAX_CERTIFICATE_EXACT_ASSERTION_NAME = |
| | | "CertificateExactAssertion"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The OID for the Certificate Exact Assertion syntax used for assertion |
| | | * values in extensible match filters. |
| | | */ |
| | | public static final String SYNTAX_CERTIFICATE_EXACT_ASSERTION_OID = |
| | | "1.3.6.1.1.15.1"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The description for the certificate attribute syntax. |
| | | */ |
| | | public static final String SYNTAX_CERTIFICATE_DESCRIPTION = "Certificate"; |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.types; |
| | | import org.opends.messages.Message; |
| | |
| | | return ConditionResult.FALSE; |
| | | } |
| | | |
| | | // Iterate through all the attributes and see if we can find a |
| | | // match. |
| | | // Get the equality matching rule for the given attribute type |
| | | MatchingRule matchingRule = attributeType.getEqualityMatchingRule(); |
| | | if (matchingRule == null) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugInfo( |
| | | "Attribute type %s does not have an equality matching " + |
| | | "rule -- returning undefined.", |
| | | attributeType.getNameOrOID()); |
| | | } |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | // Normalize the assertion value |
| | | ByteString value = assertionValue.getValue(); |
| | | ByteString normalizedValue; |
| | | try |
| | | { |
| | | normalizedValue = matchingRule.normalizeAssertionValue(value); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We can't normalize the assertion value, so the result must be |
| | | // undefined. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | |
| | | // Iterate through all the attributes and see if we can find a match. |
| | | AttributeValue dummyAttributeValue = AttributeValues.create(value, |
| | | normalizedValue); |
| | | |
| | | for (Attribute a : attrs) |
| | | { |
| | | if (a.contains(assertionValue)) |
| | | if (a.contains(dummyAttributeValue)) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugVerbose( |
| | | "Returning TRUE for equality component %s in " + |
| | | "filter %s for entry %s", |
| | | this, completeFilter, entry.getDN()); |
| | | "filter %s for entry %s", this, completeFilter, entry.getDN()); |
| | | } |
| | | return ConditionResult.TRUE; |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.controls; |
| | | |
| | | import java.text.ParseException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.protocols.asn1.ASN1Writer; |
| | | import org.opends.server.protocols.asn1.ASN1; |
| | | import org.opends.server.util.Base64; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | @DataProvider(name = "differentNormalization") |
| | | public Object[][] differentNormalizationData() throws ParseException |
| | | { |
| | | final String BASE64_CERT_VALUE = |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + |
| | | "BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" + |
| | | "dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" + |
| | | "Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" + |
| | | "b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" + |
| | | "IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" + |
| | | "8zAb1pbJ4HzC7iRlVGhRJjFORkGhyvU4P5o2wL0iz/uko6rL9/pFhIlIMbwbV8sm" + |
| | | "mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" + |
| | | "69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" + |
| | | "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" + |
| | | "FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" + |
| | | "MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" + |
| | | "6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" + |
| | | "axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" + |
| | | "1AIUXiE3Qcck"; |
| | | final String CERT_EXACT_ASSERTION = |
| | | "{ serialNumber 13233831500277100508, issuer rdnSequence:\""+ |
| | | "CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }"; |
| | | return new Object[][]{ |
| | | {"userCertificate", ByteString.wrap(Base64.decode(BASE64_CERT_VALUE)), |
| | | CERT_EXACT_ASSERTION}}; |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | @Test(dataProvider = "differentNormalization") |
| | | public void testDifferentNormalization(String type, ByteString value, |
| | | String assertion) |
| | | { |
| | | MatchedValuesFilter mvf; |
| | | AttributeType attrType = DirectoryServer.getAttributeType("usercertificate"); |
| | | AttributeValue attrValue = AttributeValues.create(attrType, value); |
| | | |
| | | mvf = MatchedValuesFilter.createEqualityFilter(type, ByteString.valueOf(assertion)); |
| | | assertTrue(mvf.valueMatches(attrType, attrValue)); |
| | | } |
| | | } |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.protocols.asn1; |
| | | |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | import static org.testng.Assert.*; |
| | | |
| | | import org.opends.server.protocols.asn1.GSERParser; |
| | | import org.opends.server.protocols.asn1.GSERException; |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class tests the GSERParser. |
| | | */ |
| | | public class GSERParserTestCase extends DirectoryServerTestCase |
| | | { |
| | | |
| | | /** |
| | | * Try to create a GSER Parser with <CODE>null</CODE> as parameter. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testGSERParserInitWithNull () throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the <CODE>hasNext</CODE> method. |
| | | */ |
| | | @Test() |
| | | public void testHasNext() throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser("0"); |
| | | assertTrue(parser.hasNext()); |
| | | assertEquals(parser.nextInteger(),0); |
| | | assertFalse(parser.hasNext()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the <CODE>skipSP</CODE> method. |
| | | */ |
| | | @Test() |
| | | public void testSkipSP() throws Exception |
| | | { |
| | | String[] values = {" 42"," 42","42"}; |
| | | for (String value : values) |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | assertEquals(parser.skipSP().nextInteger(),42); |
| | | assertFalse(parser.hasNext()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the <CODE>skipMSP</CODE> method. |
| | | */ |
| | | @Test() |
| | | public void testSkipMSP() throws Exception |
| | | { |
| | | String[] values = {" 42"," 42"," 42"}; |
| | | for (String value : values) |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | assertEquals(parser.skipMSP().nextInteger(),42); |
| | | assertFalse(parser.hasNext()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Verify that <CODE>skipMSP</CODE> requires at least one space. |
| | | */ |
| | | @Test(expectedExceptions = { GSERException.class }) |
| | | public void testSkipMSPwithZeroSpaces() throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser("42"); |
| | | parser.skipMSP(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testSequence</CODE> test case. |
| | | */ |
| | | @DataProvider(name="sequenceValues") |
| | | public Object[][] createSequenceValues() |
| | | { |
| | | return new Object[][] { |
| | | {"{123,122}", true}, |
| | | {"{ 123,1}", true }, |
| | | {"{ 123 , 1 }", true }, |
| | | {"{0123,}", false}, |
| | | {"{0123 42 }", false}, |
| | | {"{123 , 11 ", false}, |
| | | {" {123 , 11 ", false}, |
| | | {" 123 , 11}", false} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test sequence parsing. |
| | | */ |
| | | @Test(dataProvider="sequenceValues") |
| | | public void testSequence(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | parser.readStartSequence(); |
| | | parser.nextInteger(); |
| | | parser.skipSP().skipSeparator(); |
| | | parser.nextInteger(); |
| | | parser.readEndSequence(); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testString</CODE> test case. |
| | | */ |
| | | @DataProvider(name="stringValues") |
| | | public Object[][] createStringValues() |
| | | { |
| | | return new Object[][] { |
| | | {"\"\"", true}, |
| | | {"\"escaped\"\"dquotes\"", true }, |
| | | {"\"valid Unicode \u00D6\u00C4\"", true }, |
| | | {"\"only one \" \"", false}, |
| | | {"invalid without dquotes", false}, |
| | | {"\"missing end", false}, |
| | | {"\"valid string\" with extra trailing characters", false} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the parsing of String values. |
| | | */ |
| | | @Test(dataProvider="stringValues") |
| | | public void testString(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | assertNotNull(parser.nextString()); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testInteger</CODE> test case. |
| | | */ |
| | | @DataProvider(name="integerValues") |
| | | public Object[][] createIntegerValues() |
| | | { |
| | | return new Object[][] { |
| | | {"0123456", true}, |
| | | {"42", true}, |
| | | {"0", true }, |
| | | {"", false}, |
| | | {"0xFF", false}, |
| | | {"NULL", false}, |
| | | {"Not a Number", false} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testBigInteger</CODE> test case. |
| | | */ |
| | | @DataProvider(name="bigIntegerValues") |
| | | public Object[][] createBigIntegerValues() |
| | | { |
| | | return new Object[][] { |
| | | {"0123456", true}, |
| | | {"42", true}, |
| | | {"0", true }, |
| | | {"", false}, |
| | | {"0xFF", false}, |
| | | {"NULL", false}, |
| | | {"Not a Number", false}, |
| | | {"2147483648",true} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the parsing of Integer values. |
| | | */ |
| | | @Test(dataProvider="integerValues") |
| | | public void testInteger(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | parser.nextInteger(); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the parsing of BigInteger values. |
| | | */ |
| | | @Test(dataProvider="bigIntegerValues") |
| | | public void testBigInteger(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | parser.nextBigInteger(); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testNamedValueIdentifier</CODE> test case. |
| | | */ |
| | | @DataProvider(name="namedValueIdentifierValues") |
| | | public Object[][] createNamedValueIdentifierValues() |
| | | { |
| | | return new Object[][] { |
| | | {"serialNumber ", true}, |
| | | {"issuer ", true}, |
| | | {"Serialnumber ", false}, |
| | | {"0serialnumber ", false}, |
| | | {"serial Number ", false}, |
| | | {"missingSpace",false} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the parsing of NamedValue identifiers. |
| | | */ |
| | | @Test(dataProvider="namedValueIdentifierValues") |
| | | public void testNamedValueIdentifier(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | assertNotNull(parser.nextNamedValueIdentifier()); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create data for the <CODE>testIdentifiedChoiceIdentifier</CODE> test case. |
| | | */ |
| | | @DataProvider(name="identifiedChoicdeIdentifierValues") |
| | | public Object[][] createIdentifiedChoicdeIdentifierValues() |
| | | { |
| | | return new Object[][] { |
| | | {"serialNumber:", true}, |
| | | {"issuer1:", true}, |
| | | {"Serialnumber:", false}, |
| | | {"0serialnumber:", false}, |
| | | {"serial Number:", false}, |
| | | {"missingColon",false} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the parsing of IdentifiedChoice identifiers. |
| | | */ |
| | | @Test(dataProvider="identifiedChoicdeIdentifierValues") |
| | | public void testIdentifiedChoicdeIdentifier(String value, boolean expectedResult) throws Exception |
| | | { |
| | | GSERParser parser = new GSERParser(value); |
| | | boolean result = true; |
| | | try |
| | | { |
| | | assertNotNull(parser.nextChoiceValueIdentifier()); |
| | | if (parser.hasNext()) |
| | | { |
| | | result = false; |
| | | } |
| | | } |
| | | catch (GSERException e) |
| | | { |
| | | result = false; |
| | | } |
| | | assertEquals(expectedResult,result); |
| | | } |
| | | } |
| 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.util.Base64; |
| | | |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class tests the certificateExactMatch matching rule. |
| | | */ |
| | | public class CertificateExactMatchingRuleTest extends SchemaTestCase |
| | | { |
| | | /** |
| | | * Generate data for the certificateExactMatch matching rule test. |
| | | */ |
| | | @DataProvider(name="certificateExactMatchingRules") |
| | | public Object[][] createCertificateExactMatchingRuleTest() |
| | | throws Exception |
| | | { |
| | | String validcert1 = |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + |
| | | "BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" + |
| | | "dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" + |
| | | "Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" + |
| | | "b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" + |
| | | "IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" + |
| | | "8zAb1pbJ4HzC7iRlVGhRJjFORkGhyvU4P5o2wL0iz/uko6rL9/pFhIlIMbwbV8sm" + |
| | | "mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" + |
| | | "69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" + |
| | | "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" + |
| | | "FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" + |
| | | "MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" + |
| | | "6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" + |
| | | "axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" + |
| | | "1AIUXiE3Qcck"; |
| | | |
| | | return new Object[][] { |
| | | {ByteString.wrap(Base64.decode(validcert1)),ByteString.valueOf( |
| | | "{ serialNumber 13233831500277100508, issuer rdnSequence:\""+ |
| | | "CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }"), true }, |
| | | {ByteString.wrap(Base64.decode(validcert1)),ByteString.valueOf( |
| | | "{ serialNumber 13233831500277100508, issuer rdnSequence:\""+ |
| | | "CN=Babs Jensen,OU=Product Development, L=Cupertione,C=US\" }"), true }, |
| | | {ByteString.wrap(Base64.decode(validcert1)),ByteString.valueOf( |
| | | "{ serialNumber 13233831500277100508, issuer rdnSequence:\""+ |
| | | "cn=BABS Jensen,ou=Product Development,L=Cupertione,c=#5553\" }"), true }, |
| | | {ByteString.wrap(Base64.decode(validcert1)),ByteString.valueOf( |
| | | "{ serialNumber 13233831511277100508, issuer rdnSequence:\""+ |
| | | "CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }"), false }, |
| | | {ByteString.wrap(Base64.decode( |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV")), |
| | | ByteString.wrap(Base64.decode( |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV")), true} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generate valid assertion values for the certificateExactMatch matching |
| | | * rule test. |
| | | */ |
| | | @DataProvider(name="certificateExactMatchValidAssertionValues") |
| | | public Object[][] createCertificateExactMatchingRuleValidAssertionValues() |
| | | { |
| | | return new Object[][] { |
| | | {"{serialNumber 123,issuer rdnSequence:\"c=DE\"}"}, |
| | | {"{serialNumber 123,issuer rdnSequence:\"\"}"}, |
| | | {"{serialNumber 0123,issuer rdnSequence:\"cn=issuer\"}"}, |
| | | {"{ serialNumber 123, issuer rdnSequence:\"c=DE\" }"}, |
| | | {"{serialNumber 123,issuer rdnSequence:\"cn=escaped\"\"dquotes\"}"}, |
| | | {"{serialNumber 123,issuer rdnSequence:\"cn=\u00D6\u00C4\"}"} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generate invalid assertion values for the certificateExactMatch matching |
| | | * rule test. |
| | | */ |
| | | @DataProvider(name="certificateExactMatchInvalidAssertionValues") |
| | | public Object[][] createCertificateExactMatchingRuleInvalidAssertionValues() |
| | | { |
| | | return new Object[][] { |
| | | {"{serialnumber 123,issuer rdnSequence:\"c=DE\"}"}, |
| | | {"{serialNumber 123,issuer rdnSequence:\"invalid\"}"}, |
| | | {"{serialNumber 0123,issuer rdnSequence: \"cn=issuer\"}"}, |
| | | {"{ serialNumber 123 , issuer rdnSequence:\"c=DE\" } trailing"} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generate invalid atribute values for the certificateExactMatch matching |
| | | * rule test. |
| | | */ |
| | | @DataProvider(name="certificateExactMatchInvalidAttributeValues") |
| | | public Object[][] createCertificateExactMatchingRuleInvalidAttributeValues() |
| | | throws Exception |
| | | { |
| | | String invalidcert1 = |
| | | "MIICpTCCAg6gAwIBBQIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + |
| | | "BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" + |
| | | "dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" + |
| | | "Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" + |
| | | "b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" + |
| | | "IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" + |
| | | "8zAb1pbJ4HzC7iRlVGhRJjFORkGhyvU4P5o2wL0iz/uko6rL9/pFhIlIMbwbV8sm" + |
| | | "mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" + |
| | | "69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" + |
| | | "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" + |
| | | "FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" + |
| | | "MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" + |
| | | "6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" + |
| | | "axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" + |
| | | "1AIUXiE3Qcck"; |
| | | |
| | | String brokencert1 = |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV"; |
| | | |
| | | return new Object[][] { |
| | | {ByteString.wrap(Base64.decode(invalidcert1))}, |
| | | {ByteString.wrap(Base64.decode(brokencert1))} |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get an instance of the matching rule. |
| | | * |
| | | * @return An instance of the matching rule to test. |
| | | */ |
| | | protected CertificateExactMatchingRule getRule() |
| | | { |
| | | return new CertificateExactMatchingRule(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the normalization and the comparison of valid values. |
| | | */ |
| | | @Test(dataProvider= "certificateExactMatchingRules") |
| | | public void certificateExactMatchingRules(ByteString attributeValue, |
| | | ByteString assertionValue, Boolean result) throws Exception |
| | | { |
| | | CertificateExactMatchingRule rule = getRule(); |
| | | |
| | | // normalize the 2 provided values and check that they are equals |
| | | ByteString normalizedAttributeValue = |
| | | rule.normalizeValue(attributeValue); |
| | | ByteString normalizedAssertionValue = |
| | | rule.normalizeAssertionValue(assertionValue); |
| | | |
| | | Boolean liveResult = rule.areEqual(normalizedAttributeValue, |
| | | normalizedAssertionValue); |
| | | assertEquals(result, liveResult); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test that valid assertion values are accepted. |
| | | */ |
| | | @Test(dataProvider= "certificateExactMatchValidAssertionValues") |
| | | public void certificateExactMatchingRuleValidAssertionValues(String value) |
| | | throws Exception |
| | | { |
| | | // Get the instance of the rule to be tested. |
| | | CertificateExactMatchingRule rule = getRule(); |
| | | |
| | | // normalize the provided assertion values |
| | | rule.normalizeAssertionValue(ByteString.valueOf(value)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test that invalid assertion values are rejected. |
| | | */ |
| | | @Test(dataProvider= "certificateExactMatchInvalidAssertionValues", |
| | | expectedExceptions={ DirectoryException.class }) |
| | | public void certificateExactMatchingRuleInvalidAssertionValues(String value) |
| | | throws Exception |
| | | { |
| | | // Get the instance of the rule to be tested. |
| | | CertificateExactMatchingRule rule = getRule(); |
| | | |
| | | // normalize the provided assertion value |
| | | rule.normalizeAssertionValue(ByteString.valueOf(value)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test that invalid attribute values are returned with the original ByteString. |
| | | */ |
| | | @Test(dataProvider= "certificateExactMatchInvalidAttributeValues") |
| | | public void certificateExactMatchingRuleInvalidAttributeValues(ByteString value) |
| | | throws Exception |
| | | { |
| | | // Get the instance of the rule to be tested. |
| | | CertificateExactMatchingRule rule = getRule(); |
| | | |
| | | // normalize the provided assertion value |
| | | ByteString normalizedValue = rule.normalizeAssertionValue(value); |
| | | assertEquals(value,normalizedValue); |
| | | } |
| | | |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2014 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.types; |
| | | |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.util.StaticUtils; |
| | | import org.opends.server.util.Base64; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.RawFilter; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | import java.text.ParseException; |
| | | |
| | | import static java.util.Arrays.asList; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | |
| | | assertEquals(actualEquals, expectStringEquals, |
| | | "Expected " + filter1 + (expectStringEquals ? " == " : " != ") + filter2); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Dataprovider for testing different normalization for value and assertion |
| | | */ |
| | | @DataProvider(name = "differentNormalization") |
| | | public Object[][] differentNormalizationData() throws ParseException |
| | | { |
| | | final String BASE64_CERT_VALUE = |
| | | "MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + |
| | | "BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" + |
| | | "dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" + |
| | | "Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" + |
| | | "b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" + |
| | | "IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" + |
| | | "8zAb1pbJ4HzC7iRlVGhRJjFORkGhyvU4P5o2wL0iz/uko6rL9/pFhIlIMbwbV8sm" + |
| | | "mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" + |
| | | "69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" + |
| | | "hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" + |
| | | "FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" + |
| | | "MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" + |
| | | "6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" + |
| | | "axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" + |
| | | "1AIUXiE3Qcck"; |
| | | final String CERT_EXACT_ASSERTION = |
| | | "{ serialNumber 13233831500277100508, issuer rdnSequence:\""+ |
| | | "CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }"; |
| | | final String CERTIFICATE_LDIF = TestCaseUtils.makeLdif( |
| | | "dn: cn=John Smith,dc=example,dc=com", |
| | | "objectclass: inetorgperson", |
| | | "cn: John Smith", |
| | | "sn: Smith", |
| | | "userCertificate;binary:: "+BASE64_CERT_VALUE |
| | | ); |
| | | StringBuilder builder = new StringBuilder(); |
| | | RawFilter.valueToFilterString(builder,ByteString.wrap(Base64.decode(BASE64_CERT_VALUE))); |
| | | final String CERTIFICATE_ENCODED = builder.toString(); |
| | | |
| | | return new Object[][]{ |
| | | {CERTIFICATE_LDIF, "userCertificate="+CERT_EXACT_ASSERTION, true}, |
| | | {CERTIFICATE_LDIF, "userCertificate="+CERTIFICATE_ENCODED, true}}; |
| | | } |
| | | |
| | | @Test(dataProvider = "differentNormalization") |
| | | public void testdifferentNormalization(String ldifEntry, String filterStr, |
| | | boolean expectMatch) throws Exception |
| | | { |
| | | Entry entry = TestCaseUtils.entryFromLdifString(ldifEntry); |
| | | boolean matches = SearchFilter.createFilterFromString(filterStr).matchesEntry(entry); |
| | | Assert.assertEquals(matches, expectMatch, "Filter=" + filterStr + "\nEntry=" + entry); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | |