Add three new certificate mappers to the server:
- One which will take attributes from the certificate subject and map them to
attributes in user entries (Issue #1278).
- One which will search for the subjects of the presented certificates in user
entries (Issue #1279).
- One which will search for the MD5 or SHA1 fingerprints of the presented
certificates in user entries (Issue #1280).
6 files added
5 files modified
| | |
| | | dn: cn=Subject Equals DN,cn=Certificate Mappers,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-certificate-mapper |
| | | cn: Certificate Mapper |
| | | cn: Subject Equals DN |
| | | ds-cfg-certificate-mapper-class: org.opends.server.extensions.SubjectEqualsDNCertificateMapper |
| | | ds-cfg-certificate-mapper-enabled: true |
| | | |
| | | dn: cn=Subject DN to User Attribute,cn=Certificate Mappers,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-certificate-mapper |
| | | objectClass: ds-cfg-subject-dn-to-user-attribute-certificate-mapper |
| | | cn: Subject DN to User Attribute |
| | | ds-cfg-certificate-mapper-class: org.opends.server.extensions.SubjectDNToUserAttributeCertificateMapper |
| | | ds-cfg-certificate-mapper-enabled: true |
| | | ds-cfg-certificate-subject-attribute-type: ds-certificate-subject-dn |
| | | |
| | | dn: cn=Subject Attribute to User Attribute,cn=Certificate Mappers,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-certificate-mapper |
| | | objectClass: ds-cfg-subject-attribute-to-user-attribute-certificate-mapper |
| | | cn: Subject Attribute to User Attribute |
| | | ds-cfg-certificate-mapper-class: org.opends.server.extensions.SubjectAttributeToUserAttributeCertificateMapper |
| | | ds-cfg-certificate-mapper-enabled: true |
| | | ds-cfg-certificate-subject-attribute-mapping: cn:cn |
| | | ds-cfg-certificate-subject-attribute-mapping: e:mail |
| | | |
| | | dn: cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-certificate-mapper |
| | | objectClass: ds-cfg-fingerprint-certificate-mapper |
| | | cn: Fingerprint Mapper |
| | | ds-cfg-certificate-mapper-class: org.opends.server.extensions.FingerprintCertificateMapper |
| | | ds-cfg-certificate-mapper-enabled: true |
| | | ds-cfg-certificate-fingerprint-attribute-type: ds-certificate-fingerprint |
| | | ds-cfg-certificate-fingerprint-algorithm: MD5 |
| | | |
| | | dn: cn=Connection Handlers,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-branch |
| | |
| | | ds-cfg-trust-manager-provider-class: org.opends.server.extensions.FileBasedTrustManagerProvider |
| | | ds-cfg-trust-manager-provider-enabled: false |
| | | ds-cfg-trust-store-type: PKCS12 |
| | | ds-cfg-trust-store-file: config/truststore |
| | | ds-cfg-trust-store-file: config/truststore.p12 |
| | | |
| | | dn: cn=Virtual Attributes,cn=config |
| | | objectClass: top |
| | |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.311 |
| | | NAME 'ds-cfg-trust-manager-provider-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 |
| | | SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.312 |
| | | NAME 'ds-cfg-certificate-subject-attribute-type' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.313 |
| | | NAME 'ds-cfg-certificate-user-base-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.314 |
| | | NAME 'ds-certificate-subject-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.315 |
| | | NAME 'ds-cfg-certificate-subject-attribute-mapping' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.316 NAME 'ds-certificate-fingerprint' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.317 |
| | | NAME 'ds-cfg-certificate-fingerprint-attribute-type' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.318 |
| | | NAME 'ds-cfg-certificate-fingerprint-algorithm' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.1 |
| | | NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL |
| | | MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled ) |
| | |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.82 NAME 'ds-cfg-root-dn-base' SUP top |
| | | STRUCTURAL MUST cn MAY ds-cfg-default-root-privilege-name |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.83 NAME 'ds-certificate-user' SUP top |
| | | AUXILIARY MAY ( userCertificate $ ds-certificate-subject-dn $ |
| | | ds-certificate-fingerprint ) X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.84 |
| | | NAME 'ds-cfg-subject-dn-to-user-attribute-certificate-mapper' |
| | | SUP ds-cfg-certificate-mapper STRUCTURAL |
| | | MUST ds-cfg-certificate-subject-attribute-type |
| | | MAY ds-cfg-certificate-user-base-dn X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.85 |
| | | NAME 'ds-cfg-subject-attribute-to-user-attribute-certificate-mapper' |
| | | SUP ds-cfg-certificate-mapper STRUCTURAL |
| | | MUST ds-cfg-certificate-subject-attribute-mapping |
| | | MAY ds-cfg-certificate-user-base-dn X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.86 |
| | | NAME 'ds-cfg-fingerprint-certificate-mapper' SUP ds-cfg-certificate-mapper |
| | | STRUCTURAL MUST ( ds-cfg-certificate-fingerprint-attribute-type $ |
| | | ds-cfg-certificate-fingerprint-algorithm ) |
| | | MAY ds-cfg-certificate-user-base-dn X-ORIGIN 'OpenDS Directory Server' ) |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the name of the |
| | | * attribute type that should be used when mapping a certificate fingerprint |
| | | * to a user entry. |
| | | */ |
| | | public static final String ATTR_CERTIFICATE_FINGERPRINT_ATTR = |
| | | "ds-cfg-certificate-fingerprint-attribute-type"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the name of the |
| | | * algorithm that should be used to generate the certificate fingerprint. |
| | | */ |
| | | public static final String ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM = |
| | | "ds-cfg-certificate-fingerprint-algorithm"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the name of the |
| | | * attribute type that should be used when mapping a certificate subject to a |
| | | * user entry. |
| | | */ |
| | | public static final String ATTR_CERTIFICATE_SUBJECT_ATTR = |
| | | "ds-cfg-certificate-subject-attribute-type"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the name of the |
| | | * attribute type that should be used when mapping attributes in a certificate |
| | | * subject to a user entry. |
| | | */ |
| | | public static final String ATTR_CERTIFICATE_SUBJECT_ATTR_MAP = |
| | | "ds-cfg-certificate-subject-attribute-mapping"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the name of the |
| | | * attribute type that should be used when mapping a certificate subject to a |
| | | * user entry. |
| | | */ |
| | | public static final String ATTR_CERTIFICATE_SUBJECT_BASEDN = |
| | | "ds-cfg-certificate-user-base-dn"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The name of the configuration attribute that holds the fully-qualified name |
| | | * of the Java class for the certificate mapper implementation. |
| | | */ |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.security.MessageDigest; |
| | | import java.security.cert.Certificate; |
| | | import java.security.cert.X509Certificate; |
| | | import javax.security.auth.x500.X500Principal; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.api.CertificateMapper; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.config.MultiChoiceConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.types.SearchScope; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a very simple Directory Server certificate mapper that |
| | | * will map a certificate to a user only if that user's entry contains an |
| | | * attribute with the fingerprint of the client certificate. There must be |
| | | * exactly one matching user entry for the mapping to be successful. |
| | | */ |
| | | public class FingerprintCertificateMapper |
| | | extends CertificateMapper |
| | | implements ConfigurableComponent |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class for debugging purposes. |
| | | */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.extensions.FingerprintCertificateMapper"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The set of allowed fingerprint algorithms. |
| | | */ |
| | | private static final Set<String> FINGERPRINT_ALGORITHMS; |
| | | |
| | | |
| | | |
| | | // The attribute type that will be used to map the certificate's fingerprint. |
| | | private AttributeType fingerprintAttributeType; |
| | | |
| | | // The DN of the configuration entry for this certificate mapper. |
| | | private DN configEntryDN; |
| | | |
| | | // The set of base DNs below which the search will be performed. |
| | | private DN[] baseDNs; |
| | | |
| | | // The algorithm that will be used to generate the fingerprint. |
| | | private String fingerprintAlgorithm; |
| | | |
| | | |
| | | |
| | | static |
| | | { |
| | | LinkedHashSet<String> algorithmSet = new LinkedHashSet<String>(2); |
| | | algorithmSet.add("md5"); |
| | | algorithmSet.add("sha1"); |
| | | FINGERPRINT_ALGORITHMS = algorithmSet; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this certificate mapper. Note that all actual |
| | | * initialization should be done in the |
| | | * <CODE>initializeCertificateMapper</CODE> method. |
| | | */ |
| | | public FingerprintCertificateMapper() |
| | | { |
| | | super(); |
| | | |
| | | assert debugConstructor(CLASS_NAME); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeCertificateMapper(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "initializeCertificateMapper", |
| | | String.valueOf(configEntry)); |
| | | |
| | | this.configEntryDN = configEntry.getDN(); |
| | | |
| | | // Get the attribute type that will be used to hold the fingerprint. |
| | | int msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ATTR); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | fingerprintAttributeType = |
| | | DirectoryServer.getAttributeType(lowerName, false); |
| | | if (fingerprintAttributeType == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | } |
| | | } |
| | | catch (ConfigException ce) |
| | | { |
| | | throw ce; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Get the fingerprint algorithm. |
| | | msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM; |
| | | MultiChoiceConfigAttribute algorithmStub = |
| | | new MultiChoiceConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM, |
| | | getMessage(msgID), true, false, false, |
| | | FINGERPRINT_ALGORITHMS); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute algorithmAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(algorithmStub); |
| | | if (algorithmAttr == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ALGORITHM; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else |
| | | { |
| | | fingerprintAlgorithm = algorithmAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ALGORITHM; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | baseDNs = null; |
| | | msgID = MSGID_FCM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | baseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeCertificateMapper() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "finalizeCertificateMapper"); |
| | | |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry mapCertificateToUser(Certificate[] certificateChain) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "mapCertificateToUser", |
| | | String.valueOf(certificateChain)); |
| | | |
| | | |
| | | // Make sure that a peer certificate was provided. |
| | | if ((certificateChain == null) || (certificateChain.length == 0)) |
| | | { |
| | | int msgID = MSGID_FCM_NO_PEER_CERTIFICATE; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the first certificate in the chain. It must be an X.509 certificate. |
| | | X509Certificate peerCertificate; |
| | | try |
| | | { |
| | | peerCertificate = (X509Certificate) certificateChain[0]; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "mapCertificateToUser", e); |
| | | |
| | | int msgID = MSGID_FCM_PEER_CERT_NOT_X509; |
| | | String message = |
| | | getMessage(msgID, String.valueOf(certificateChain[0].getType())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the signature from the peer certificate and create a digest of it |
| | | // using the configured algorithm. |
| | | String fingerprintString; |
| | | try |
| | | { |
| | | MessageDigest digest = MessageDigest.getInstance(fingerprintAlgorithm); |
| | | byte[] fingerprintBytes = digest.digest(peerCertificate.getEncoded()); |
| | | fingerprintString = bytesToColonDelimitedHex(fingerprintBytes); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "mapCertificateToUser", e); |
| | | |
| | | String peerSubject = peerCertificate.getSubjectX500Principal().getName( |
| | | X500Principal.RFC2253); |
| | | |
| | | int msgID = MSGID_FCM_CANNOT_CALCULATE_FINGERPRINT; |
| | | String message = getMessage(msgID, peerSubject, |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Create the search filter from the fingerprint. |
| | | AttributeValue value = |
| | | new AttributeValue(fingerprintAttributeType, fingerprintString); |
| | | SearchFilter filter = |
| | | SearchFilter.createEqualityFilter(fingerprintAttributeType, value); |
| | | |
| | | |
| | | // If we have an explicit set of base DNs, then use it. Otherwise, use the |
| | | // set of public naming contexts in the server. |
| | | DN[] bases = baseDNs; |
| | | if (bases == null) |
| | | { |
| | | bases = new DN[0]; |
| | | bases = DirectoryServer.getPublicNamingContexts().keySet().toArray(bases); |
| | | } |
| | | |
| | | |
| | | // For each base DN, issue an internal search in an attempt to map the |
| | | // certificate. |
| | | Entry userEntry = null; |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | for (DN baseDN : bases) |
| | | { |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(baseDN, SearchScope.WHOLE_SUBTREE, filter); |
| | | for (SearchResultEntry entry : searchOperation.getSearchEntries()) |
| | | { |
| | | if (userEntry == null) |
| | | { |
| | | userEntry = entry; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_FCM_MULTIPLE_MATCHING_ENTRIES; |
| | | String message = getMessage(msgID, fingerprintString, |
| | | String.valueOf(userEntry.getDN()), |
| | | String.valueOf(entry.getDN())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then we either found exactly one user entry or we |
| | | // didn't find any. Either way, return the entry or null to the caller. |
| | | return userEntry; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this |
| | | * component is associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this |
| | | * component is associated. |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN"); |
| | | |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurationAttributes"); |
| | | |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | int msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR; |
| | | attrList.add(new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR, |
| | | getMessage(msgID), true, false, false, |
| | | fingerprintAttributeType.getNameOrOID())); |
| | | |
| | | msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM; |
| | | attrList.add(new MultiChoiceConfigAttribute( |
| | | ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM, |
| | | getMessage(msgID), true, false, false, |
| | | FINGERPRINT_ALGORITHMS, fingerprintAlgorithm)); |
| | | |
| | | LinkedList<DN> dnList = new LinkedList<DN>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | dnList.add(baseDN); |
| | | } |
| | | } |
| | | |
| | | msgID = MSGID_FCM_DESCRIPTION_BASE_DN; |
| | | attrList.add(new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false, |
| | | dnList)); |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an |
| | | * acceptable configuration for this component. If it does not, |
| | | * then detailed information about the problem(s) should be added to |
| | | * the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to |
| | | * make the determination. |
| | | * @param unacceptableReasons A list that can be used to hold |
| | | * messages about why the provided |
| | | * entry does not have an acceptable |
| | | * configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an |
| | | * acceptable configuration for this component, or |
| | | * <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration", |
| | | String.valueOf(configEntry), "java.util.List<String>"); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | boolean configAcceptable = true; |
| | | |
| | | |
| | | // Get the attribute type that will be used to hold the fingerprint. |
| | | AttributeType newFingerprintType = null; |
| | | int msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ATTR); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | newFingerprintType = |
| | | DirectoryServer.getAttributeType(lowerName, false); |
| | | if (newFingerprintType == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Get the fingerprint algorithm. |
| | | String newFingerprintAlgorithm = null; |
| | | msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM; |
| | | MultiChoiceConfigAttribute algorithmStub = |
| | | new MultiChoiceConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM, |
| | | getMessage(msgID), true, false, false, |
| | | FINGERPRINT_ALGORITHMS); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute algorithmAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(algorithmStub); |
| | | if (algorithmAttr == null) |
| | | { |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ALGORITHM; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | else |
| | | { |
| | | newFingerprintAlgorithm = algorithmAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ALGORITHM; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | DN[] newBaseDNs = null; |
| | | msgID = MSGID_FCM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | newBaseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(newBaseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained |
| | | * in the provided entry. Information about the result of this |
| | | * processing should be added to the provided message list. |
| | | * Information should always be added to this list if a |
| | | * configuration change could not be applied. If detailed results |
| | | * are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not |
| | | * changed) should also be included. |
| | | * |
| | | * @param configEntry The entry containing the new |
| | | * configuration to apply for this |
| | | * component. |
| | | * @param detailedResults Indicates whether detailed information |
| | | * about the processing should be added to |
| | | * the list. |
| | | * |
| | | * @return Information about the result of the configuration |
| | | * update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "applyNewConfiguration", |
| | | String.valueOf(configEntry), |
| | | String.valueOf(detailedResults)); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | boolean adminActionRequired = false; |
| | | |
| | | |
| | | // Get the attribute type that will be used to hold the fingerprint. |
| | | AttributeType newFingerprintType = null; |
| | | int msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ATTR)); |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | newFingerprintType = |
| | | DirectoryServer.getAttributeType(lowerName, false); |
| | | if (newFingerprintType == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.NO_SUCH_ATTRIBUTE; |
| | | } |
| | | |
| | | msgID = MSGID_FCM_NO_SUCH_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the fingerprint algorithm. |
| | | String newFingerprintAlgorithm = null; |
| | | msgID = MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM; |
| | | MultiChoiceConfigAttribute algorithmStub = |
| | | new MultiChoiceConfigAttribute(ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM, |
| | | getMessage(msgID), true, false, false, |
| | | FINGERPRINT_ALGORITHMS); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute algorithmAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(algorithmStub); |
| | | if (algorithmAttr == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_FCM_NO_FINGERPRINT_ALGORITHM; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_FINGERPRINT_ALGORITHM)); |
| | | } |
| | | else |
| | | { |
| | | newFingerprintAlgorithm = algorithmAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_FINGERPRINT_ALGORITHM; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | DN[] newBaseDNs = null; |
| | | msgID = MSGID_FCM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | newBaseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(newBaseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | msgID = MSGID_FCM_CANNOT_GET_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | fingerprintAttributeType = newFingerprintType; |
| | | fingerprintAlgorithm = newFingerprintAlgorithm; |
| | | baseDNs = newBaseDNs; |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.security.cert.Certificate; |
| | | import java.security.cert.X509Certificate; |
| | | import javax.security.auth.x500.X500Principal; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.api.CertificateMapper; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.types.SearchScope; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a very simple Directory Server certificate mapper that |
| | | * will map a certificate to a user based on attributes contained in both the |
| | | * certificate subject and the user's entry. The configuration may include |
| | | * mappings from certificate attributes to attributes in user entries, and all |
| | | * of those certificate attributes that are present in the subject will be used |
| | | * to search for matching user entries. |
| | | */ |
| | | public class SubjectAttributeToUserAttributeCertificateMapper |
| | | extends CertificateMapper |
| | | implements ConfigurableComponent |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class for debugging purposes. |
| | | */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper"; |
| | | |
| | | |
| | | |
| | | // The DN of the configuration entry for this certificate mapper. |
| | | private DN configEntryDN; |
| | | |
| | | // The set of base DNs below which the search will be performed. |
| | | private DN[] baseDNs; |
| | | |
| | | // The mappings between certificate attribute names and user attribute types. |
| | | private LinkedHashMap<String,AttributeType> attributeMap; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this certificate mapper. Note that all actual |
| | | * initialization should be done in the |
| | | * <CODE>initializeCertificateMapper</CODE> method. |
| | | */ |
| | | public SubjectAttributeToUserAttributeCertificateMapper() |
| | | { |
| | | super(); |
| | | |
| | | assert debugConstructor(CLASS_NAME); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeCertificateMapper(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "initializeCertificateMapper", |
| | | String.valueOf(configEntry)); |
| | | |
| | | this.configEntryDN = configEntry.getDN(); |
| | | |
| | | // Get the attribute that will be used to map subject attributes to user |
| | | // attributes. |
| | | attributeMap = new LinkedHashMap<String,AttributeType>(); |
| | | int msgID = MSGID_SATUACM_DESCRIPTION_ATTR_MAP; |
| | | StringConfigAttribute mapStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR_MAP, |
| | | getMessage(msgID), true, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute mapAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(mapStub); |
| | | if (mapAttr == null) |
| | | { |
| | | msgID = MSGID_SATUACM_NO_MAP_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR_MAP); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else |
| | | { |
| | | for (String mapStr : mapAttr.pendingValues()) |
| | | { |
| | | String lowerMap = toLowerCase(mapStr); |
| | | int colonPos = lowerMap.indexOf(':'); |
| | | if (colonPos <= 0) |
| | | { |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | String certAttrName = lowerMap.substring(0, colonPos).trim(); |
| | | String userAttrName = lowerMap.substring(colonPos+1).trim(); |
| | | if ((certAttrName.length() == 0) || (userAttrName.length() == 0)) |
| | | { |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | if (attributeMap.containsKey(certAttrName)) |
| | | { |
| | | msgID = MSGID_SATUACM_DUPLICATE_CERT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | certAttrName); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | AttributeType userAttrType = |
| | | DirectoryServer.getAttributeType(userAttrName, false); |
| | | if (userAttrType == null) |
| | | { |
| | | msgID = MSGID_SATUACM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, mapStr, |
| | | String.valueOf(configEntryDN), |
| | | userAttrName); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | for (AttributeType attrType : attributeMap.values()) |
| | | { |
| | | if (attrType.equals(userAttrType)) |
| | | { |
| | | msgID = MSGID_SATUACM_DUPLICATE_USER_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrType.getNameOrOID()); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | } |
| | | |
| | | attributeMap.put(certAttrName, userAttrType); |
| | | } |
| | | } |
| | | } |
| | | catch (ConfigException ce) |
| | | { |
| | | throw ce; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_ATTR_MAP; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | baseDNs = null; |
| | | msgID = MSGID_SATUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | baseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeCertificateMapper() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "finalizeCertificateMapper"); |
| | | |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry mapCertificateToUser(Certificate[] certificateChain) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "mapCertificateToUser", |
| | | String.valueOf(certificateChain)); |
| | | |
| | | |
| | | // Make sure that a peer certificate was provided. |
| | | if ((certificateChain == null) || (certificateChain.length == 0)) |
| | | { |
| | | int msgID = MSGID_SATUACM_NO_PEER_CERTIFICATE; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the first certificate in the chain. It must be an X.509 certificate. |
| | | X509Certificate peerCertificate; |
| | | try |
| | | { |
| | | peerCertificate = (X509Certificate) certificateChain[0]; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "mapCertificateToUser", e); |
| | | |
| | | int msgID = MSGID_SATUACM_PEER_CERT_NOT_X509; |
| | | String message = |
| | | getMessage(msgID, String.valueOf(certificateChain[0].getType())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the subject from the peer certificate and use it to create a search |
| | | // filter. |
| | | DN peerDN; |
| | | X500Principal peerPrincipal = peerCertificate.getSubjectX500Principal(); |
| | | String peerName = peerPrincipal.getName(X500Principal.RFC2253); |
| | | try |
| | | { |
| | | peerDN = DN.decode(peerName); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_SATUACM_CANNOT_DECODE_SUBJECT_AS_DN; |
| | | String message = getMessage(msgID, peerName, de.getErrorMessage()); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID, de); |
| | | } |
| | | |
| | | LinkedList<SearchFilter> filterComps = new LinkedList<SearchFilter>(); |
| | | for (int i=0; i < peerDN.getNumComponents(); i++) |
| | | { |
| | | RDN rdn = peerDN.getRDN(i); |
| | | for (int j=0; j < rdn.getNumValues(); j++) |
| | | { |
| | | String lowerName = toLowerCase(rdn.getAttributeName(j)); |
| | | AttributeType attrType = attributeMap.get(lowerName); |
| | | if (attrType != null) |
| | | { |
| | | filterComps.add(SearchFilter.createEqualityFilter(attrType, |
| | | rdn.getAttributeValue(j))); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (filterComps.isEmpty()) |
| | | { |
| | | int msgID = MSGID_SATUACM_NO_MAPPABLE_ATTRIBUTES; |
| | | String message = getMessage(msgID, peerName); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | SearchFilter filter = SearchFilter.createANDFilter(filterComps); |
| | | |
| | | |
| | | // If we have an explicit set of base DNs, then use it. Otherwise, use the |
| | | // set of public naming contexts in the server. |
| | | DN[] bases = baseDNs; |
| | | if (bases == null) |
| | | { |
| | | bases = new DN[0]; |
| | | bases = DirectoryServer.getPublicNamingContexts().keySet().toArray(bases); |
| | | } |
| | | |
| | | |
| | | // For each base DN, issue an internal search in an attempt to map the |
| | | // certificate. |
| | | Entry userEntry = null; |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | for (DN baseDN : bases) |
| | | { |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(baseDN, SearchScope.WHOLE_SUBTREE, filter); |
| | | for (SearchResultEntry entry : searchOperation.getSearchEntries()) |
| | | { |
| | | if (userEntry == null) |
| | | { |
| | | userEntry = entry; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_SATUACM_MULTIPLE_MATCHING_ENTRIES; |
| | | String message = getMessage(msgID, peerName, |
| | | String.valueOf(userEntry.getDN()), |
| | | String.valueOf(entry.getDN())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then we either found exactly one user entry or we |
| | | // didn't find any. Either way, return the entry or null to the caller. |
| | | return userEntry; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this |
| | | * component is associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this |
| | | * component is associated. |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN"); |
| | | |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurationAttributes"); |
| | | |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | LinkedList<String> mapValues = new LinkedList<String>(); |
| | | for (String certAttrName : attributeMap.keySet()) |
| | | { |
| | | AttributeType certAttrType = attributeMap.get(certAttrName); |
| | | mapValues.add(certAttrName + ":" + certAttrType.getNameOrOID()); |
| | | } |
| | | |
| | | int msgID = MSGID_SATUACM_DESCRIPTION_ATTR_MAP; |
| | | attrList.add(new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR_MAP, |
| | | getMessage(msgID), true, false, |
| | | false, mapValues)); |
| | | |
| | | LinkedList<DN> dnList = new LinkedList<DN>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | dnList.add(baseDN); |
| | | } |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_DESCRIPTION_BASE_DN; |
| | | attrList.add(new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false, |
| | | dnList)); |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an |
| | | * acceptable configuration for this component. If it does not, |
| | | * then detailed information about the problem(s) should be added to |
| | | * the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to |
| | | * make the determination. |
| | | * @param unacceptableReasons A list that can be used to hold |
| | | * messages about why the provided |
| | | * entry does not have an acceptable |
| | | * configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an |
| | | * acceptable configuration for this component, or |
| | | * <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration", |
| | | String.valueOf(configEntry), "java.util.List<String>"); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | boolean configAcceptable = true; |
| | | |
| | | |
| | | // Get the attribute that will be used to map subject attributes to user |
| | | // attributes. |
| | | LinkedHashMap<String,AttributeType> newAttributeMap = |
| | | new LinkedHashMap<String,AttributeType>(); |
| | | int msgID = MSGID_SATUACM_DESCRIPTION_ATTR_MAP; |
| | | StringConfigAttribute mapStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR_MAP, |
| | | getMessage(msgID), true, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute mapAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(mapStub); |
| | | if (mapAttr == null) |
| | | { |
| | | msgID = MSGID_SATUACM_NO_MAP_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR_MAP); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | else |
| | | { |
| | | mapLoop: |
| | | for (String mapStr : mapAttr.pendingValues()) |
| | | { |
| | | String lowerMap = toLowerCase(mapStr); |
| | | int colonPos = lowerMap.indexOf(':'); |
| | | if (colonPos <= 0) |
| | | { |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | continue; |
| | | } |
| | | |
| | | String certAttrName = lowerMap.substring(0, colonPos).trim(); |
| | | String userAttrName = lowerMap.substring(colonPos+1).trim(); |
| | | if ((certAttrName.length() == 0) || (userAttrName.length() == 0)) |
| | | { |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | continue; |
| | | } |
| | | |
| | | if (newAttributeMap.containsKey(certAttrName)) |
| | | { |
| | | msgID = MSGID_SATUACM_DUPLICATE_CERT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | certAttrName); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | continue; |
| | | } |
| | | |
| | | AttributeType userAttrType = |
| | | DirectoryServer.getAttributeType(userAttrName, false); |
| | | if (userAttrType == null) |
| | | { |
| | | msgID = MSGID_SATUACM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, mapStr, |
| | | String.valueOf(configEntryDN), |
| | | userAttrName); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | continue; |
| | | } |
| | | |
| | | for (AttributeType attrType : newAttributeMap.values()) |
| | | { |
| | | if (attrType.equals(userAttrType)) |
| | | { |
| | | msgID = MSGID_SATUACM_DUPLICATE_USER_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrType.getNameOrOID()); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | continue mapLoop; |
| | | } |
| | | } |
| | | |
| | | newAttributeMap.put(certAttrName, userAttrType); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e); |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_ATTR_MAP; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | DN[] newBaseDNs = null; |
| | | msgID = MSGID_SATUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | newBaseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(newBaseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e); |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained |
| | | * in the provided entry. Information about the result of this |
| | | * processing should be added to the provided message list. |
| | | * Information should always be added to this list if a |
| | | * configuration change could not be applied. If detailed results |
| | | * are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not |
| | | * changed) should also be included. |
| | | * |
| | | * @param configEntry The entry containing the new |
| | | * configuration to apply for this |
| | | * component. |
| | | * @param detailedResults Indicates whether detailed information |
| | | * about the processing should be added to |
| | | * the list. |
| | | * |
| | | * @return Information about the result of the configuration |
| | | * update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "applyNewConfiguration", |
| | | String.valueOf(configEntry), |
| | | String.valueOf(detailedResults)); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | boolean adminActionRequired = false; |
| | | |
| | | |
| | | // Get the attribute that will be used to map subject attributes to user |
| | | // attributes. |
| | | LinkedHashMap<String,AttributeType> newAttributeMap = |
| | | new LinkedHashMap<String,AttributeType>(); |
| | | int msgID = MSGID_SATUACM_DESCRIPTION_ATTR_MAP; |
| | | StringConfigAttribute mapStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR_MAP, |
| | | getMessage(msgID), true, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute mapAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(mapStub); |
| | | if (mapAttr == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_NO_MAP_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR_MAP)); |
| | | } |
| | | else |
| | | { |
| | | mapLoop: |
| | | for (String mapStr : mapAttr.pendingValues()) |
| | | { |
| | | String lowerMap = toLowerCase(mapStr); |
| | | int colonPos = lowerMap.indexOf(':'); |
| | | if (colonPos <= 0) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr)); |
| | | break; |
| | | } |
| | | |
| | | String certAttrName = lowerMap.substring(0, colonPos).trim(); |
| | | String userAttrName = lowerMap.substring(colonPos+1).trim(); |
| | | if ((certAttrName.length() == 0) || (userAttrName.length() == 0)) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_INVALID_MAP_FORMAT; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | mapStr)); |
| | | break; |
| | | } |
| | | |
| | | if (newAttributeMap.containsKey(certAttrName)) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_DUPLICATE_CERT_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | certAttrName)); |
| | | break; |
| | | } |
| | | |
| | | AttributeType userAttrType = |
| | | DirectoryServer.getAttributeType(userAttrName, false); |
| | | if (userAttrType == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.NO_SUCH_ATTRIBUTE; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_NO_SUCH_ATTR; |
| | | messages.add(getMessage(msgID, mapStr, |
| | | String.valueOf(configEntryDN), |
| | | userAttrName)); |
| | | break; |
| | | } |
| | | |
| | | for (AttributeType attrType : newAttributeMap.values()) |
| | | { |
| | | if (attrType.equals(userAttrType)) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_DUPLICATE_USER_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrType.getNameOrOID())); |
| | | break mapLoop; |
| | | } |
| | | } |
| | | |
| | | newAttributeMap.put(certAttrName, userAttrType); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "applyNewConfiguration", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_ATTR_MAP; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | DN[] newBaseDNs = null; |
| | | msgID = MSGID_SATUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | newBaseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(newBaseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "applyNewConfiguration", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | msgID = MSGID_SATUACM_CANNOT_GET_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | attributeMap = newAttributeMap; |
| | | baseDNs = newBaseDNs; |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.security.cert.Certificate; |
| | | import java.security.cert.X509Certificate; |
| | | import javax.security.auth.x500.X500Principal; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.api.CertificateMapper; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.types.SearchScope; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a very simple Directory Server certificate mapper that |
| | | * will map a certificate to a user only if that user's entry contains an |
| | | * attribute with the subject of the client certificate. There must be exactly |
| | | * one matching user entry for the mapping to be successful. |
| | | */ |
| | | public class SubjectDNToUserAttributeCertificateMapper |
| | | extends CertificateMapper |
| | | implements ConfigurableComponent |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class for debugging purposes. |
| | | */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.extensions.SubjectDNToUserAttributeCertificateMapper"; |
| | | |
| | | |
| | | |
| | | // The attribute type that will be used to map the certificate's subject. |
| | | private AttributeType subjectAttributeType; |
| | | |
| | | // The DN of the configuration entry for this certificate mapper. |
| | | private DN configEntryDN; |
| | | |
| | | // The set of base DNs below which the search will be performed. |
| | | private DN[] baseDNs; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this certificate mapper. Note that all actual |
| | | * initialization should be done in the |
| | | * <CODE>initializeCertificateMapper</CODE> method. |
| | | */ |
| | | public SubjectDNToUserAttributeCertificateMapper() |
| | | { |
| | | super(); |
| | | |
| | | assert debugConstructor(CLASS_NAME); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeCertificateMapper(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "initializeCertificateMapper", |
| | | String.valueOf(configEntry)); |
| | | |
| | | this.configEntryDN = configEntry.getDN(); |
| | | |
| | | // Get the attribute type that will be used to hold the certificate subject. |
| | | int msgID = MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | msgID = MSGID_SDTUACM_NO_SUBJECT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | subjectAttributeType = |
| | | DirectoryServer.getAttributeType(lowerName, false); |
| | | if (subjectAttributeType == null) |
| | | { |
| | | msgID = MSGID_SDTUACM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | } |
| | | } |
| | | catch (ConfigException ce) |
| | | { |
| | | throw ce; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_SUBJECT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | baseDNs = null; |
| | | msgID = MSGID_SDTUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | baseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(baseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "initializeCertificateMapper", e); |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeCertificateMapper() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "finalizeCertificateMapper"); |
| | | |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry mapCertificateToUser(Certificate[] certificateChain) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "mapCertificateToUser", |
| | | String.valueOf(certificateChain)); |
| | | |
| | | |
| | | // Make sure that a peer certificate was provided. |
| | | if ((certificateChain == null) || (certificateChain.length == 0)) |
| | | { |
| | | int msgID = MSGID_SDTUACM_NO_PEER_CERTIFICATE; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the first certificate in the chain. It must be an X.509 certificate. |
| | | X509Certificate peerCertificate; |
| | | try |
| | | { |
| | | peerCertificate = (X509Certificate) certificateChain[0]; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "mapCertificateToUser", e); |
| | | |
| | | int msgID = MSGID_SDTUACM_PEER_CERT_NOT_X509; |
| | | String message = |
| | | getMessage(msgID, String.valueOf(certificateChain[0].getType())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | |
| | | |
| | | // Get the subject from the peer certificate and use it to create a search |
| | | // filter. |
| | | X500Principal peerPrincipal = peerCertificate.getSubjectX500Principal(); |
| | | String peerName = peerPrincipal.getName(X500Principal.RFC2253); |
| | | AttributeValue value = new AttributeValue(subjectAttributeType, peerName); |
| | | SearchFilter filter = |
| | | SearchFilter.createEqualityFilter(subjectAttributeType, value); |
| | | |
| | | |
| | | // If we have an explicit set of base DNs, then use it. Otherwise, use the |
| | | // set of public naming contexts in the server. |
| | | DN[] bases = baseDNs; |
| | | if (bases == null) |
| | | { |
| | | bases = new DN[0]; |
| | | bases = DirectoryServer.getPublicNamingContexts().keySet().toArray(bases); |
| | | } |
| | | |
| | | |
| | | // For each base DN, issue an internal search in an attempt to map the |
| | | // certificate. |
| | | Entry userEntry = null; |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | for (DN baseDN : bases) |
| | | { |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(baseDN, SearchScope.WHOLE_SUBTREE, filter); |
| | | for (SearchResultEntry entry : searchOperation.getSearchEntries()) |
| | | { |
| | | if (userEntry == null) |
| | | { |
| | | userEntry = entry; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_SDTUACM_MULTIPLE_MATCHING_ENTRIES; |
| | | String message = getMessage(msgID, peerName, |
| | | String.valueOf(userEntry.getDN()), |
| | | String.valueOf(entry.getDN())); |
| | | throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, |
| | | msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then we either found exactly one user entry or we |
| | | // didn't find any. Either way, return the entry or null to the caller. |
| | | return userEntry; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this |
| | | * component is associated. |
| | | * |
| | | * @return The DN of the configuration entry with which this |
| | | * component is associated. |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN"); |
| | | |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | * |
| | | * @return The set of configuration attributes that are associated |
| | | * with this configurable component. |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getConfigurationAttributes"); |
| | | |
| | | LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); |
| | | |
| | | int msgID = MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR; |
| | | attrList.add(new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR, |
| | | getMessage(msgID), true, false, false, |
| | | subjectAttributeType.getNameOrOID())); |
| | | |
| | | LinkedList<DN> dnList = new LinkedList<DN>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | dnList.add(baseDN); |
| | | } |
| | | } |
| | | |
| | | msgID = MSGID_SDTUACM_DESCRIPTION_BASE_DN; |
| | | attrList.add(new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false, |
| | | dnList)); |
| | | |
| | | return attrList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an |
| | | * acceptable configuration for this component. If it does not, |
| | | * then detailed information about the problem(s) should be added to |
| | | * the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to |
| | | * make the determination. |
| | | * @param unacceptableReasons A list that can be used to hold |
| | | * messages about why the provided |
| | | * entry does not have an acceptable |
| | | * configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an |
| | | * acceptable configuration for this component, or |
| | | * <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration", |
| | | String.valueOf(configEntry), "java.util.List<String>"); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | boolean configAcceptable = true; |
| | | |
| | | |
| | | // Get the attribute type that will be used to hold the certificate subject. |
| | | int msgID = MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | msgID = MSGID_SDTUACM_NO_SUBJECT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName, false); |
| | | if (attrType == null) |
| | | { |
| | | msgID = MSGID_SDTUACM_NO_SUCH_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e); |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_SUBJECT_ATTR; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | msgID = MSGID_SDTUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e); |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_BASE_DN; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e)); |
| | | unacceptableReasons.add(message); |
| | | configAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained |
| | | * in the provided entry. Information about the result of this |
| | | * processing should be added to the provided message list. |
| | | * Information should always be added to this list if a |
| | | * configuration change could not be applied. If detailed results |
| | | * are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not |
| | | * changed) should also be included. |
| | | * |
| | | * @param configEntry The entry containing the new |
| | | * configuration to apply for this |
| | | * component. |
| | | * @param detailedResults Indicates whether detailed information |
| | | * about the processing should be added to |
| | | * the list. |
| | | * |
| | | * @return Information about the result of the configuration |
| | | * update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "applyNewConfiguration", |
| | | String.valueOf(configEntry), |
| | | String.valueOf(detailedResults)); |
| | | |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | boolean adminActionRequired = false; |
| | | |
| | | |
| | | // Get the attribute type that will be used to hold the certificate subject. |
| | | AttributeType newAttributeType = null; |
| | | int msgID = MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR; |
| | | StringConfigAttribute attrStub = |
| | | new StringConfigAttribute(ATTR_CERTIFICATE_SUBJECT_ATTR, |
| | | getMessage(msgID), true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute attrAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(attrStub); |
| | | if (attrAttr == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SDTUACM_NO_SUBJECT_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | ATTR_CERTIFICATE_SUBJECT_ATTR)); |
| | | } |
| | | else |
| | | { |
| | | String attrName = attrAttr.pendingValue(); |
| | | String lowerName = toLowerCase(attrName); |
| | | newAttributeType = DirectoryServer.getAttributeType(lowerName, false); |
| | | if (subjectAttributeType == null) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.NO_SUCH_ATTRIBUTE; |
| | | } |
| | | |
| | | msgID = MSGID_SDTUACM_NO_SUCH_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | attrName)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "applyNewConfiguration", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_SUBJECT_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the set of base DNs below which to perform the searches. |
| | | DN[] newBaseDNs = null; |
| | | msgID = MSGID_SDTUACM_DESCRIPTION_BASE_DN; |
| | | DNConfigAttribute baseStub = |
| | | new DNConfigAttribute(ATTR_CERTIFICATE_SUBJECT_BASEDN, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | DNConfigAttribute baseAttr = |
| | | (DNConfigAttribute) configEntry.getConfigAttribute(baseStub); |
| | | if (baseAttr != null) |
| | | { |
| | | List<DN> dnList = baseAttr.activeValues(); |
| | | newBaseDNs = new DN[dnList.size()]; |
| | | dnList.toArray(newBaseDNs); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "applyNewConfiguration", e); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_SDTUACM_CANNOT_GET_BASE_DN; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | subjectAttributeType = newAttributeType; |
| | | baseDNs = newBaseDNs; |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * subject attribute type attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 411; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configuration entry |
| | | * does not specify which attribute type should be used to hold certificate |
| | | * subjects. This takes two arguments, which are the DN of the configuration |
| | | * entry and the attribute type that should be used to specify the subject |
| | | * attribute. |
| | | */ |
| | | public static final int MSGID_SDTUACM_NO_SUBJECT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 412; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if subject attribute type |
| | | * does not exist in the server schema. This takes two arguments, which are |
| | | * the DN of the configuration entry and the name of the specified attribute |
| | | * type. |
| | | */ |
| | | public static final int MSGID_SDTUACM_NO_SUCH_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 413; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to determine the subject attribute type. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_SDTUACM_CANNOT_GET_SUBJECT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 414; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * search base DN attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SDTUACM_DESCRIPTION_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 415; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to determine the search base DN. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_SDTUACM_CANNOT_GET_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 416; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client did not |
| | | * present any certificate to the server. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SDTUACM_NO_PEER_CERTIFICATE = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 417; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client certificate |
| | | * was not an X.509 certificate. This takes a single argument, which is the |
| | | * name of the certificate format. |
| | | */ |
| | | public static final int MSGID_SDTUACM_PEER_CERT_NOT_X509 = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 418; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if multiple user entries |
| | | * matched the specified certificate subject. This takes three arguments, |
| | | * which are the certificate subject and the DNs of the first two users found |
| | | * to match that subject. |
| | | */ |
| | | public static final int MSGID_SDTUACM_MULTIPLE_MATCHING_ENTRIES = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 419; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * attribute map attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SATUACM_DESCRIPTION_ATTR_MAP = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 420; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configuration entry |
| | | * does not specify which attribute type should be used to map certificate |
| | | * attributes to user attributes. This takes two arguments, which are the DN |
| | | * of the configuration entry and the attribute type that should be used to |
| | | * specify the mapping. |
| | | */ |
| | | public static final int MSGID_SATUACM_NO_MAP_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 421; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an attribute map value |
| | | * has an invalid format. This takes two arguments, which are the DN of the |
| | | * configuration entry and the invalid map value. |
| | | */ |
| | | public static final int MSGID_SATUACM_INVALID_MAP_FORMAT = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 422; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if there are multiple |
| | | * mappings that target the same certificate attribute. This takes two |
| | | * arguments, which are the DN of the configuration entry and the name of the |
| | | * certificate attribute. |
| | | */ |
| | | public static final int MSGID_SATUACM_DUPLICATE_CERT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 423; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an attribute mapping |
| | | * references a user attribute that is not defined in the server schema. |
| | | * This takes two argumetns, which are the DN of the configuration entry and |
| | | * the name of the undefined user attribute. |
| | | */ |
| | | public static final int MSGID_SATUACM_NO_SUCH_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 424; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if there are multiple |
| | | * mappings that target the same user attribute. This takes two arguments, |
| | | * which are the DN of the configuration entry and the name of the user |
| | | * attribute. |
| | | */ |
| | | public static final int MSGID_SATUACM_DUPLICATE_USER_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 425; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * attempting to process the attribute mapping. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_SATUACM_CANNOT_GET_ATTR_MAP = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 426; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * search base DN attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SATUACM_DESCRIPTION_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 427; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * attempting to process the set of base DNs. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_SATUACM_CANNOT_GET_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 428; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client did not |
| | | * present any certificate to the server. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_SATUACM_NO_PEER_CERTIFICATE = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 429; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client certificate |
| | | * was not an X.509 certificate. This takes a single argument, which is the |
| | | * name of the certificate format. |
| | | */ |
| | | public static final int MSGID_SATUACM_PEER_CERT_NOT_X509 = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 430; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the peer certificate |
| | | * subject cannot be decoded as a DN. This takes two arguments, which are |
| | | * the peer certificate subject and a message explaining the problem that |
| | | * occurred. |
| | | */ |
| | | public static final int MSGID_SATUACM_CANNOT_DECODE_SUBJECT_AS_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 431; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if a peer certificate |
| | | * subject does not contain any mappable attributes. This takes a single |
| | | * argument, which is the peer certificate subject. |
| | | */ |
| | | public static final int MSGID_SATUACM_NO_MAPPABLE_ATTRIBUTES = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 432; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if multiple user entries |
| | | * matched the specified certificate subject. This takes three arguments, |
| | | * which are the certificate subject and the DNs of the first two users found |
| | | * to match that subject. |
| | | */ |
| | | public static final int MSGID_SATUACM_MULTIPLE_MATCHING_ENTRIES = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 433; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * fingerprint attribute type attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 434; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configuration entry |
| | | * does not specify which attribute type should be used to hold certificate |
| | | * fingerprints. This takes two arguments, which are the DN of the |
| | | * configuration entry and the attribute type that should be used to specify |
| | | * the fingerprint attribute. |
| | | */ |
| | | public static final int MSGID_FCM_NO_FINGERPRINT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 435; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the fingerprint |
| | | * attribute type does not exist in the server schema. This takes two |
| | | * arguments, which are the DN of the configuration entry and the name of the |
| | | * specified attribute type. |
| | | */ |
| | | public static final int MSGID_FCM_NO_SUCH_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 436; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to determine the fingerprint attribute type. This takes two |
| | | * arguments, which are the DN of the configuration entry and a string |
| | | * representation of the exception that was caught. |
| | | */ |
| | | public static final int MSGID_FCM_CANNOT_GET_FINGERPRINT_ATTR = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 437; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * fingerprint algorithm attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 438; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configuration entry |
| | | * does not specify which digest algorithm should be used to compute |
| | | * fingerprints. This takes two arguments, which are the DN of the |
| | | * configuration entry and the attribute type that should be used to specify |
| | | * the fingerprint algorithm. |
| | | */ |
| | | public static final int MSGID_FCM_NO_FINGERPRINT_ALGORITHM = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 439; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to determine the fingerprint algorithm. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_FCM_CANNOT_GET_FINGERPRINT_ALGORITHM = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 440; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used as the description for the |
| | | * search base DN attribute. It does not take any arguments. |
| | | */ |
| | | public static final int MSGID_FCM_DESCRIPTION_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 441; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to determine the search base DN. This takes two arguments, |
| | | * which are the DN of the configuration entry and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_FCM_CANNOT_GET_BASE_DN = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 442; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client did not |
| | | * present any certificate to the server. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_FCM_NO_PEER_CERTIFICATE = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 443; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the client certificate |
| | | * was not an X.509 certificate. This takes a single argument, which is the |
| | | * name of the certificate format. |
| | | */ |
| | | public static final int MSGID_FCM_PEER_CERT_NOT_X509 = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 444; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * attempting to compute the fingerprint for a certificate. This takes two |
| | | * arguments, which are the certificate subject and a string representation of |
| | | * the exception that was caught. |
| | | */ |
| | | public static final int MSGID_FCM_CANNOT_CALCULATE_FINGERPRINT = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 445; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if multiple user entries |
| | | * matched the specified certificate fingerprint. This takes three arguments, |
| | | * which are the certificate fingerprint and the DNs of the first two users |
| | | * found to match that fingerprint. |
| | | */ |
| | | public static final int MSGID_FCM_MULTIPLE_MATCHING_ENTRIES = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 446; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | "Cannot remove user %s as a member of static group %s " + |
| | | "because an error occurred while attempting to perform " + |
| | | "an internal modification to update the group: %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_SDTUACM_DESCRIPTION_SUBJECT_ATTR, |
| | | "Specifies the name of the attribute type in user " + |
| | | "entries that contains the subjects of the certificates " + |
| | | "held by that user. Changes to this configuration " + |
| | | "attribute will take effect immediately."); |
| | | registerMessage(MSGID_SDTUACM_NO_SUBJECT_ATTR, |
| | | "Configuration entry %s does not contain required " + |
| | | "attribute %s, which is used to specify which attribute " + |
| | | "should contain the subjects of the certificates held " + |
| | | "by users."); |
| | | registerMessage(MSGID_SDTUACM_NO_SUCH_ATTR, |
| | | "Configuration entry %s indicates that certificate " + |
| | | "subjects should be held in attribute %s, but this " + |
| | | "attribute is not defined in the server schema."); |
| | | registerMessage(MSGID_SDTUACM_CANNOT_GET_SUBJECT_ATTR, |
| | | "An error occurred while attempting to determine which " + |
| | | "attribute type should be used to hold certificate " + |
| | | "subjects from configuration entry %s: %s."); |
| | | registerMessage(MSGID_SDTUACM_DESCRIPTION_BASE_DN, |
| | | "Specifies the base DNs below which the searches to " + |
| | | "find matching user entries will be performed. If no " + |
| | | "base DN(s) are provided, then the server will search " + |
| | | "below all public naming contexts. Changes to this " + |
| | | "configuration attribute will take effect immediately."); |
| | | registerMessage(MSGID_SDTUACM_CANNOT_GET_BASE_DN, |
| | | "An error occurred while attempting to determine the " + |
| | | "search base DN(s) from configuration entry %s: %s."); |
| | | registerMessage(MSGID_SDTUACM_NO_PEER_CERTIFICATE, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "entry because no peer certificate was available."); |
| | | registerMessage(MSGID_SDTUACM_PEER_CERT_NOT_X509, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "because the peer certificate was not an X.509 " + |
| | | "certificate (peer certificate format was %s)."); |
| | | registerMessage(MSGID_SDTUACM_MULTIPLE_MATCHING_ENTRIES, |
| | | "The certificate with subject %s could not be mapped to " + |
| | | "exactly one user. It maps to both %s and %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_SATUACM_DESCRIPTION_ATTR_MAP, |
| | | "Specifies the name of the attribute type in user " + |
| | | "entries that defines the mapping between attributes " + |
| | | "in certificate subjects and attributes in user " + |
| | | "entries. Values should be in the form " + |
| | | "'certattr:userattr'. Changes to this configuration " + |
| | | "attribute will take effect immediately."); |
| | | registerMessage(MSGID_SATUACM_NO_MAP_ATTR, |
| | | "Configuration entry %s does not contain required " + |
| | | "attribute %s, which is used to specify the mappings " + |
| | | "between attributes in certificate subjects and " + |
| | | "attributes in user entries."); |
| | | registerMessage(MSGID_SATUACM_INVALID_MAP_FORMAT, |
| | | "Configuration entry %s has value '%s' which violates " + |
| | | "the format required for attribute mappings. The " + |
| | | "expected format is 'certattr:userattr'."); |
| | | registerMessage(MSGID_SATUACM_DUPLICATE_CERT_ATTR, |
| | | "Configuration entry %s contains multiple mappings " + |
| | | "for certificate attribute %s."); |
| | | registerMessage(MSGID_SATUACM_NO_SUCH_ATTR, |
| | | "Mapping %s in configuration entry %s references " + |
| | | "attribute %s which is not defined in the server schema."); |
| | | registerMessage(MSGID_SATUACM_DUPLICATE_USER_ATTR, |
| | | "Configuration entry %s contains multiple mappings " + |
| | | "for user attribute %s."); |
| | | registerMessage(MSGID_SATUACM_CANNOT_GET_ATTR_MAP, |
| | | "An error occurred while attempting to determine the set " + |
| | | "of attribute mappings from configuration entry %s: %s."); |
| | | registerMessage(MSGID_SATUACM_DESCRIPTION_BASE_DN, |
| | | "Specifies the base DNs below which the searches to " + |
| | | "find matching user entries will be performed. If no " + |
| | | "base DN(s) are provided, then the server will search " + |
| | | "below all public naming contexts. Changes to this " + |
| | | "configuration attribute will take effect immediately."); |
| | | registerMessage(MSGID_SATUACM_CANNOT_GET_BASE_DN, |
| | | "An error occurred while attempting to determine the " + |
| | | "search base DN(s) from configuration entry %s: %s."); |
| | | registerMessage(MSGID_SATUACM_NO_PEER_CERTIFICATE, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "entry because no peer certificate was available."); |
| | | registerMessage(MSGID_SATUACM_PEER_CERT_NOT_X509, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "because the peer certificate was not an X.509 " + |
| | | "certificate (peer certificate format was %s)."); |
| | | registerMessage(MSGID_SATUACM_CANNOT_DECODE_SUBJECT_AS_DN, |
| | | "Unable to decode peer certificate subject %s as a DN: " + |
| | | "%s."); |
| | | registerMessage(MSGID_SATUACM_NO_MAPPABLE_ATTRIBUTES, |
| | | "Peer certificate subject %s does not contain any " + |
| | | "attributes for which a mapping has been established."); |
| | | registerMessage(MSGID_SATUACM_MULTIPLE_MATCHING_ENTRIES, |
| | | "The certificate with subject %s could not be mapped to " + |
| | | "exactly one user. It maps to both %s and %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_FCM_DESCRIPTION_FINGERPRINT_ATTR, |
| | | "Specifies the name of the attribute type in user " + |
| | | "entries that contains the fingerprints of the " + |
| | | "certificates held by that user. Changes to this " + |
| | | "configuration attribute will take effect immediately."); |
| | | registerMessage(MSGID_FCM_NO_FINGERPRINT_ATTR, |
| | | "Configuration entry %s does not contain required " + |
| | | "attribute %s, which is used to specify which attribute " + |
| | | "should contain the fingerprints of the certificates " + |
| | | "held by users."); |
| | | registerMessage(MSGID_FCM_NO_SUCH_ATTR, |
| | | "Configuration entry %s indicates that certificate " + |
| | | "fingerprints should be held in attribute %s, but this " + |
| | | "attribute is not defined in the server schema."); |
| | | registerMessage(MSGID_FCM_CANNOT_GET_FINGERPRINT_ATTR, |
| | | "An error occurred while attempting to determine which " + |
| | | "attribute type should be used to hold certificate " + |
| | | "fingerprints from configuration entry %s: %s."); |
| | | registerMessage(MSGID_FCM_DESCRIPTION_FINGERPRINT_ALGORITHM, |
| | | "Specifies the name of the digest algorithm used for " + |
| | | "the certificate fingerprints. The value should be " + |
| | | "either 'MD5' or 'SHA1'. Changes to this configuration " + |
| | | "attribute will take effect immediately."); |
| | | registerMessage(MSGID_FCM_NO_FINGERPRINT_ALGORITHM, |
| | | "Configuration entry %s does not contain required " + |
| | | "attribute %s, which is used to specify which digest " + |
| | | "algorithm should be used to compute certificate " + |
| | | "fingerprints."); |
| | | registerMessage(MSGID_FCM_CANNOT_GET_FINGERPRINT_ALGORITHM, |
| | | "An error occurred while attempting to determine the " + |
| | | "digest algorithm from configuration entry %s: %s."); |
| | | registerMessage(MSGID_FCM_DESCRIPTION_BASE_DN, |
| | | "Specifies the base DNs below which the searches to " + |
| | | "find matching user entries will be performed. If no " + |
| | | "base DN(s) are provided, then the server will search " + |
| | | "below all public naming contexts. Changes to this " + |
| | | "configuration attribute will take effect immediately."); |
| | | registerMessage(MSGID_FCM_CANNOT_GET_BASE_DN, |
| | | "An error occurred while attempting to determine the " + |
| | | "search base DN(s) from configuration entry %s: %s."); |
| | | registerMessage(MSGID_FCM_NO_PEER_CERTIFICATE, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "entry because no peer certificate was available."); |
| | | registerMessage(MSGID_FCM_PEER_CERT_NOT_X509, |
| | | "Could not map the provided certificate chain to a user " + |
| | | "because the peer certificate was not an X.509 " + |
| | | "certificate (peer certificate format was %s)."); |
| | | registerMessage(MSGID_FCM_CANNOT_CALCULATE_FINGERPRINT, |
| | | "An error occurred while attempting to calculate the " + |
| | | "fingerprint for the peer certificate with subject %s: " + |
| | | "%s."); |
| | | registerMessage(MSGID_FCM_MULTIPLE_MATCHING_ENTRIES, |
| | | "The certificate with fingerprint %s could not be mapped " + |
| | | "to exactly one user. It maps to both %s and %s."); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * Retrieves a string representation of the contents of the provided byte |
| | | * array using hexadecimal characters and a colon between each byte. |
| | | * |
| | | * @param b The byte array containing the data. |
| | | * |
| | | * @return A string representation of the contents of the provided byte |
| | | * array using hexadecimal characters. |
| | | */ |
| | | public static String bytesToColonDelimitedHex(byte[] b) |
| | | { |
| | | if ((b == null) || (b.length == 0)) |
| | | { |
| | | return ""; |
| | | } |
| | | |
| | | int arrayLength = b.length; |
| | | StringBuilder buffer = new StringBuilder((arrayLength - 1) * 3 + 2); |
| | | buffer.append(byteToHex(b[0])); |
| | | |
| | | for (int i=1; i < arrayLength; i++) |
| | | { |
| | | buffer.append(":"); |
| | | buffer.append(byteToHex(b[i])); |
| | | } |
| | | |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a string representation of the contents of the provided byte |
| | | * buffer using hexadecimal characters and a space between each byte. |
| | | * |
| | | * @param b The byte buffer containing the data. |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.tools.LDAPSearch; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.ModificationType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the fingerprint certificate mapper. |
| | | */ |
| | | public class FingerprintCertificateMapperTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of invalid configurations that cannot be used to |
| | | * initialize the certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "invalidConfigs") |
| | | public Object[][] getInvalidConfigurations() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | "dn: cn=No Fingerprint Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-fingerprint-certificate-mapper", |
| | | "cn: No Fingerprint Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "FingerprintCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-fingerprint-algorithm: MD5", |
| | | "", |
| | | "dn: cn=Undefined Fingerprint Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-fingerprint-certificate-mapper", |
| | | "cn: Undefined Fingerprint Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "FingerprintCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-fingerprint-attribute-type: undefined", |
| | | "ds-cfg-certificate-fingerprint-algorithm: MD5", |
| | | "", |
| | | "dn: cn=No Fingerprint Algorithm,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-fingerprint-certificate-mapper", |
| | | "cn: No Fingerprint Algorithm", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "FingerprintCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-fingerprint-attribute-type: " + |
| | | "ds-certificate-fingerprint", |
| | | "", |
| | | "dn: cn=Invalid Fingerprint Algorithm,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-fingerprint-certificate-mapper", |
| | | "cn: Invalid Fingerprint Algorithm", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "FingerprintCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-fingerprint-attribute-type: " + |
| | | "ds-certificate-fingerprint", |
| | | "ds-cfg-certificate-fingerprint-algorithm: invalid", |
| | | "", |
| | | "dn: cn=Invalid Base DN,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-fingerprint-certificate-mapper", |
| | | "cn: Invalid Base DN", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "FingerprintCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-fingerprint-attribute-type: " + |
| | | "ds-certificate-fingerprint", |
| | | "ds-cfg-certificate-fingerprint-algorithm: MD5", |
| | | "ds-cfg-certificate-user-base-dn: invalid"); |
| | | |
| | | |
| | | Object[][] configEntries = new Object[entries.size()][1]; |
| | | for (int i=0; i < configEntries.length; i++) |
| | | { |
| | | configEntries[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return configEntries; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests initialization with an invalid configuration. |
| | | * |
| | | * @param e The configuration entry to use to initialize the certificate |
| | | * mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "invalidConfigs", |
| | | expectedExceptions = { ConfigException.class, |
| | | InitializationException.class }) |
| | | public void testInvalidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | DN parentDN = DN.decode("cn=Certificate Mappers,cn=config"); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | ConfigEntry configEntry = new ConfigEntry(e, parentEntry); |
| | | |
| | | FingerprintCertificateMapper mapper = new FingerprintCertificateMapper(); |
| | | mapper.initializeCertificateMapper(configEntry); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using the default configuration. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingDefaultConfig() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "ds-certificate-fingerprint: " + |
| | | "07:5A:AB:4B:E1:DD:E3:05:83:C0:FE:5F:A3:E8:1E:EB"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using the SHA-1 digest algorithm.. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingSHA1() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setFingerprintAlgorithm("SHA1"); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "ds-certificate-fingerprint: " + |
| | | "CB:A4:C7:A0:46:1F:44:88:12:23:56:49:F9:54:F4:37:E1:9F:9F:A4"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setFingerprintAlgorithm("MD5"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping due to no matching entries. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingNoMatchingEntries() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping due to multiple matching entries. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingMultipleMatchingEntries() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntries( |
| | | "dn: uid=test.user1,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user1", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User 1", |
| | | "ds-certificate-fingerprint: " + |
| | | "07:5A:AB:4B:E1:DD:E3:05:83:C0:FE:5F:A3:E8:1E:EB", |
| | | "", |
| | | "dn: uid=test.user2,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User 2", |
| | | "ds-certificate-fingerprint: " + |
| | | "07:5A:AB:4B:E1:DD:E3:05:83:C0:FE:5F:A3:E8:1E:EB"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to remove the fingerprint attribute will |
| | | * fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testRemoveFingerprintAttribute() |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | Attribute a = |
| | | new Attribute(DirectoryServer.getAttributeType( |
| | | "ds-cfg-certificate-fingerprint-attribute-type")); |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.DELETE, a)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to remove the fingerprint algorithm will |
| | | * fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testRemoveFingerprintAlgorithm() |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | Attribute a = |
| | | new Attribute(DirectoryServer.getAttributeType( |
| | | "ds-cfg-certificate-fingerprint-algorithm")); |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.DELETE, a)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an undefined fingerprint attribute |
| | | * will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetUndefinedFingerprintAttribute() |
| | | throws Exception |
| | | { |
| | | setFingerprintAttribute("undefined"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an undefined fingerprint algorithm |
| | | * will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetUndefinedFingerprintAlgorithm() |
| | | throws Exception |
| | | { |
| | | setFingerprintAlgorithm("undefined"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an invalid base DN will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetInvalidBaseDN() |
| | | throws Exception |
| | | { |
| | | setBaseDNs(new String[] { "invalid" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject DN to User Attribute certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void enableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject Equals DN certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void disableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = "cn=Subject Equals DN,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the fingerprint certificate mapper so that it |
| | | * will look for the fingerprint in the specified attribute. |
| | | * |
| | | * @param attrName The name of the attribute in which to look for the |
| | | * certificate subject. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setFingerprintAttribute(String attrName) |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-fingerprint-attribute-type", |
| | | attrName))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the fingerprint certificate mapper so that it |
| | | * will use the specified fingerprint algorithm. |
| | | * |
| | | * @param algorithm The name of the fingerprint algorithm to use. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setFingerprintAlgorithm(String algorithm) |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-fingerprint-algorithm", |
| | | algorithm))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the Subject DN to User Attribute certificate |
| | | * mapper so that it will look for the subject DN below the specified set of |
| | | * base DNs. |
| | | * |
| | | * @param baseDNs The set of base DNs to use when mapping certificates to |
| | | * users. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setBaseDNs(String[] baseDNs) |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Fingerprint Mapper,cn=Certificate Mappers,cn=config"; |
| | | |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType("ds-cfg-certificate-user-base-dn"); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (String baseDN : baseDNs) |
| | | { |
| | | values.add(new AttributeValue(attrType, baseDN)); |
| | | } |
| | | } |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute(attrType, attrType.getNameOrOID(), |
| | | values))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | } |
| | | |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.tools.LDAPSearch; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.ModificationType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the Subject Attribute to User Attribute certificate |
| | | * mapper. |
| | | */ |
| | | public class SubjectAttributeToUserAttributeCertificateMapperTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of invalid configurations that cannot be used to |
| | | * initialize the certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "invalidConfigs") |
| | | public Object[][] getInvalidConfigurations() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | "dn: cn=No Map Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: No Map Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "", |
| | | "dn: cn=No Map Colon,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: No Map Colon", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: nomapcolon", |
| | | "", |
| | | "dn: cn=No Map Cert Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: No Map Cert Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: :cn", |
| | | "", |
| | | "dn: cn=No Map User Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: No Map User Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:", |
| | | "", |
| | | "dn: cn=Undefined User Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: Undefined User Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:undefined", |
| | | "", |
| | | "dn: cn=Duplicate Cert Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: Duplicate Cert Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:cn", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:sn", |
| | | "", |
| | | "dn: cn=Duplicate User Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: Duplicate User Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:cn", |
| | | "ds-cfg-certificate-subject-attribute-mapping: e:cn", |
| | | "", |
| | | "dn: cn=Invalid Base DN,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: " + |
| | | "ds-cfg-subject-attribute-to-user-attribute-certificate-mapper", |
| | | "cn: Invalid Base DN", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectAttributeToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-mapping: cn:cn", |
| | | "ds-cfg-certificate-user-base-dn: invalid"); |
| | | |
| | | |
| | | Object[][] configEntries = new Object[entries.size()][1]; |
| | | for (int i=0; i < configEntries.length; i++) |
| | | { |
| | | configEntries[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return configEntries; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests initialization with an invalid configuration. |
| | | * |
| | | * @param e The configuration entry to use to initialize the certificate |
| | | * mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "invalidConfigs", |
| | | expectedExceptions = { ConfigException.class, |
| | | InitializationException.class }) |
| | | public void testInvalidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | DN parentDN = DN.decode("cn=Certificate Mappers,cn=config"); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | ConfigEntry configEntry = new ConfigEntry(e, parentEntry); |
| | | |
| | | SubjectAttributeToUserAttributeCertificateMapper mapper = |
| | | new SubjectAttributeToUserAttributeCertificateMapper(); |
| | | mapper.initializeCertificateMapper(configEntry); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using the default configuration. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingDefaultConfig() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping with multiple attributes. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingMultipleAttributes() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setAttributeMappings(new String[] { "cn:cn", "o:o" }); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "o: test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setAttributeMappings(new String[] { "cn:cn", "e:mail" }); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping due to no mappable attributes in the certificate. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedNoMappableAttributes() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setAttributeMappings(new String[] { "e:mail" }); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "o: test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, System.err) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setAttributeMappings(new String[] { "cn:cn", "e:mail" }); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping due to no matching users. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingNoMatchingUsers() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Not Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping due to multiple matching users. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingMultipleMatchingUsers() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntries( |
| | | "dn: uid=test.user1,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user1", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "", |
| | | "dn: uid=test.user2,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping when there are no users below the configured base |
| | | * DNs that match the criteria. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingNoUserBelowBaseDNs() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setBaseDNs(new String[] { "dc=example,dc=com" }); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntries( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setBaseDNs(null); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to remove the subject attribute will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testRemoveMapAttribute() |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Subject Attribute to User Attribute," + |
| | | "cn=Certificate Mappers,cn=config"; |
| | | |
| | | Attribute a = |
| | | new Attribute(DirectoryServer.getAttributeType( |
| | | "ds-cfg-certificate-subject-attribute-mapping")); |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.DELETE, a)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with no colon |
| | | * will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingNoColon() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { "nocolon" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with no cert |
| | | * attribute will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingNoCertAttribute() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { ":cn" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with no user |
| | | * attribute will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingNoUserAttribute() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { "cn:" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with an |
| | | * undefined user attribute will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingUndefinedUserAttribute() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { "cn:undefined" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with a |
| | | * duplicate cert attribute mapping will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingDuplicateCertAttribute() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { "cn:cn", "cn:sn" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an attribute mapping with a |
| | | * duplicate user attribute mapping will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetMappingDuplicateUserAttribute() |
| | | throws Exception |
| | | { |
| | | setAttributeMappings(new String[] { "cn:cn", "e:cn" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an invalid base DN will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetInvalidBaseDN() |
| | | throws Exception |
| | | { |
| | | setBaseDNs(new String[] { "invalid" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject Attribute to User Attribute certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void enableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = "cn=Subject Attribute to User Attribute," + |
| | | "cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject Equals DN certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void disableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = "cn=Subject Equals DN,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the Subject Attribute to User Attribute |
| | | * certificate mapper so that it will use the specified set of mappings. |
| | | * |
| | | * @param mappings The specified set of mappings to use. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setAttributeMappings(String[] mappings) |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Subject Attribute to User Attribute," + |
| | | "cn=Certificate Mappers,cn=config"; |
| | | |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType( |
| | | "ds-cfg-certificate-subject-attribute-mapping"); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | if (mappings != null) |
| | | { |
| | | for (String mapping : mappings) |
| | | { |
| | | values.add(new AttributeValue(attrType, mapping)); |
| | | } |
| | | } |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute(attrType, attrType.getNameOrOID(), |
| | | values))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the Subject Attribute to User Attribute |
| | | * certificate mapper so that it will look for matches below the specified set |
| | | * of base DNs. |
| | | * |
| | | * @param baseDNs The set of base DNs to use when mapping certificates to |
| | | * users. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setBaseDNs(String[] baseDNs) |
| | | throws Exception |
| | | { |
| | | String mapperDN = "cn=Subject Attribute to User Attribute," + |
| | | "cn=Certificate Mappers,cn=config"; |
| | | |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType("ds-cfg-certificate-user-base-dn"); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (String baseDN : baseDNs) |
| | | { |
| | | values.add(new AttributeValue(attrType, baseDN)); |
| | | } |
| | | } |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute(attrType, attrType.getNameOrOID(), |
| | | values))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | } |
| | | |
| 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 |
| | | * |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.tools.LDAPSearch; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.ModificationType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the Subject DN to User Attribute certificate mapper. |
| | | */ |
| | | public class SubjectDNToUserAttributeCertificateMapperTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of invalid configurations that cannot be used to |
| | | * initialize the certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "invalidConfigs") |
| | | public Object[][] getInvalidConfigurations() |
| | | throws Exception |
| | | { |
| | | List<Entry> entries = TestCaseUtils.makeEntries( |
| | | "dn: cn=No Subject Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-subject-dn-to-user-attribute-certificate-mapper", |
| | | "cn: No Subject Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectDNToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "", |
| | | "dn: cn=Undefined Subject Attr,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-subject-dn-to-user-attribute-certificate-mapper", |
| | | "cn: Undefined Subject Attr", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectDNToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-type: undefined", |
| | | "", |
| | | "dn: cn=Invalid Base DN,cn=Certificate Mappers,cn=config", |
| | | "objectClass: top", |
| | | "objectClass: ds-cfg-certificate-mapper", |
| | | "objectClass: ds-cfg-subject-dn-to-user-attribute-certificate-mapper", |
| | | "cn: Invalid Base DN", |
| | | "ds-cfg-certificate-mapper-class: org.opends.server.extensions." + |
| | | "SubjectDNToUserAttributeCertificateMapper", |
| | | "ds-cfg-certificate-mapper-enabled: true", |
| | | "ds-cfg-certificate-subject-attribute-type: ds-certificate-subject-dn", |
| | | "ds-cfg-certificate-user-base-dn: invalid"); |
| | | |
| | | |
| | | Object[][] configEntries = new Object[entries.size()][1]; |
| | | for (int i=0; i < configEntries.length; i++) |
| | | { |
| | | configEntries[i] = new Object[] { entries.get(i) }; |
| | | } |
| | | |
| | | return configEntries; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests initialization with an invalid configuration. |
| | | * |
| | | * @param e The configuration entry to use to initialize the certificate |
| | | * mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "invalidConfigs", |
| | | expectedExceptions = { ConfigException.class, |
| | | InitializationException.class }) |
| | | public void testInvalidConfigs(Entry e) |
| | | throws Exception |
| | | { |
| | | DN parentDN = DN.decode("cn=Certificate Mappers,cn=config"); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | ConfigEntry configEntry = new ConfigEntry(e, parentEntry); |
| | | |
| | | SubjectDNToUserAttributeCertificateMapper mapper = |
| | | new SubjectDNToUserAttributeCertificateMapper(); |
| | | mapper.initializeCertificateMapper(configEntry); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using the default configuration. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingDefaultConfig() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "ds-certificate-subject-dn: CN=Test User, O=Test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using a configuration with a different subject |
| | | * attribute. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingAlternateSubjectAttribute() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setSubjectAttribute("manager"); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "manager: CN=Test User, O=Test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setSubjectAttribute("ds-certificate-subject-dn"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a successful mapping using a configuration with a different set of |
| | | * base DNs. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSuccessfulMappingAlternateBaseDNs() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setBaseDNs(new String[] { "o=test" }); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "ds-certificate-subject-dn: CN=Test User, O=Test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setSubjectAttribute("ds-certificate-subject-dn"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping when there are no users that should match. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingNoUsers() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntry( |
| | | "dn: cn=Test User,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping when there are multiple users that match the |
| | | * critieria. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingMultipleUsers() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntries( |
| | | "dn: uid=test.user1,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user1", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User 1", |
| | | "ds-certificate-subject-dn: CN=Test User, O=Test", |
| | | "", |
| | | "dn: uid=test.user2,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User 2", |
| | | "ds-certificate-subject-dn: CN=Test User, O=Test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests a failed mapping when there are no users below the configured base |
| | | * DNs that match the criteria. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testFailedMappingNoUserBelowBaseDNs() |
| | | throws Exception |
| | | { |
| | | enableMapper(); |
| | | |
| | | try |
| | | { |
| | | setBaseDNs(new String[] { "dc=example,dc=com" }); |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.addEntries( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "objectClass: ds-certificate-user", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "ds-certificate-subject-dn: CN=Test User, O=Test"); |
| | | |
| | | |
| | | |
| | | String keyStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.keystore"; |
| | | String trustStorePath = DirectoryServer.getServerRoot() + File.separator + |
| | | "config" + File.separator + "client.truststore"; |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()), |
| | | "-Z", |
| | | "-K", keyStorePath, |
| | | "-W", "password", |
| | | "-P", trustStorePath, |
| | | "-r", |
| | | "-b", "", |
| | | "-s", "base", |
| | | "(objectClass=*)" |
| | | }; |
| | | |
| | | assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); |
| | | } |
| | | finally |
| | | { |
| | | disableMapper(); |
| | | setBaseDNs(null); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to remove the subject attribute will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testRemoveSubjectAttribute() |
| | | throws Exception |
| | | { |
| | | String mapperDN = |
| | | "cn=Subject DN to User Attribute,cn=Certificate Mappers,cn=config"; |
| | | |
| | | Attribute a = |
| | | new Attribute(DirectoryServer.getAttributeType( |
| | | "ds-cfg-certificate-subject-attribute-type")); |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.DELETE, a)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertFalse(modifyOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an undefined subject attribute will |
| | | * fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetUndefinedSubjectAttribute() |
| | | throws Exception |
| | | { |
| | | setSubjectAttribute("undefined"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests to ensure that an attmept to set an invalid base DN will fail. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { AssertionError.class }) |
| | | public void testSetInvalidBaseDN() |
| | | throws Exception |
| | | { |
| | | setBaseDNs(new String[] { "invalid" }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject DN to User Attribute certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void enableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = |
| | | "cn=Subject DN to User Attribute,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the SASL EXTERNAL mechanism handler so that it |
| | | * uses the Subject Equals DN certificate mapper. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void disableMapper() |
| | | throws Exception |
| | | { |
| | | String externalDN = "cn=EXTERNAL,cn=SASL Mechanisms,cn=config"; |
| | | String mapperDN = "cn=Subject Equals DN,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-mapper-dn", |
| | | mapperDN))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(externalDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the Subject DN to User Attribute certificate |
| | | * mapper so that it will look for the subject DN in the specified attribute. |
| | | * |
| | | * @param attrName The name of the attribute in which to look for the |
| | | * certificate subject. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setSubjectAttribute(String attrName) |
| | | throws Exception |
| | | { |
| | | String mapperDN = |
| | | "cn=Subject DN to User Attribute,cn=Certificate Mappers,cn=config"; |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute("ds-cfg-certificate-subject-attribute-type", |
| | | attrName))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Alters the configuration of the Subject DN to User Attribute certificate |
| | | * mapper so that it will look for the subject DN below the specified set of |
| | | * base DNs. |
| | | * |
| | | * @param baseDNs The set of base DNs to use when mapping certificates to |
| | | * users. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void setBaseDNs(String[] baseDNs) |
| | | throws Exception |
| | | { |
| | | String mapperDN = |
| | | "cn=Subject DN to User Attribute,cn=Certificate Mappers,cn=config"; |
| | | |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType("ds-cfg-certificate-user-base-dn"); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | if (baseDNs != null) |
| | | { |
| | | for (String baseDN : baseDNs) |
| | | { |
| | | values.add(new AttributeValue(attrType, baseDN)); |
| | | } |
| | | } |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<Modification>(); |
| | | mods.add(new Modification(ModificationType.REPLACE, |
| | | new Attribute(attrType, attrType.getNameOrOID(), |
| | | values))); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modifyOperation = |
| | | conn.processModify(DN.decode(mapperDN), mods); |
| | | assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | } |
| | | |