From aad596c8559b3d3d081617736cdbeda1374f017b Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 11 May 2012 21:58:30 +0000
Subject: [PATCH] Fix OPENDJ-482: Validation for the CertificateSyntax
---
opends/src/server/org/opends/server/schema/CertificateSyntax.java | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 266 insertions(+), 4 deletions(-)
diff --git a/opends/src/server/org/opends/server/schema/CertificateSyntax.java b/opends/src/server/org/opends/server/schema/CertificateSyntax.java
index 00724f4..6555af5 100644
--- a/opends/src/server/org/opends/server/schema/CertificateSyntax.java
+++ b/opends/src/server/org/opends/server/schema/CertificateSyntax.java
@@ -23,12 +23,16 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2012 Forgerock AS
*/
package org.opends.server.schema;
-import org.opends.server.admin.std.server.AttributeSyntaxCfg;
+import java.util.List;
+
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.CertificateAttributeSyntaxCfg;
import org.opends.server.api.ApproximateMatchingRule;
import org.opends.server.api.AttributeSyntax;
import org.opends.server.api.EqualityMatchingRule;
@@ -37,12 +41,20 @@
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.ByteSequence;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.ResultCode;
+import org.opends.server.protocols.asn1.ASN1;
+import org.opends.server.protocols.asn1.ASN1Exception;
+import org.opends.server.protocols.asn1.ASN1Reader;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.messages.SchemaMessages.*;
+
+import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import static org.opends.server.schema.SchemaConstants.*;
+import static org.opends.server.protocols.asn1.ASN1Constants.*;
/**
@@ -51,7 +63,8 @@
* bytes. It will be treated much like the octet string attribute syntax.
*/
public class CertificateSyntax
- extends AttributeSyntax<AttributeSyntaxCfg>
+ extends AttributeSyntax<CertificateAttributeSyntaxCfg>
+ implements ConfigurationChangeListener<CertificateAttributeSyntaxCfg>
{
// The default equality matching rule for this syntax.
private EqualityMatchingRule defaultEqualityMatchingRule;
@@ -62,6 +75,9 @@
// The default substring matching rule for this syntax.
private SubstringMatchingRule defaultSubstringMatchingRule;
+ // The current configuration.
+ private volatile CertificateAttributeSyntaxCfg config;
+
/**
@@ -80,7 +96,7 @@
/**
* {@inheritDoc}
*/
- public void initializeSyntax(AttributeSyntaxCfg configuration)
+ public void initializeSyntax(CertificateAttributeSyntaxCfg configuration)
throws ConfigException
{
defaultEqualityMatchingRule =
@@ -106,6 +122,34 @@
logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
SMR_OCTET_STRING_OID, SYNTAX_CERTIFICATE_NAME));
}
+
+ this.config = configuration;
+ config.addCertificateChangeListener(this);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(
+ CertificateAttributeSyntaxCfg configuration,
+ List<Message> unacceptableReasons)
+ {
+ // The configuration is always acceptable.
+ return true;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationChange(
+ CertificateAttributeSyntaxCfg configuration)
+ {
+ this.config = configuration;
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
}
@@ -222,7 +266,215 @@
public boolean valueIsAcceptable(ByteSequence value,
MessageBuilder invalidReason)
{
- // All values will be acceptable for the certificate syntax.
+ // Skip validation if strict validation is disabled.
+ if (!config.isStrictFormat())
+ {
+ return true;
+ }
+
+ // Validate the ByteSequence against the definitions of X.509, clause 7
+ long x509Version=0;
+ ASN1Reader reader = ASN1.getReader(value);
+ try
+ {
+ // Certificate SIGNED SEQUENCE
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readStartSequence();
+
+ // CertificateContent SEQUENCE
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readStartSequence();
+
+ // Optional Version
+ if (reader.hasNextElement() &&
+ reader.peekType() == (TYPE_MASK_CONTEXT | TYPE_MASK_CONSTRUCTED))
+ {
+ reader.readStartExplicitTag();
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_INTEGER_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ x509Version=reader.readInteger();
+ if (x509Version < 0 || x509Version >2)
+ {
+ // invalid Version specified
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_INVALID_VERSION
+ .get(x509Version));
+ return false;
+ }
+ if (x509Version == 0)
+ {
+ // DEFAULT values shall not be included in DER encoded SEQUENCE
+ // (X.690, 11.5)
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_INVALID_DER.get());
+ return false;
+ }
+ reader.readEndExplicitTag();
+ }
+
+ // serialNumber
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_INTEGER_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // signature AlgorithmIdentifier
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // issuer name (SEQUENCE as of X.501, 9.2)
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // validity (SEQUENCE)
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // subject name (SEQUENCE as of X.501, 9.2)
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // SubjectPublicKeyInfo (SEQUENCE)
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // OPTIONAL issuerUniqueIdentifier
+ if (reader.hasNextElement() &&
+ reader.peekType() == (TYPE_MASK_CONTEXT + 1))
+ {
+ if (x509Version < 1)
+ {
+ // only valid in v2 and v3
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+ }
+
+ // OPTIONAL subjectUniqueIdentifier
+ if (reader.hasNextElement() &&
+ reader.peekType() == (TYPE_MASK_CONTEXT + 2))
+ {
+ if (x509Version < 1)
+ {
+ // only valid in v2 and v3
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+ }
+
+ // OPTIONAL extensions
+ if (reader.hasNextElement() &&
+ reader.peekType() == ((TYPE_MASK_CONTEXT|TYPE_MASK_CONSTRUCTED) + 3))
+ {
+ if (x509Version < 2)
+ {
+ // only valid in v3
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readStartExplicitTag(); // read Tag
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ // only valid in v3
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readEndExplicitTag(); // read end Tag
+ }
+
+ // There should not be any further ASN.1 elements within this SEQUENCE
+ if (reader.hasNextElement())
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readEndSequence(); // End CertificateContent SEQUENCE
+
+ // AlgorithmIdentifier SEQUENCE
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_SEQUENCE_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // ENCRYPTED HASH BIT STRING
+ if (!reader.hasNextElement() ||
+ reader.peekType() != UNIVERSAL_BIT_STRING_TYPE)
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.skipElement();
+
+ // There should not be any further ASN.1 elements within this SEQUENCE
+ if (reader.hasNextElement())
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ reader.readEndSequence(); // End Certificate SEQUENCE
+
+ // There should not be any further ASN.1 elements
+ if (reader.hasNextElement())
+ {
+ invalidReason.append(ERR_SYNTAX_CERTIFICATE_NOTVALID.get());
+ return false;
+ }
+ // End of the certificate
+ }
+ catch (ASN1Exception e)
+ {
+ System.out.println(e.getMessageObject());
+ invalidReason.append(e.getMessageObject());
+ return false;
+ }
+
+ // The basic structure of the value is an X.509 certificate
return true;
}
@@ -235,5 +487,15 @@
{
return true;
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isHumanReadable()
+ {
+ return false;
+ }
}
--
Gitblit v1.10.0