Hi,

We'd like to submit the following patch to OpenSSL, which allows you to
specify the directoryName format for X509v3 extensions such as
subjectAltName, crlDistributionPoints, etc. It parses RFC2253-style
distinguished names, so you can specify something like the following in your
oppenssl.cnf:

[ usr_cert ]
crlDistributionPoints = @crldp1
...

[ crldp1 ]
DirName = CN=myhost,O=myorg,C=GB
URI = http://www.myhost.com/myca.crl

I hope this proves useful.

Ollie

~~~~~~~

File: crypto/x509v3/v3_alt.c, baseline is openssl-0.9.5a

*** v3_alt.c.orig       Wed Dec  1 01:49:46 1999
--- v3_alt.c    Thu Aug 31 17:13:40 2000
***************
*** 65,70 ****
--- 65,71 ----
  static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
  static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens);
  static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens);
+ static int rfc2253_to_x509_name(char *dn_string, X509_NAME **x509_name);
  X509V3_EXT_METHOD v3_alt[] = {
  { NID_subject_alt_name, 0,
  (X509V3_EXT_NEW)GENERAL_NAMES_new,
***************
*** 376,381 ****
--- 377,388 ----
                        goto err;
        }
        type = GEN_IPADD;
+ } else if(!name_cmp(name, "DirName")) {
+   if (!rfc2253_to_x509_name(value, &(gen->d.dirn))) {
+     X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
+     goto err;
+   }
+       type = GEN_DIRNAME;
  } else {
        X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
        ERR_add_error_data(2, "name=", name);
***************
*** 399,401 ****
--- 406,612 ----
  GENERAL_NAME_free(gen);
  return NULL;
  }
+ 
+ /*
+  * This routine converts an RFC2253-style string into an X509_NAME
+  */
+ 
+ static int rfc2253_to_x509_name(char *dn_string, X509_NAME **x509_name)
+ {
+       int rc = 0;
+       unsigned int parsed_ok = 0;
+       X509_NAME_ENTRY *entry = NULL;
+       char *str = NULL;
+       char *cc;
+       char *type;
+       char *value;
+       int rdn_flag_next = 0;
+       int rdn_flag_this;
+       int prev_set;
+       int new_set;
+       int ii;
+       int error;
+ 
+       /*
+        * Create the X509_NAME structure.
+        */
+       *x509_name = X509_NAME_new();
+       if (*x509_name == NULL)
+       {
+               goto EXIT_LABEL;
+       }
+ 
+       /*
+        * Duplicate the string because we will be inserting nulls into it.
+        */
+       str = Malloc(strlen(dn_string) + 1);
+       if (str == NULL)
+       {
+               goto EXIT_LABEL;
+       }
+       strcpy(str, dn_string);
+ 
+       /*
+        * Search through the string, extracting each type/value pair and
adding
+        * them to the X509_NAME structure.
+        */
+       cc = str;
+       for (;;)
+       {
+               /*
+                * Look for the start of an attributeType.
+                */
+               while (isspace((int)*cc))
+               {
+                       cc++;
+               }
+ 
+               /*
+                * Check that it's valid; remember where it starts if so.
+                */
+               if (!isalpha((int)*cc))
+               {
+                       break;
+               }
+               type = cc;
+               cc++;
+ 
+               /*
+                * Look for the end of the attributeType and insert nulls
until we find
+                * an equals sign.
+                */
+               while (isalpha((int)*cc) || isdigit((int)*cc) || (*cc ==
'-'))
+               {
+                       cc++;
+               }
+ 
+               if (*cc == 0)
+               {
+                       break;
+               }
+ 
+               while (isspace((int)*cc))
+               {
+                       *cc = 0;
+                       cc++;
+               }
+ 
+               if (*cc != '=')
+               {
+                       break;
+               }
+               *cc = 0;
+               cc++;
+ 
+               /*
+                * Look for the start of an attributeValue. Note that we
will fail to
+                * parse an attribute with nothing in it, eg CN=,O=DCL,C=GB.
+                */
+               while (isspace((int)*cc))
+               {
+                       cc++;
+               }
+               value = cc;
+ 
+               /*
+                * Look for the end of the attributeValue and insert a null.
If that's
+                * the end of the string, set cc to null so that we exit the
loop after
+                * adding this last value.
+                */
+               while (strchr(",;+", (int)*cc) == NULL)
+               {
+                       cc++;
+               }
+ 
+               rdn_flag_this = rdn_flag_next;
+               if (*cc == 0)
+               {
+                       cc = NULL;
+               }
+               else
+               {
+                       /*
+                        * Work out whether the next attributeType/Value
pair will be part of
+                        * the same RDN ('+' separator) or a new RDN (',' or
';' separator).
+                        */
+                       if (*cc == '+')
+                       {
+                               rdn_flag_next = -1;
+                       }
+                       else
+                       {
+                               rdn_flag_next = 0;
+                       }
+ 
+                       *cc = 0;
+                       cc++;
+               }
+ 
+               /*
+                * Add the attribute to the X509_NAME structure.
+                */
+               error = X509_NAME_add_entry_by_txt(*x509_name, type,
MBSTRING_ASC,
+                                           (unsigned char *)value, -1, -1,
rdn_flag_this);
+               if (error == 0)
+               {
+                       goto EXIT_LABEL;
+               }
+ 
+               if (cc == NULL)
+               {
+                       parsed_ok = 1;
+                       break;
+               }
+       }
+ 
+       /*
+        * We've broken out of the loop. If parsed_ok==0 or there are no
entries
+        * in the name structure, it's an error.
+        */
+       if ((parsed_ok == 0) || (X509_NAME_entry_count(*x509_name) == 0))
+       {
+               goto EXIT_LABEL;
+       }
+ 
+       /*
+        * Now reverse the order of the entries in the X509_NAME structure,
so
+        * that the ordering agrees with X.501 (i.e. opposite to RFC2253).
We
+        * can't construct the list of entries backwards in the first place,
+        * because the logic in X509_NAME_add_entry() doesn't allow us to
set up
+        * 'set' correctly for each entry.
+        */
+       prev_set = -1;
+       new_set = -1;
+       for (ii = (X509_NAME_entry_count(*x509_name) - 1); ii >= 0 ; ii--)
+       {
+               entry = sk_X509_NAME_ENTRY_delete((*x509_name)->entries,
ii);
+               if (entry->set != prev_set)
+               {
+                       prev_set = entry->set;
+                       new_set++;
+               }
+               entry->set = new_set;
+               sk_X509_NAME_ENTRY_push((*x509_name)->entries, entry);
+       }
+ 
+       rc = 1;
+ 
+ EXIT_LABEL:
+ 
+       if (!rc)
+       {
+               if (*x509_name != NULL)
+               {
+                       X509_NAME_free(*x509_name);
+                       *x509_name = NULL;
+               }
+       }
+ 
+       if (str != NULL)
+       {
+               Free(str);
+       }
+ 
+       return(rc);
+ }
+ 



--
Ollie King
Network Convergence Group
Data Connection Ltd
Tel:   +44 20 8366 1177        Fax: +44 20 8363 1468
Email: [EMAIL PROTECTED]  Web: http://www.dataconnection.com


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to