STRTOK(3)           Linux Programmer's Manual           STRTOK(3)

  NAME
        strtok, strtok_r - extract tokens from strings

  BUGS
        Never use these functions.
        ^^^^^^^^^^^^^^^^^^^^^^^^^^

no, i'm not making this up, this is a vanilla debian woody.

On 02-04-17 12:41:35 CEST, Robert Joop wrote:
> On 02-04-16 19:04:41 CEST, Michael Bell wrote:
> > The only bad detail is now "openssl -subj" which use a DN with ","
> > inside but the order is the one from X.500.
> 
> looking at last night's snap, apps/req.c, build_subject(), i see that
> one can use both , and / delimiters.
> but i fail to see whether one can escape the delimiters. can one?

one cannot, it uses strtok...

i've souped it up a little, so that now the args for req -subj and ca
-subj can contain escaped characters, e.g. req -subj
'/C=US/CN=John\/Jane Doe'.

except for the escaping, this is the format used by openssl in
index.txt...

this is also the format that will be emitted by openca when it interfaces
to openssl:

use X500::DN;
my $dn = new X500::DN (new X500::RDN ('c'=>'US'), new X500::RDN ('o'=>'\\Acme/2, 
Inc.'), new X500::RDN ('cn'=>'John Doe, PhD')) or die;
print $dn->getRFC2253String(), "\n";
print $dn->getOpenSSLString(), "\n";

outputs:

cn=John Doe\, PhD, o=\\Acme/2\, Inc., c=US
/c=US/o=\\Acme\/2, Inc./cn=John Doe, PhD

a patch (based on openssl-SNAP-20020423) is attached.

rj
diff -ru orig/openssl-SNAP-20020423/apps/ca.c openssl-SNAP-20020423/apps/ca.c
--- orig/openssl-SNAP-20020423/apps/ca.c        Fri Mar  8 21:00:46 2002
+++ openssl-SNAP-20020423/apps/ca.c     Wed Apr 24 15:49:55 2002
@@ -3023,64 +3023,122 @@
        return ret;
        }
 
+/*
+ * subject is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
 static X509_NAME *do_subject(char *subject)
        {
-       X509_NAME *n = NULL;
-
-       int i, nid, ne_num=0;
+       size_t buflen = strlen (subject)+1; /* to copy the types and values into. due 
+to escaping, the copy can only become shorter */
+       char *buf = malloc (buflen);
+       size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
+       char **ne_types = malloc (max_ne * sizeof (char *));
+       char **ne_values = malloc (max_ne * sizeof (char *));
 
-       char *ne_name = NULL;
-       char *ne_value = NULL;
+       char *sp = subject, *bp = buf;
+       int i, ne_num = 0;
 
-       char *tmp = NULL;
-       char *p[2];
+       X509_NAME *n = NULL;
+       int nid;
 
-       char *str_list[256];
-       
-       p[0] = ",/";
-       p[1] = "=";
+       if (!buf || !ne_types || !ne_values)
+       {
+               BIO_printf(bio_err, "malloc error\n");
+               goto error0;
+       }
 
-       n = X509_NAME_new();
+       if (*subject != '/')
+       {
+               BIO_printf(bio_err, "Subject does not start with '/'.\n");
+               goto error0;
+       }
+       sp++; /* skip leading / */
 
-       tmp = strtok(subject, p[0]);
-       while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+       while (*sp)
+       {
+               /* collect type */
+               ne_types[ne_num] = bp;
+               while (*sp)
                {
-               char *token = tmp;
-
-               while (token[0] == ' ')
-                       token++;
-               str_list[ne_num] = token;
-
-               tmp = strtok(NULL, p[0]);
-               ne_num++;
+                       if (*sp == '\\') /* is there anything to escape in the 
+type...? */
+                               if (*++sp)
+                                       *bp++ = *sp++;
+                               else
+                               {
+                                       BIO_printf(bio_err, "escape character at end 
+of string\n");
+                                       goto error0;
+                               }
+                       else if (*sp == '=')
+                       {
+                               sp++;
+                               *bp++ = '\0';
+                               break;
+                       }
+                       else
+                               *bp++ = *sp++;
                }
+               if (!*sp)
+               {
+                       BIO_printf(bio_err, "end of string encountered while 
+processing type of subject name element #%d\n", ne_num);
+                       goto error0;
+               }
+               ne_values[ne_num] = bp;
+               while (*sp)
+               {
+                       if (*sp == '\\')
+                               if (*++sp)
+                                       *bp++ = *sp++;
+                               else
+                               {
+                                       BIO_printf(bio_err, "escape character at end 
+of string\n");
+                                       goto error0;
+                               }
+                       else if (*sp == '/')
+                       {
+                               sp++;
+                               *bp++ = '\0';
+                               break;
+                       }
+                       else
+                               *bp++ = *sp++;
+               }
+               *bp++ = '\0';
+               ne_num++;
+       }
+
+       n = X509_NAME_new();
 
        for (i = 0; i < ne_num; i++)
                {
-               ne_name  = strtok(str_list[i], p[1]);
-               ne_value = strtok(NULL, p[1]);
-
-               if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+               if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
                        {
-                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, 
skipped\n", ne_name);
+                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, 
+skipped\n", ne_types[i]);
                        continue;
                        }
 
-               if (ne_value == NULL)
+               if (!*ne_values[i])
                        {
-                       BIO_printf(bio_err, "No value provided for Subject Attribute 
%s, skipped\n", ne_name);
+                       BIO_printf(bio_err, "No value provided for Subject Attribute 
+%s, skipped\n", ne_types[i]);
                        continue;
                        }
 
-               if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned 
char*)ne_value, -1,-1,0))
-                       {
-                       X509_NAME_free(n);
-                       return NULL;
-                       }
+               if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned 
+char*)ne_values[i], -1,-1,0))
+                       goto error1;
                }
 
+       free (ne_values);
+       free (ne_types);
+       free (buf);
        return n;
-       }
+
+error1:
+       X509_NAME_free(n);
+error0:
+       free (ne_values);
+       free (ne_types);
+       free (buf);
+       return NULL;
+}
 
 
 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
diff -ru orig/openssl-SNAP-20020423/apps/req.c openssl-SNAP-20020423/apps/req.c
--- orig/openssl-SNAP-20020423/apps/req.c       Wed Apr 17 12:00:48 2002
+++ openssl-SNAP-20020423/apps/req.c    Wed Apr 24 15:50:03 2002
@@ -1210,66 +1210,125 @@
        return(ret);
        }
 
+/*
+ * subject is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
 static int build_subject(X509_REQ *req, char *subject, unsigned long chtype)
        {
-       X509_NAME *n = NULL;
-
-       int i, nid, ne_num=0;
+       size_t buflen = strlen (subject)+1; /* to copy the types and values into. due 
+to escaping, the copy can only become shorter */
+       char *buf = malloc (buflen);
+       size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
+       char **ne_types = malloc (max_ne * sizeof (char *));
+       char **ne_values = malloc (max_ne * sizeof (char *));
 
-       char *ne_name = NULL;
-       char *ne_value = NULL;
+       char *sp = subject, *bp = buf;
+       int i, ne_num = 0;
 
-       char *tmp = NULL;
-       char *p[2];
+       X509_NAME *n = NULL;
+       int nid;
 
-       char *str_list[256];
-       
-       p[0] = ",/";
-        p[1] = "=";
+       if (!buf || !ne_types || !ne_values)
+       {
+               BIO_printf(bio_err, "malloc error\n");
+               goto error0;
+       }
 
-       n = X509_NAME_new();
+       if (*subject != '/')
+       {
+               BIO_printf(bio_err, "Subject does not start with '/'.\n");
+               goto error0;
+       }
+       sp++; /* skip leading / */
 
-       tmp = strtok(subject, p[0]);
-       while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+       while (*sp)
+       {
+               /* collect type */
+               ne_types[ne_num] = bp;
+               while (*sp)
                {
-               char *token = tmp;
-
-               while (token[0] == ' ')
-                       token++;
-               str_list[ne_num] = token;
-
-               tmp = strtok(NULL, p[0]);
-               ne_num++;
+                       if (*sp == '\\') /* is there anything to escape in the 
+type...? */
+                               if (*++sp)
+                                       *bp++ = *sp++;
+                               else
+                               {
+                                       BIO_printf(bio_err, "escape character at end 
+of string\n");
+                                       goto error0;
+                               }
+                       else if (*sp == '=')
+                       {
+                               sp++;
+                               *bp++ = '\0';
+                               break;
+                       }
+                       else
+                               *bp++ = *sp++;
+               }
+               if (!*sp)
+               {
+                       BIO_printf(bio_err, "end of string encountered while 
+processing type of subject name element #%d\n", ne_num);
+                       goto error0;
                }
+               ne_values[ne_num] = bp;
+               while (*sp)
+               {
+                       if (*sp == '\\')
+                               if (*++sp)
+                                       *bp++ = *sp++;
+                               else
+                               {
+                                       BIO_printf(bio_err, "escape character at end 
+of string\n");
+                                       goto error0;
+                               }
+                       else if (*sp == '/')
+                       {
+                               sp++;
+                               *bp++ = '\0';
+                               break;
+                       }
+                       else
+                               *bp++ = *sp++;
+               }
+               *bp++ = '\0';
+               ne_num++;
+       }
+
+       n = X509_NAME_new();
 
        for(i = 0; i < ne_num; i++)
                {
-               ne_name  = strtok(str_list[i], p[1]);
-               ne_value = strtok(NULL, p[1]);
-
-               if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+               if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
                        {
-                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, 
skipped\n", ne_name);
+                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, 
+skipped\n", ne_types[i]);
                        continue;
                        }
 
-               if (ne_value == NULL)
+               if (!*ne_values[i])
                        {
-                       BIO_printf(bio_err, "No value provided for Subject Attribute 
%s, skipped\n", ne_name);
+                       BIO_printf(bio_err, "No value provided for Subject Attribute 
+%s, skipped\n", ne_types[i]);
                        continue;
                        }
 
-               if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned 
char*)ne_value, -1,-1,0))
-                       {
-                       X509_NAME_free(n);
-                       return 0;
-                       }
+               if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned 
+char*)ne_values[i], -1,-1,0))
+                       goto error1;
+
                }
 
        if (!X509_REQ_set_subject_name(req, n))
-               return 0;
+               goto error1;
        X509_NAME_free(n);
+       free (ne_values);
+       free (ne_types);
+       free (buf);
        return 1;
+
+error1:
+       X509_NAME_free(n);
+error0:
+       free (ne_values);
+       free (ne_types);
+       free (buf);
+       return 0;
 }
 
 
diff -ru orig/openssl-SNAP-20020423/doc/apps/ca.pod 
openssl-SNAP-20020423/doc/apps/ca.pod
--- orig/openssl-SNAP-20020423/doc/apps/ca.pod  Mon Nov 26 14:01:41 2001
+++ openssl-SNAP-20020423/doc/apps/ca.pod       Wed Apr 24 15:53:13 2002
@@ -216,7 +216,9 @@
 
 =item B<-subj arg>
 
-supersedes subject name given in the request
+supersedes subject name given in the request.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
 
 =item B<-crlexts section>
 
diff -ru orig/openssl-SNAP-20020423/doc/apps/req.pod 
openssl-SNAP-20020423/doc/apps/req.pod
--- orig/openssl-SNAP-20020423/doc/apps/req.pod Sun Dec  2 01:00:53 2001
+++ openssl-SNAP-20020423/doc/apps/req.pod      Wed Apr 24 15:03:32 2002
@@ -168,6 +168,8 @@
 
 sets subject name for new request or supersedes the subject name
 when processing a request.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
 
 =item B<-x509>
 

Reply via email to