New code to tests DN strings.
authorWerner Koch <wk@gnupg.org>
Mon, 3 Jul 2006 12:50:12 +0000 (12:50 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 3 Jul 2006 12:50:12 +0000 (12:50 +0000)
NEWS
configure.ac
doc/ChangeLog
doc/ksba.texi
src/ChangeLog
src/dn.c
src/ksba.h
src/libksba.vers
tests/ChangeLog
tests/t-dnparser.c

diff --git a/NEWS b/NEWS
index b8927fa..55dca57 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+Noteworthy changes in version 0.9.16
+-------------------------------------------------
+
+
+
+ * Interface changes relative to the 0.9.13 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ksba_dn_teststr                NEW
+ ksba_dn_str2der                NEW
+ ksba_dn_der2str                NEW
+
+
 Noteworthy changes in version 0.9.15 (2006-06-20)
 -------------------------------------------------
 
index 46216f7..5a94b1d 100644 (file)
@@ -24,7 +24,7 @@ min_automake_version="1.9.3"
 
 # Version number: Remember to change immediately *after* a release.
 #                 Append a "-cvs" for non-released versions.
-AC_INIT(libksba, 0.9.15, gpa-dev@gnupg.org)
+AC_INIT(libksba, 0.9.16-cvs, gpa-dev@gnupg.org)
 # LT Version numbers: Remember to change them just *before* a release.
 #   (Interfaces removed:    CURRENT++, AGE=0, REVISION=0)
 #   (Interfaces added:      CURRENT++, AGE++, REVISION=0)
index 9a85131..5694aef 100644 (file)
@@ -1,3 +1,7 @@
+2006-07-03  Werner Koch  <wk@g10code.com>
+
+       * ksba.texi (DNs): New section
+
 2006-03-30  Brad Hards <bradh@frogmouth.net>  (wk)
 
        * ksba.texi: Fixed typos and other errors.
index cd68e62..b92840d 100644 (file)
@@ -891,6 +891,7 @@ to support some of the main functions.
 @menu
 * Names::                      General Names object
 * OIDs::                       Object Identifier helpers
+* DNs::                        Distinguished Name helpers
 @end menu
 
 @node Names
@@ -967,6 +968,37 @@ print_names (ksba_name_t name)
 [This needs to get written - for now please see libksba/src/oids.c]
 
 
+@node DNs
+@section Distinguished Name helpers
+
+These are helper functions for the so called distinguished names.  They
+are used for example as the issuer and subject name.
+
+@deftypefun gpg_error_t ksba_dn_teststr (@w{const char *@var{string}}, @w{int @var{seq}}, @w{size_t *@var{rerroff}}, @w{size_t *@var{rerrlen}})
+
+Assuming that @var{string} contains an RFC-2253 encoded string, test
+whether this string may be passed as a valid DN to libksba.  On success
+the functions returns @code{0}.  On error the function returns an error
+code and stores the offset of the erroneous part at
+@var{rerroff}. @var{rerrlen} will then receive the length of the
+erroneous part.
+
+This function is mostly useful to test whether a certain component label
+is supported. @var{seq} should be passed as @code{0} for now.  Any of
+@var{rerroff} and @var{rerrlen} may be passed as @var{NULL} if the
+caller is not interested at this value.
+
+@end deftypefun
+
+
+gpg_error_t
+ksba_dn_str2der (const char *string, void **rder, size_t *rderlen);
+
+gpg_error_t
+ksba_dn_der2str (const void *der, size_t derlen, char **r_string);
+
+
+
 \f
 @node Error Handling
 @chapter Error Handling
index d9b7937..f8d63a3 100644 (file)
@@ -1,3 +1,11 @@
+2006-07-03  Werner Koch  <wk@g10code.com>
+
+       * ksba.h, ksba.c (ksba_dn_teststr): New.
+       * dn.c (parse_rdn): New optionsl args ROFF and RLEN.  Changed
+       callers.
+       (ksba_dn_der2str, ksba_dn_str2der): New.
+       * libksba.vers: Added new functions.
+
 2006-06-19  Werner Koch  <wk@g10code.com>
 
        * ber-decoder.c (_ksba_ber_decoder_decode): always store value
index 0e1016e..0a6ad27 100644 (file)
--- a/src/dn.c
+++ b/src/dn.c
@@ -1,5 +1,5 @@
 /* dn.c - Distinguished Name helper functions
- *      Copyright (C) 2001 g10 Code GmbH
+ *      Copyright (C) 2001, 2006 g10 Code GmbH
  *
  * This file is part of KSBA.
  *
@@ -843,13 +843,16 @@ write_escaped (ksba_writer_t w, const unsigned char *buffer, size_t nbytes)
 
 
 /* Parse one RDN, and write it to WRITER.  Returns a pointer to the
-   next RDN part where the comma has alrady been skipped or NULL in
-   case of an error.  When NULL is passed as WRITER, the fucntion does
+   next RDN part where the comma has already been skipped or NULL in
+   case of an error.  When NULL is passed as WRITER, the function does
    not allocate any memory but just parses the string and returns the
-   ENDP. */
+   ENDP. If ROFF or RLEN are not NULL, they will receive informaion
+   useful for error reporting. */
 static gpg_error_t
-parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
+parse_rdn (const unsigned char *string, const char **endp, 
+           ksba_writer_t writer, size_t *roff, size_t *rlen)
 {
+  const unsigned char *orig_string = string;
   const unsigned char *s, *s1;
   size_t n, n1;
   int i;
@@ -863,15 +866,24 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
   int valuetype;
   int need_escaping = 0;
   gpg_error_t err = 0;
+  size_t dummy_roff, dummy_rlen;
+
+  if (!roff)
+    roff = &dummy_roff;
+  if (!rlen)
+    rlen = &dummy_rlen;
+
+  *roff = *rlen = 0;
 
   if (!string)
     return gpg_error (GPG_ERR_INV_VALUE);
   while (*string == ' ')
     string++;
+  *roff = string - orig_string;
   if (!*string)
     return gpg_error (GPG_ERR_SYNTAX); /* empty elements are not allowed */
   s = string;
-
+  
   if ( ((*s == 'o' && s[1] == 'i' && s[2] == 'd')
         ||(*s == 'O' && s[1] == 'I' && s[2] == 'D'))
        && s[3] == '.' && digitp (s+4))
@@ -879,6 +891,7 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
 
   /* parse attributeType */
   string = s;
+  *roff = string - orig_string;
   if (digitp (s))
     { /* oid */
       for (s++; digitp (s) || (*s == '.' && s[1] != '.'); s++)
@@ -921,7 +934,11 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
             break;
         }
       if (!oid_name_tbl[i].name)
-        return gpg_error (GPG_ERR_UNKNOWN_NAME);
+        {
+          *roff = string - orig_string;
+          *rlen = n;
+          return gpg_error (GPG_ERR_UNKNOWN_NAME);
+        }
       oid = oid_name_tbl[i].oid;
       oidlen = oid_name_tbl[i].oidlen;
     }
@@ -930,6 +947,8 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
     s++;
   string = s;
 
+  *roff = string - orig_string;
+
   /* parse attributeValue */
   if (!*s)
     {
@@ -948,6 +967,7 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
       n = s - string;
       if (!n || (n & 1))
         {
+          *rlen = n;
           err = gpg_error (GPG_ERR_SYNTAX); /* no hex digits or odd number */
           goto leave;
         }
@@ -995,6 +1015,7 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
       s = count_quoted_string (string, &n, 1, &valuetype);
       if (!s || *s != '\"')
         {
+          *rlen = s - orig_string;
           err = gpg_error (GPG_ERR_SYNTAX); /* error or quote not closed */
           goto leave;
         }
@@ -1027,11 +1048,14 @@ parse_rdn (const unsigned char *string, const char **endp, ksba_writer_t writer)
     }
   if ( *s && *s != ',' && *s != ';' && *s != '+')
     {
+      *roff = s - orig_string;
       err = gpg_error (GPG_ERR_SYNTAX); /* invalid delimiter */
       goto leave;
     }
   if (*s == '+') /* fixme: implement this */
     {
+      *roff = s - orig_string;
+      *rlen = 1;
       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); 
       goto leave;
     }
@@ -1094,18 +1118,18 @@ _ksba_dn_from_str (const char *string, char **rbuf, size_t *rlength)
   int part_array_size, nparts;
 
   *rbuf = NULL; *rlength = 0;
-  /* We are going to build the object using a writer object */
+  /* We are going to build the object using a writer object */
   err = ksba_writer_new (&writer);
   if (!err)
     err = ksba_writer_set_mem (writer, 1024);
   if (err)
     return err;
 
-  /* We must assign it in reverese order so we do it in 2 passes */
+  /* We must assign it in reverse order so we do it in 2 passes. */
   part_array_size = 0;
   for (nparts=0, s=string; s && *s;)
     {
-      err = parse_rdn (s, &endp, NULL);
+      err = parse_rdn (s, &endp, NULL, NULL, NULL);
       if (err)
         goto leave;
       if (nparts >= part_array_size)
@@ -1134,19 +1158,19 @@ _ksba_dn_from_str (const char *string, char **rbuf, size_t *rlength)
 
   while (--nparts >= 0)
     {
-      err = parse_rdn (part_array[nparts], &endp, writer);
+      err = parse_rdn (part_array[nparts], &endp, writer, NULL, NULL);
       if (err)
         goto leave;
     }
 
-  /* Now get the memory */
+  /* Now get the memory */
   buf = ksba_writer_snatch_mem (writer, &buflen);
   if (!buf)
     {
       err = gpg_error (GPG_ERR_ENOMEM);
       goto leave;
     }
-  /* reinitialize the buffer to create the outer sequence*/
+  /* Reinitialize the buffer to create the outer sequence.  */
   err = ksba_writer_set_mem (writer, buflen + 10);
   if (err)
     goto leave;
@@ -1177,3 +1201,60 @@ _ksba_dn_from_str (const char *string, char **rbuf, size_t *rlength)
 }
 
 
+
+gpg_error_t
+ksba_dn_der2str (const void *der, size_t derlen, char **rstring)
+{
+  return _ksba_derdn_to_str (der, derlen, rstring);
+}
+
+
+gpg_error_t
+ksba_dn_str2der (const char *string, unsigned char **rder, size_t *rderlen)
+{
+  return _ksba_dn_from_str (string, (char**)rder, rderlen);
+}
+
+
+
+/* Assuming that STRING contains an rfc2253 encoded string, test
+   whther this string may be passed as a valid DN to libksba.  On
+   success the functions returns 0.  On error the function returns an
+   error code and stores the offset within STRING of the erroneous
+   part at RERROFF. RERRLEN will then receive the length of the
+   erroneous part.  This function is most useful to test whether a
+   symbolic name (like SN) is supported. SEQ should be passed as 0 for
+   now.  RERROFF and RERRLEN may be passed as NULL if the caller is
+   not interested at this value. */
+gpg_error_t 
+ksba_dn_teststr (const char *string, int seq, 
+                 size_t *rerroff, size_t *rerrlen)
+{
+  size_t dummy_erroff, dummy_errlen;
+  gpg_error_t err;
+  int nparts;
+  const char *s, *endp;
+  size_t off, len;
+
+  if (!rerroff)
+    rerroff = &dummy_erroff;
+  if (!rerrlen)
+    rerrlen = &dummy_errlen;
+
+  *rerrlen = *rerroff = 0;
+
+  for (nparts=0, s=string; s && *s;)
+    {
+      err = parse_rdn (s, &endp, NULL, &off, &len);
+      if (err && !seq--)
+        {
+          *rerroff = s - string + off;
+          *rerrlen = len? len : strlen (s);
+          return err;
+        }
+      s = endp;
+    }
+  if (!nparts)
+    return gpg_error (GPG_ERR_SYNTAX);
+  return 0;
+}
index 4175a65..9806b84 100644 (file)
@@ -481,6 +481,13 @@ char *ksba_oid_to_str (const char *buffer, size_t length);
 gpg_error_t ksba_oid_from_str (const char *string,
                                unsigned char **rbuf, size_t *rlength);
 
+/*-- dn.c --*/
+gpg_error_t ksba_dn_der2str (const void *der, size_t derlen, char **r_string);
+gpg_error_t ksba_dn_str2der (const char *string,
+                             unsigned char **rder, size_t *rderlen);
+gpg_error_t ksba_dn_teststr (const char *string, int seq, 
+                             size_t *rerroff, size_t *rerrlen);
+
 
 /*-- name.c --*/
 gpg_error_t ksba_name_new (ksba_name_t *r_name);
index c16ea27..77df520 100644 (file)
@@ -81,6 +81,8 @@ KSBA_0.9 {
 
     ksba_oid_from_str; ksba_oid_to_str;
 
+    ksba_dn_der2str; ksba_dn_str2der; ksba_dn_teststr;
+
     ksba_reader_clear; ksba_reader_error; ksba_reader_new;
     ksba_reader_read; ksba_reader_release; ksba_reader_set_cb;
     ksba_reader_set_fd; ksba_reader_set_file; ksba_reader_set_mem;
@@ -101,6 +103,5 @@ KSBA_0.9 {
 KSBA_PRIVATE_TESTS {
    global:
      _ksba_keyinfo_from_sexp;  _ksba_keyinfo_to_sexp;
-     _ksba_dn_from_str;
 
 } KSBA_0.9;
index dd1803d..1c5a943 100644 (file)
@@ -1,3 +1,9 @@
+2006-07-03  Werner Koch  <wk@g10code.com>
+
+       * t-dnparser.c: Use ksba_dn_str2der isntead of internal functions.
+       (test_1): Also test ksba_dn_test_str.
+       (test_2): New.
+
 2005-04-19  Werner Koch  <wk@g10code.com>
 
        * t-ocsp.c (main): Add option --no-nonce.  Ret rid of the
index e622e5f..0425bcd 100644 (file)
@@ -1,5 +1,5 @@
 /* t-dnparser.c - basic test for the DN parser
- *      Copyright (C) 2002 g10 Code GmbH
+ *      Copyright (C) 2002, 2006 g10 Code GmbH
  *
  * This file is part of KSBA.
  *
@@ -27,7 +27,6 @@
 #include <errno.h>
 
 #include "../src/ksba.h"
-#include "../src/convert.h"
 #include "t-common.h"
 
 
@@ -48,17 +47,50 @@ test_1 (void)
   };
   gpg_error_t err;
   int i;
-  char *buf;
-  size_t len;
+  unsigned char *buf;
+  size_t off, len;
 
   for (i=0; empty_elements[i]; i++)
     {
-      err = _ksba_dn_from_str (empty_elements[i], &buf, &len);
+      err = ksba_dn_str2der (empty_elements[i], &buf, &len);
       if (gpg_err_code (err) != GPG_ERR_SYNTAX)
         fail ("empty element not detected");
+      err = ksba_dn_teststr (empty_elements[i], 0, &off, &len);
+      if (!err)
+        fail ("ksba_dn_teststr returned no error");
+      printf ("string ->%s<-  error at %lu.%lu (%.*s)\n",
+              empty_elements[i], (unsigned long)off, (unsigned long)len,
+              (int)len, empty_elements[i]+off);
       xfree (buf);
     }
+}
+
+static void
+test_2 (void)
+{
+  static char *invalid_labels[] = {
+    "C=de,FOO=something,O=bar",
+    "Y=foo, C=baz",
+    NULL
+  };
+  gpg_error_t err;
+  int i;
+  unsigned char *buf;
+  size_t off, len;
 
+  for (i=0; invalid_labels[i]; i++)
+    {
+      err = ksba_dn_str2der (invalid_labels[i], &buf, &len);
+      if (gpg_err_code (err) != GPG_ERR_UNKNOWN_NAME)
+        fail ("invalid label not detected");
+      err = ksba_dn_teststr (invalid_labels[i], 0, &off, &len);
+      if (!err)
+        fail ("ksba_dn_test_str returned no error");
+      printf ("string ->%s<-  error at %lu.%lu (%.*s)\n",
+              invalid_labels[i], (unsigned long)off, (unsigned long)len,
+              (int)len, invalid_labels[i]+off);
+      xfree (buf);
+    }
 }
 
 
@@ -68,12 +100,12 @@ main (int argc, char **argv)
 {
   char inputbuf[4096];
   int inputlen;
-  char *buf;
+  unsigned char *buf;
   size_t len;
   gpg_error_t err;
   
   if (argc == 2 && !strcmp (argv[1], "--to-str") )
-    { /* Read the DER encoed DN from stdin write the string to stdout */
+    { /* Read the DER encoded DN from stdin write the string to stdout */
       inputlen = fread (inputbuf, 1, sizeof inputbuf, stdin);
       if (!feof (stdin))
         fail ("read error or input too large");
@@ -87,13 +119,14 @@ main (int argc, char **argv)
       if (!feof (stdin))
         fail ("read error or input too large");
       
-      err = _ksba_dn_from_str (inputbuf, &buf, &len);
+      err = ksba_dn_str2der (inputbuf, &buf, &len);
       fail_if_err (err);
       fwrite (buf, len, 1, stdout);
     }
   else if (argc == 1)
     {
       test_1 ();
+      test_2 ();
     }
   else
     {