opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -57,6 +57,9 @@ import javax.naming.ldap.Control; import javax.naming.ldap.LdapContext; import org.opends.server.types.CryptoManager; import org.opends.server.config.ConfigConstants; /** * Class used to update and read the contents of the Administration Data. */ @@ -169,13 +172,15 @@ /** * The unique name of the instance key public-key certificate. */ INSTANCE_KEY_ID("ds-cfg-key-id", ADSPropertySyntax.STRING), INSTANCE_KEY_ID(ConfigConstants.ATTR_CRYPTO_KEY_ID, ADSPropertySyntax.STRING), /** * The instance key-pair public-key certificate. Note: This attribute * belongs to an instance key entry, separate from the server entry and * named by the ds-cfg-key-id attribute from the server entry. */ INSTANCE_PUBLIC_KEY_CERTIFICATE("ds-cfg-public-key-certificate"/*;binary*/, INSTANCE_PUBLIC_KEY_CERTIFICATE( ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE/*binary*/, ADSPropertySyntax.CERTIFICATE_BINARY); private String attrName; @@ -431,7 +436,7 @@ throw new ADSContextException( ADSContextException.ErrorType.ALREADY_REGISTERED); } catch (NamingException x) catch (Exception x) { throw new ADSContextException( ADSContextException.ErrorType.ERROR_UNEXPECTED, x); @@ -476,7 +481,7 @@ throw new ADSContextException( ADSContextException.ErrorType.NOT_YET_REGISTERED); } catch (NamingException x) catch (Exception x) { throw new ADSContextException( ADSContextException.ErrorType.ERROR_UNEXPECTED, x); @@ -2048,7 +2053,7 @@ Returns the parent entry of the server key entries in ADS. @return the parent entry of the server key entries in ADS. */ private static String getInstanceKeysContainerDN() public static String getInstanceKeysContainerDN() { return "cn=instance keys," + getAdministrationSuffixDN(); } @@ -2064,11 +2069,14 @@ the instance key entry belongs. @param serverEntryDn The server's ADS entry DN. @throws NamingException In case some JNDI operation fails. @throws CryptoManager.CryptoManagerException In case there is a problem getting the instance public key certificate ID. */ private void registerInstanceKeyCertificate( Map<ServerProperty, Object> serverProperties, LdapName serverEntryDn) throws NamingException { LdapName serverEntryDn) throws NamingException, CryptoManager.CryptoManagerException { assert serverProperties.containsKey( ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE); if (! serverProperties.containsKey( @@ -2117,7 +2125,9 @@ else { /* create key ID, if it was not supplied in serverProperties */ if (null == keyID) { keyID = java.util.UUID.randomUUID().toString(); keyID = CryptoManager.getInstanceKeyID( (byte[])serverProperties.get( ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)); keyAttrs.put(new BasicAttribute( ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID)); } @@ -2142,18 +2152,29 @@ public-key certificate entries in ADS. @return The set of valid (i.e., not tagged as compromised) instance key-pair public-key certificate entries in ADS represented as a Map from ds-cfg-key-id value to ds-cfg-public-key-certificate;binary value Note that the collection value to ds-cfg-public-key-certificate;binary value. Note that the collection might be empty. @throws ADSContextException in case of problems with the entry search. @see org.opends.server.types.CryptoManager#getTrustedCertificates */ public Map<String,byte[]> getTrustedCertificates() throws ADSContextException { Map<String, byte[]> keyEntryMap = new HashMap<String, byte[]>(); final Map<String, byte[]> certificateMap = new HashMap<String, byte[]>(); final String baseDNStr = getInstanceKeysContainerDN(); try { final LdapName baseDN = new LdapName(getInstanceKeysContainerDN()); final String searchFilter = "(&(objectclass=ds-cfg-instance-key)(!(ds-cfg-key-compromised-time=*)))"; final LdapName baseDN = new LdapName(baseDNStr); final String FILTER_OC_INSTANCE_KEY = new StringBuilder("(objectclass=") .append(ConfigConstants.OC_CRYPTO_INSTANCE_KEY) .append(")").toString(); final String FILTER_NOT_COMPROMISED = new StringBuilder("(!(") .append(ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME) .append("=*))").toString(); final String searchFilter = new StringBuilder("(&") .append(FILTER_OC_INSTANCE_KEY) .append(FILTER_NOT_COMPROMISED) .append(")").toString(); final SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE); final String attrIDs[]= { @@ -2169,13 +2190,13 @@ final Attribute keyIDAttr = attrs.get(attrIDs[0]); final Attribute keyCertAttr = attrs.get(attrIDs[1]); if (null == keyIDAttr || null == keyCertAttr) continue; // schema viol. keyEntryMap.put((String)keyIDAttr.get(), (byte[])keyCertAttr.get()); certificateMap.put((String)keyIDAttr.get(), (byte[])keyCertAttr.get()); } } catch (NamingException x) { throw new ADSContextException( ADSContextException.ErrorType.ERROR_UNEXPECTED, x); } return keyEntryMap; return certificateMap; } } opends/src/server/org/opends/server/schema/BinarySyntax.java
@@ -29,14 +29,12 @@ import org.opends.server.admin.std.server.AttributeSyntaxCfg; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.api.AttributeSyntax; import org.opends.server.api.EqualityMatchingRule; import org.opends.server.api.OrderingMatchingRule; import org.opends.server.api.SubstringMatchingRule; import org.opends.server.api.*; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.types.ByteString; import org.opends.server.types.AttributeValue; import org.opends.server.types.DirectoryException; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.messages.SchemaMessages.*; @@ -65,6 +63,24 @@ /** * A {@code byte[]} attribute value decoder for this syntax. */ public static final AttributeValueDecoder<byte[]> DECODER = new AttributeValueDecoder<byte[]>() { /** * {@inheritDoc} */ public byte[] decode(AttributeValue value) throws DirectoryException { // Make sure that the value is valid. value.getNormalizedValue(); return value.getValueBytes(); } }; /** * Creates a new instance of this syntax. Note that the only thing that * should be done here is to invoke the default constructor for the * superclass. All initialization should be performed in the opends/src/server/org/opends/server/types/CryptoManager.java
@@ -68,6 +68,8 @@ import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.schema.DirectoryStringSyntax; import org.opends.server.schema.IntegerSyntax; import org.opends.server.schema.BinarySyntax; import org.opends.admin.ads.ADSContext; /** * This class provides the interface to the Directory Server @@ -91,6 +93,18 @@ */ private static final DebugTracer TRACER = getTracer(); // Various schema element references. private final AttributeType attrKeyID; private final AttributeType attrPublicKeyCertificate; private final AttributeType attrTransformation; private final AttributeType attrMacAlgorithm; private final AttributeType attrSymmetricKey; private final AttributeType attrInitVectorLength; private final AttributeType attrKeyLength; private final AttributeType attrCompromisedTime; private final ObjectClass ocCipherKey; private final ObjectClass ocMacKey; // The secure random number generator used for key generation, // initialization vector PRNG seed... private static final SecureRandom secureRandom = new SecureRandom(); @@ -100,9 +114,6 @@ private static final Random pseudoRandom = new Random(secureRandom.nextLong()); // The preferred key wrapping transformation private final String preferredKeyWrappingTransformation; // The preferred message digest algorithm for the Directory Server. private final String preferredDigestAlgorithm; @@ -126,6 +137,9 @@ // The preferred key length for the preferred cipher. private final int preferredCipherTransformationKeyLengthBits; // The preferred key wrapping transformation private final String preferredKeyWrappingTransformation; // The name of the local certificate to use for SSL. private final String sslCertNickname; @@ -138,17 +152,6 @@ // The set of SSL cipher suites enabled or null for the default set. private final SortedSet<String> sslCipherSuites; // Various schema element references. private final AttributeType attrKeyID; private final AttributeType attrTransformation; private final AttributeType attrMacAlgorithm; private final AttributeType attrSymmetricKey; private final AttributeType attrInitVectorLength; private final AttributeType attrKeyLength; private final AttributeType attrCompromisedTime; private final ObjectClass ocCipherKey; private final ObjectClass ocMacKey; /** * Creates a new instance of this crypto manager object from a given @@ -171,6 +174,8 @@ // Initialize various schema references. attrKeyID = DirectoryServer.getAttributeType( ConfigConstants.ATTR_CRYPTO_KEY_ID); attrPublicKeyCertificate = DirectoryServer.getAttributeType( ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); attrTransformation = DirectoryServer.getAttributeType( ConfigConstants.ATTR_CRYPTO_CIPHER_TRANSFORMATION_NAME); attrMacAlgorithm = DirectoryServer.getAttributeType( @@ -340,9 +345,8 @@ final Entry e = searchOp.getSearchEntries().getFirst(); /* attribute ds-cfg-public-key-certificate is a MUST in the schema */ final List<Attribute> attrs = e.getAttribute(DirectoryServer.getAttributeType( ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE)); final List<Attribute> attrs = e.getAttribute(attrPublicKeyCertificate); final Attribute a = attrs.get(0); final AttributeValue v = a.getValues().iterator().next(); certificate = v.getValueBytes(); @@ -411,7 +415,7 @@ * @throws CryptoManagerException If there is a problem computing * the identifier from the instance key. */ public String getInstanceKeyID(byte[] instanceKeyCertificate) public static String getInstanceKeyID(byte[] instanceKeyCertificate) throws CryptoManagerException { MessageDigest md; final String mdAlgorithmName = "MD5"; @@ -430,6 +434,74 @@ /** Return the set of valid (i.e., not tagged as compromised) instance key-pair public-key certificate entries in ADS. @return The set of valid (i.e., not tagged as compromised) instance key-pair public-key certificate entries in ADS represented as a Map from ds-cfg-key-id value to ds-cfg-public-key-certificate;binary value. Note that the collection might be empty. @throws CryptoManagerException In case of a problem with the search operation. @see org.opends.admin.ads.ADSContext#getTrustedCertificates() */ private Map<String, byte[]> getTrustedCertificates() throws CryptoManagerException { final Map<String, byte[]> certificateMap = new HashMap<String, byte[]>(); final String baseDNStr = ADSContext.getInstanceKeysContainerDN(); try { final DN baseDN = DN.decode(baseDNStr); final String FILTER_OC_INSTANCE_KEY = new StringBuilder("(objectclass=") .append(ConfigConstants.OC_CRYPTO_INSTANCE_KEY) .append(")").toString(); final String FILTER_NOT_COMPROMISED = new StringBuilder("(!(") .append(ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME) .append("=*))").toString(); final String searchFilter = new StringBuilder("(&") .append(FILTER_OC_INSTANCE_KEY) .append(FILTER_NOT_COMPROMISED) .append(")").toString(); final LinkedHashSet<String> requestedAttributes = new LinkedHashSet<String>(); requestedAttributes.add(ConfigConstants.ATTR_CRYPTO_KEY_ID); final String ATTR_INSTANCE_KEY_CERTIFICATE_BINARY = ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE + ";binary"; requestedAttributes.add(ATTR_INSTANCE_KEY_CERTIFICATE_BINARY); final InternalClientConnection icc = InternalClientConnection.getRootConnection(); InternalSearchOperation searchOp = icc.processSearch( baseDN, SearchScope.SINGLE_LEVEL, DereferencePolicy.NEVER_DEREF_ALIASES, /* size limit */ 0, /* time limit */ 0, /* types only */ false, SearchFilter.createFilterFromString(searchFilter), requestedAttributes); for (Entry e : searchOp.getSearchEntries()) { /* attribute ds-cfg-key-id is the RDN and attribute ds-cfg-public-key-certificate is a MUST in the schema */ final String keyID = e.getAttributeValue( attrKeyID, DirectoryStringSyntax.DECODER); final byte[] certificate = e.getAttributeValue( attrPublicKeyCertificate, BinarySyntax.DECODER); certificateMap.put(keyID, certificate); } } catch (DirectoryException ex) { throw new CryptoManagerException( // TODO: i18n Message.raw("Error retrieving instance-key public key" + " certificates from ADS container %s.", baseDNStr), ex); } return(certificateMap); } /** * Encodes a ds-cfg-symmetric-key attribute value using the supplied * arguments. * @@ -640,7 +712,12 @@ final String symmetricKeyAttribute, final String requestedInstanceKeyID) throws CryptoManagerException { return symmetricKeyAttribute; // TODO: really unwrap and rewrap final SecretKey secretKey = decodeSymmetricKeyAttribute(symmetricKeyAttribute); final byte[] wrappingKeyCert = getTrustedCertificates().get(requestedInstanceKeyID); return encodeSymmetricKeyAttribute( requestedInstanceKeyID, wrappingKeyCert, secretKey); } opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/GetSymmetricKeyExtendedOperationTestCase.java
@@ -60,7 +60,7 @@ @Test @Test(enabled=false) public void testValidRequest() throws Exception { CryptoManager cm = DirectoryServer.getCryptoManager();