[svn] ksba - r254 - in trunk: . src tests

svn author wk cvs at cvs.gnupg.org
Thu Aug 31 17:47:50 CEST 2006


Author: wk
Date: 2006-08-31 17:47:49 +0200 (Thu, 31 Aug 2006)
New Revision: 254

Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/README
   trunk/TODO
   trunk/configure.ac
   trunk/src/ChangeLog
   trunk/src/crl.c
   trunk/src/ksba-config.in
   trunk/src/ksba.h
   trunk/src/ksba.m4
   trunk/src/ocsp.c
   trunk/src/ocsp.h
   trunk/tests/ChangeLog
   trunk/tests/t-common.h
   trunk/tests/t-ocsp.c
Log:
Preparing the 1.0 release


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/ChangeLog	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,3 +1,12 @@
+2006-08-31  Werner Koch  <wk at g10code.com>
+
+	Released 1.0.0.
+	
+	* configure.ac: Bumped LT version to C17/A9/R0.
+	
+	* configure.ac: Require libgpg-error 1.2. Removed test on
+	GPG_ERR_UNKNOWN_CRIT_EXTN.
+
 2006-08-01  Werner Koch  <wk at g10code.com>
 
 	Released 0.9.16.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/NEWS	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,13 +1,19 @@
-Noteworthy changes in version 0.9.17
+Noteworthy changes in version 1.0.0 (2006-08-31)
 -------------------------------------------------
 
  * OCSP nonces are now checked to detect replay attacks.
 
  * OCSP extensions may no be retrieved.
 
+ * Implemented ksba_ocsp_get_responder_id which used to always return
+   an error code not_implemented.  Thus we can assume that the
+   function has never been used and we don't need to see this as an
+   API break.
+
  * Interface changes relative to the 0.9.16 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ksba_ocsp_get_extension        NEW
+ ksba_ocsp_get_responder_id     CHANGED: No ABI break.
 
 
 Noteworthy changes in version 0.9.16 (2006-08-01)

Modified: trunk/README
===================================================================
--- trunk/README	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/README	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,7 +1,7 @@
                                LIBKSBA
                               ---------
 
-                     Copyright 2001 g10 Code GmbH
+                  Copyright 2001, 2006 g10 Code GmbH
 
 This file is free software; as a special exception the author gives
 unlimited permission to copy and/or distribute it, with or without
@@ -41,8 +41,9 @@
 
 A standard info format reference manual is included.  However the OCSP
 feature has not yet been documented.  See the comments in src/ocsp.c
-and the example tests/t-ocsp.c.  The program dirmngr uses the ocsp
-feature and may be used as another example.
+and the example tests/t-ocsp.c.  The package dirmngr make extensive
+use of the ocsp feature and may be used as another example.
 
 
 
+

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/TODO	2006-08-31 15:47:49 UTC (rev 254)
@@ -51,4 +51,3 @@
 ** The ASN.1 parse tree is not released in all places
 ** Some memory is not released in case of errors.
 
-* Implement ksba_ocsp_get_extension!!!!

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/configure.ac	2006-08-31 15:47:49 UTC (rev 254)
@@ -26,8 +26,8 @@
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [0.9.17])
-m4_define([my_issvn], [yes])
+m4_define([my_version], [1.0.0])
+m4_define([my_issvn], [no])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \
           || echo 'Revision: 0')|sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))
@@ -39,16 +39,17 @@
 #   (Interfaces added:      CURRENT++, AGE++, REVISION=0)
 #   (No interfaces changed:                   REVISION++)
 # Please remember to document interface changes in the NEWS file.
-LIBKSBA_LT_CURRENT=16
-LIBKSBA_LT_AGE=8
+LIBKSBA_LT_CURRENT=17
+LIBKSBA_LT_AGE=9
 LIBKSBA_LT_REVISION=0
 #-------------------
+# If the API is changed in an incompatible way: increment the next counter.
+KSBA_CONFIG_API_VERSION=1
 
-# fixme: When bouncing this to a newer version, you check whether the
-# declaration tests for some symbols can be removed.
-NEED_GPG_ERROR_VERSION=0.7
 
+NEED_GPG_ERROR_VERSION=1.2
 
+
 PACKAGE=$PACKAGE_NAME
 VERSION=$PACKAGE_VERSION
 
@@ -136,10 +137,6 @@
   AC_MSG_ERROR([libgpg-error is needed.
                 See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ .])
 fi
-_tmp_gpg_error_save_cflags="$CFLAGS"
-CFLAGS="$CFLAGS $GPG_ERROR_CFLAGS"
-AC_CHECK_DECLS(GPG_ERR_UNKNOWN_CRIT_EXTN,,,[#include <gpg-error.h>])
-CFLAGS="${_tmp_gpg_error_save_cflags}"
 
 AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_KSBA,
           [The default error source for libksba.])
@@ -173,6 +170,7 @@
 KSBA_CONFIG_CFLAGS=""
 AC_SUBST(KSBA_CONFIG_LIBS)
 AC_SUBST(KSBA_CONFIG_CFLAGS)
+AC_SUBST(KSBA_CONFIG_API_VERSION)
 
 # The Makefiles need to know about cross compiling
 AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ChangeLog	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,3 +1,28 @@
+2006-08-31  Werner Koch  <wk at g10code.com>
+
+	* ocsp.h (struct ocsp_extension_s): New.
+	* ocsp.c (extract_nonce): Renamed to ..
+	(parse_response_extensions): .. this. Extended to save all
+	extensions.
+	(release_ocsp_extensions): New.
+	(ksba_ocsp_release): Release new extension data.
+	(ksba_ocsp_parse_response): Reset extesnion data.
+	(parse_optional_boolean): New.
+	(parse_single_extensions): New.
+
+	* ksba.m4: Implement --api-version check.
+	* ksba-config.in (echo_api_version): New option --api-version.
+
+	* crl.c (GPG_ERR_UNKNOWN_CRIT_EXTN): Removed definition as we now
+	require a decent libgpg-error.
+
+	* ocsp.c (ksba_ocsp_get_responder_id): Implemented.  Changed NAME
+	from ksba_name_t* to char** and SHA1KEYHASH from unsigned char* to
+	ksba_sexp_t*.  Given that the function has always returned an
+	not_implemented error code and thus was not useful at all, we
+	don't consider this as an ABI change (still pointers) and the API
+	change is not real as this function was never useful.
+
 2006-08-30  Werner Koch  <wk at g10code.com>
 
 	* ocsp.c (extract_nonce): New.

Modified: trunk/src/crl.c
===================================================================
--- trunk/src/crl.c	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/crl.c	2006-08-31 15:47:49 UTC (rev 254)
@@ -35,9 +35,6 @@
 #include "ber-decoder.h"
 #include "crl.h"
 
-#if !HAVE_DECL_GPG_ERR_UNKNOWN_CRIT_EXTN
-#define GPG_ERR_UNKNOWN_CRIT_EXTN  172
-#endif
 
 static const char oidstr_crlNumber[] = "2.5.29.20";
 static const char oidstr_crlReason[] = "2.5.29.21";

Modified: trunk/src/ksba-config.in
===================================================================
--- trunk/src/ksba-config.in	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ksba-config.in	2006-08-31 15:47:49 UTC (rev 254)
@@ -14,6 +14,8 @@
 cflags="@KSBA_CONFIG_CFLAGS@ @GPG_ERROR_CFLAGS@"
 prefix=@prefix@
 exec_prefix=@exec_prefix@
+api_version="@KSBA_CONFIG_API_VERSION@"
+
 includes=""
 libdirs=""
 exec_prefix_set=no
@@ -21,6 +23,7 @@
 echo_cflags=no
 echo_prefix=no
 echo_exec_prefix=no
+echo_api_version=no
 
 
 usage()
@@ -31,6 +34,7 @@
 	[--prefix[=DIR]]
 	[--exec-prefix[=DIR]]
 	[--version]
+        [--api-version]
 	[--libs]
 	[--cflags]
 EOF
@@ -68,6 +72,9 @@
       echo "@VERSION@"
       exit 0
       ;;
+    --api-version)
+      echo_api_version=yes
+      ;;
     --cflags)
       echo_cflags=yes
       ;;
@@ -89,6 +96,10 @@
     echo $exec_prefix
 fi
 
+if test "$echo_api_version" = "yes"; then
+    echo "$api_version"
+fi
+
 if test "$echo_cflags" = "yes"; then
     includes=""
     if test "@includedir@" != "/usr/include" ; then

Modified: trunk/src/ksba.h
===================================================================
--- trunk/src/ksba.h	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ksba.h	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,5 +1,5 @@
 /* ksba.h - X509 library for the Aegypten project
- *      Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
+ *      Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 g10 Code GmbH
  *
  * This file is part of KSBA.
  *
@@ -390,8 +390,8 @@
 ksba_sexp_t ksba_ocsp_get_sig_val (ksba_ocsp_t ocsp,
                                    ksba_isotime_t produced_at);
 gpg_error_t ksba_ocsp_get_responder_id (ksba_ocsp_t ocsp,
-                                        ksba_name_t *name,
-                                        unsigned char *sha1keyhash);
+                                        char **r_name,
+                                        ksba_sexp_t *r_keyid);
 ksba_cert_t ksba_ocsp_get_cert (ksba_ocsp_t ocsp, int idx);
 gpg_error_t ksba_ocsp_get_status (ksba_ocsp_t ocsp, ksba_cert_t cert,
                                   ksba_status_t *r_status,
@@ -402,7 +402,8 @@
 gpg_error_t ksba_ocsp_get_extension (ksba_ocsp_t ocsp, ksba_cert_t cert,
                                      int idx,
                                      char const **r_oid, int *r_crit,
-                                     size_t *r_deroff, size_t *r_derlen);
+                                     unsigned char const **r_der, 
+                                     size_t *r_derlen);
 
 
 /*-- certreq.c --*/

Modified: trunk/src/ksba.m4
===================================================================
--- trunk/src/ksba.m4	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ksba.m4	2006-08-31 15:47:49 UTC (rev 254)
@@ -13,6 +13,12 @@
 dnl AM_PATH_KSBA([MINIMUM-VERSION,
 dnl              [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
 dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
+dnl with the API version to also check the API compatibility. Example:
+dnl a MINIMUN-VERSION of 1:1.0.7 won't pass the test unless the installed 
+dnl version of libksba is at least 1.0.7 *and* the API number is 1.  Using
+dnl this features allows to prevent build against newer versions of libksba
+dnl with a changed API.
 dnl
 AC_DEFUN([AM_PATH_KSBA],
 [ AC_ARG_WITH(ksba-prefix,
@@ -27,7 +33,15 @@
   fi
 
   AC_PATH_PROG(KSBA_CONFIG, ksba-config, no)
-  min_ksba_version=ifelse([$1], ,0.4.4,$1)
+  tmp=ifelse([$1], ,1:1.0.0,$1)
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_ksba_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_ksba_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_ksba_api=0
+     min_ksba_version="$tmp"
+  fi
+
   AC_MSG_CHECKING(for KSBA - version >= $min_ksba_version)
   ok=no
   if test "$KSBA_CONFIG" != "no" ; then
@@ -61,14 +75,33 @@
     fi
   fi
   if test $ok = yes; then
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+  if test $ok = yes; then
+     # Even if we have a recent libksba, we should check that the
+     # API is compatible.
+     if test "$req_ksba_api" -gt 0 ; then
+        tmp=`$KSBA_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           AC_MSG_CHECKING([KSBA API version])
+           if test "$req_ksba_api" -eq "$tmp" ; then
+             AC_MSG_RESULT(okay)
+           else
+             ok=no
+             AC_MSG_RESULT([does not match.  want=$req_ksba_api got=$tmp.])
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
     KSBA_CFLAGS=`$KSBA_CONFIG $ksba_config_args --cflags`
     KSBA_LIBS=`$KSBA_CONFIG $ksba_config_args --libs`
-    AC_MSG_RESULT(yes)
     ifelse([$2], , :, [$2])
   else
     KSBA_CFLAGS=""
     KSBA_LIBS=""
-    AC_MSG_RESULT(no)
     ifelse([$3], , :, [$3])
   fi
   AC_SUBST(KSBA_CFLAGS)

Modified: trunk/src/ocsp.c
===================================================================
--- trunk/src/ocsp.c	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ocsp.c	2006-08-31 15:47:49 UTC (rev 254)
@@ -143,7 +143,44 @@
   return err;
 }
 
+
+/* Note that R_BOOL will only be set if a value has been given. Thus
+   the caller should set it to the default value prior to calling this
+   function.  Obviously no call to parse_skip is required after
+   calling this function. */
 static gpg_error_t
+parse_optional_boolean (unsigned char const **buf, size_t *len, int *r_bool)
+{
+  gpg_error_t err;
+  struct tag_info ti;
+
+  err = _ksba_ber_parse_tl (buf, len, &ti);
+  if (err)
+    ;
+  else if (!ti.length)
+    err = gpg_error (GPG_ERR_TOO_SHORT);
+  else if (ti.length > *len)
+    err = gpg_error (GPG_ERR_BAD_BER);
+  else if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BOOLEAN
+           && !ti.is_constructed)
+    { 
+      if (ti.length != 1)
+        err = gpg_error (GPG_ERR_BAD_BER);
+      *r_bool = !!**buf;
+      parse_skip (buf, len, &ti);
+    }
+  else
+    { /* Undo the read. */
+      *buf -= ti.nhdr;
+      *len += ti.nhdr;
+    }
+
+  return err;
+}
+
+
+
+static gpg_error_t
 parse_object_id_into_str (unsigned char const **buf, size_t *len, char **oid)
 {
   struct tag_info ti;
@@ -238,6 +275,18 @@
 }
 
 
+static void
+release_ocsp_extensions (struct ocsp_extension_s *ex)
+{
+  while (ex)
+    {
+      struct ocsp_extension_s *tmp = ex->next;
+      xfree (ex);
+      ex = tmp;
+    }
+}
+
+
 /* Release the OCSP object and all its resources. Passing NULL for
    OCSP is a valid nop. */
 void
@@ -254,10 +303,14 @@
       ocsp->requestlist = ri->next;
       ksba_cert_release (ri->cert);
       ksba_cert_release (ri->issuer_cert);
+      release_ocsp_extensions (ri->single_extensions);
       xfree (ri->serialno);
     }
   xfree (ocsp->sigval);
+  xfree (ocsp->responder_id.name);
+  xfree (ocsp->responder_id.keyid);
   release_ocsp_certlist (ocsp->received_certs);
+  release_ocsp_extensions (ocsp->response_extensions);
   xfree (ocsp);
 }
 
@@ -775,8 +828,10 @@
 
 
 
-/* Extract the nonce from the extension sequence.  A typical data
-   ASN.1 blob passed to this function is:
+/* 
+   Parse the response extensions and store them aways.  While doing
+   this we also check the nonce extension.  A typical data ASN.1 blob
+   with only the nonce extension as passed to this function is:
 
     SEQUENCE {
       SEQUENCE {
@@ -790,19 +845,24 @@
 */
 
 static int
-extract_nonce (ksba_ocsp_t ocsp, const unsigned char *data, size_t datalen)
+parse_response_extensions (ksba_ocsp_t ocsp,
+                          const unsigned char *data, size_t datalen)
 {
   gpg_error_t err;
   struct tag_info ti;
   size_t length;
   char *oid = NULL;
 
+  assert (!ocsp->response_extensions);
   err = parse_sequence (&data, &datalen, &ti);
   if (err)
     goto leave;
   length = ti.length;
   while (length)
     {
+      struct ocsp_extension_s *ex;
+      int is_crit;
+
       err = parse_sequence (&data, &datalen, &ti);
       if (err)
         goto leave;
@@ -817,6 +877,10 @@
       err = parse_object_id_into_str (&data, &datalen, &oid);
       if (err)
         goto leave;
+      is_crit = 0;
+      err = parse_optional_boolean (&data, &datalen, &is_crit);
+      if (err)
+        goto leave;
       err = parse_octet_string (&data, &datalen, &ti);
       if (err)
         goto leave;
@@ -831,6 +895,21 @@
           else
             ocsp->good_nonce = 1;
         }
+      ex = xtrymalloc (sizeof *ex + strlen (oid) + ti.length);
+      if (!ex)
+        {
+          err = gpg_error_from_errno (errno);
+          goto leave;
+        }
+      ex->crit = is_crit;
+      strcpy (ex->data, oid);
+      ex->data[strlen (oid)] = 0;
+      ex->off = strlen (oid) + 1;
+      ex->len = ti.length;
+      memcpy (ex->data + ex->off, data, ti.length);
+      ex->next = ocsp->response_extensions;
+      ocsp->response_extensions = ex;
+
       parse_skip (&data, &datalen, &ti); /* Skip the octet string / integer. */
     }
 
@@ -840,6 +919,73 @@
 }
 
 
+/* 
+   Parse single extensions and store them away.
+*/
+static int
+parse_single_extensions (struct ocsp_reqitem_s *ri,
+                         const unsigned char *data, size_t datalen)
+{
+  gpg_error_t err;
+  struct tag_info ti;
+  size_t length;
+  char *oid = NULL;
+
+  assert (ri && !ri->single_extensions);
+  err = parse_sequence (&data, &datalen, &ti);
+  if (err)
+    goto leave;
+  length = ti.length;
+  while (length)
+    {
+      struct ocsp_extension_s *ex;
+      int is_crit;
+
+      err = parse_sequence (&data, &datalen, &ti);
+      if (err)
+        goto leave;
+      if (length < ti.nhdr + ti.length)
+        {
+          err = gpg_error (GPG_ERR_BAD_BER);
+          goto leave;
+        }
+      length -= ti.nhdr + ti.length;
+
+      xfree (oid);
+      err = parse_object_id_into_str (&data, &datalen, &oid);
+      if (err)
+        goto leave;
+      is_crit = 0;
+      err = parse_optional_boolean (&data, &datalen, &is_crit);
+      if (err)
+        goto leave;
+      err = parse_octet_string (&data, &datalen, &ti);
+      if (err)
+        goto leave;
+      ex = xtrymalloc (sizeof *ex + strlen (oid) + ti.length);
+      if (!ex)
+        {
+          err = gpg_error_from_errno (errno);
+          goto leave;
+        }
+      ex->crit = is_crit;
+      strcpy (ex->data, oid);
+      ex->data[strlen (oid)] = 0;
+      ex->off = strlen (oid) + 1;
+      ex->len = ti.length;
+      memcpy (ex->data + ex->off, data, ti.length);
+      ex->next = ri->single_extensions;
+      ri->single_extensions = ex;
+
+      parse_skip (&data, &datalen, &ti); /* Skip the octet string / integer. */
+    }
+
+ leave:
+  xfree (oid);
+  return err;
+}
+
+
 /* Parse the first part of a response:
 
      OCSPResponse ::= SEQUENCE {
@@ -1178,7 +1324,13 @@
     return gpg_error (GPG_ERR_BAD_BER);
   if (ti.class == CLASS_CONTEXT && ti.tag == 1  && ti.is_constructed)
     {
-      parse_skip (data, datalen, &ti); /* FIXME */
+      if (request_item)
+        {
+          err = parse_single_extensions (request_item, *data, ti.length);
+          if (err)
+            return err;
+        }
+      parse_skip (data, datalen, &ti);
     }
   else
     err = gpg_error (GPG_ERR_INV_OBJ);
@@ -1232,6 +1384,8 @@
     }
 
   /* The responderID field. */
+  assert (!ocsp->responder_id.name);
+  assert (!ocsp->responder_id.keyid);
   err = _ksba_ber_parse_tl (data, datalen, &ti);
   if (err)
     return err;
@@ -1239,11 +1393,24 @@
     return gpg_error (GPG_ERR_BAD_BER);
   else if (ti.class == CLASS_CONTEXT && ti.tag == 1  && ti.is_constructed)
     { /* byName. */
-      parse_skip (data, datalen, &ti);  /* FIXME */
+      err = _ksba_derdn_to_str (*data, ti.length, &ocsp->responder_id.name);
+      if (err)
+        return err; 
+      parse_skip (data, datalen, &ti);
     }
   else if (ti.class == CLASS_CONTEXT && ti.tag == 2  && ti.is_constructed)
     { /* byKey. */
-      parse_skip (data, datalen, &ti);  /* FIXME */
+      err = parse_octet_string (data, datalen, &ti);
+      if (err)
+        return err;
+      if (!ti.length)
+        return gpg_error (GPG_ERR_INV_OBJ); /* Zero length key id.  */
+      ocsp->responder_id.keyid = xtrymalloc (ti.length);
+      if (!ocsp->responder_id.keyid)
+        return gpg_error_from_errno (errno);
+      memcpy (ocsp->responder_id.keyid, *data, ti.length);
+      ocsp->responder_id.keyidlen = ti.length;
+      parse_skip (data, datalen, &ti); 
     }
   else
     err = gpg_error (GPG_ERR_INV_OBJ);
@@ -1274,7 +1441,7 @@
   err = parse_context_tag (data, datalen, &ti, 1);
   if (!err)
     {
-      err = extract_nonce (ocsp, *data, ti.length);
+      err = parse_response_extensions (ocsp, *data, ti.length);
       if (err)
         return err;
       parse_skip (data, datalen, &ti);
@@ -1439,16 +1606,20 @@
   if (!ocsp->requestlist)
     return gpg_error (GPG_ERR_MISSING_ACTION);
 
+  /* Reset the fields used to track the response.  This is so that we
+     can use the parse function a second time for the same
+     request. This is useful in case of a TryLater response status. */
   ocsp->response_status = KSBA_OCSP_RSPSTATUS_NONE;
   release_ocsp_certlist (ocsp->received_certs);
+  release_ocsp_extensions (ocsp->response_extensions);
   ocsp->received_certs = NULL;
   ocsp->hash_length = 0;
   ocsp->bad_nonce = 0;
   ocsp->good_nonce = 0;
-
-  /* Reset the fields used to track the response.  This is so that we
-     can use the parse function a second time for the same
-     request. This is useful in case of a TryLater response status. */
+  xfree (ocsp->responder_id.name);
+  ocsp->responder_id.name = NULL;
+  xfree (ocsp->responder_id.keyid);
+  ocsp->responder_id.keyid = NULL;
   for (ri=ocsp->requestlist; ri; ri = ri->next)
     {
       ri->status = KSBA_STATUS_NONE;
@@ -1456,8 +1627,10 @@
       *ri->next_update = 0;
       *ri->revocation_time = 0;
       ri->revocation_reason = 0;
+      release_ocsp_extensions (ri->single_extensions);
     }
 
+  /* Run the actual parser.  */
   err = parse_response (ocsp, msg, msglen);
   *response_status = ocsp->response_status;
 
@@ -1534,21 +1707,50 @@
 }
 
 
-/* Return the responder ID for the current response into NAME or into
-   the provided 20 byte buffer SHA1KEYHASH.  On sucess NAME either
-   contains the responder ID as a standard name or if NAME is NULL,
-   SHA1KEYHASH contains the hash of the public key.  SHA1KEYHASH may
-   be given as NULL if support for a KEYHASH is not intended.  Caller
-   must release NAME. */
+/* Return the responder ID for the current response into R_NAME or
+   into R_KEYID.  On sucess either R_NAME or R_KEYID will receive an
+   allocated object.  If R_NAME or R_KEYID has been passed as NULL but
+   a value is available the errorcode GPG_ERR_NO_DATA is returned.
+   Caller must release the values stored at R_NAME or R_KEYID; the
+   function stores NULL tehre in case of an error.  */
 gpg_error_t
 ksba_ocsp_get_responder_id (ksba_ocsp_t ocsp,
-                            ksba_name_t *name, unsigned char *sha1keyhash)
+                            char **r_name, ksba_sexp_t *r_keyid)
 {
+  if (r_name)
+    *r_name = NULL;
+  if (r_keyid)
+    *r_keyid = NULL;
+
   if (!ocsp)
     return gpg_error (GPG_ERR_INV_VALUE);
 
+  if (ocsp->responder_id.name && r_name)
+    {
+      *r_name = xtrystrdup (ocsp->responder_id.name);
+      if (!*r_name)
+        return gpg_error_from_errno (errno);
+    }
+  else if (ocsp->responder_id.keyid && r_keyid)
+    {
+      char numbuf[50];
+      size_t numbuflen;
 
-  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+      sprintf (numbuf,"(%lu:", (unsigned long)ocsp->responder_id.keyidlen);
+      numbuflen = strlen (numbuf);
+      *r_keyid = xtrymalloc (numbuflen + ocsp->responder_id.keyidlen + 2);
+      if (!*r_keyid)
+        return gpg_error_from_errno (errno);
+      strcpy (*r_keyid, numbuf);
+      memcpy (*r_keyid+numbuflen,
+              ocsp->responder_id.keyid, ocsp->responder_id.keyidlen);
+      (*r_keyid)[numbuflen + ocsp->responder_id.keyidlen] = ')';
+      (*r_keyid)[numbuflen + ocsp->responder_id.keyidlen + 1] = 0;
+    }
+  else
+    gpg_error (GPG_ERR_NO_DATA);
+  
+  return 0;
 }
 
 
@@ -1628,40 +1830,56 @@
 }
 
 
+/* WARNING: The returned values ares only valid as long as no other
+   ocsp function is called on the same context.  */
 gpg_error_t
 ksba_ocsp_get_extension (ksba_ocsp_t ocsp, ksba_cert_t cert, int idx,
                          char const **r_oid, int *r_crit,
-                         size_t *r_deroff, size_t *r_derlen)
+                         unsigned char const **r_der, size_t *r_derlen)
 {
-  gpg_error_t err;
+  struct ocsp_extension_s *ex;
 
   if (!ocsp)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (!ocsp->requestlist)
     return gpg_error (GPG_ERR_MISSING_ACTION);
+  if (idx < 0)
+    return gpg_error (GPG_ERR_INV_INDEX);
 
   if (cert)
     {
       /* Return extensions for the certificate (singleExtensions).  */
-/*       for (ri=ocsp->requestlist; ri; ri = ri->next) */
-/*         if (ri->cert == cert) */
-/*           break; */
-/*       if (!ri) */
-/*         return gpg_error (GPG_ERR_NOT_FOUND); */
+      struct ocsp_reqitem_s *ri;
 
-
+      for (ri=ocsp->requestlist; ri; ri = ri->next)
+        if (ri->cert == cert)
+          break;
+      if (!ri)
+        return gpg_error (GPG_ERR_NOT_FOUND);
+      
+      for (ex=ri->single_extensions; ex && idx; ex = ex->next, idx--)
+        ;
+      if (!ex)
+        return gpg_error (GPG_ERR_EOF); /* No more extensions. */
     }
   else
     {
       /* Return extensions for the response (responseExtensions).  */
-
-
-
+      for (ex=ocsp->response_extensions; ex && idx; ex = ex->next, idx--)
+        ;
+      if (!ex)
+        return gpg_error (GPG_ERR_EOF); /* No more extensions. */
     }
 
-  return gpg_error (GPG_ERR_EOF); 
+  if (r_oid)
+    *r_oid = ex->data;
+  if (r_crit)
+    *r_crit = ex->crit;
+  if (r_der)
+    *r_der = ex->data + ex->off;
+  if (r_derlen)
+    *r_derlen = ex->len;
 
-/*   if (idx < 0 || idx >= cert->cache.n_extns) */
-/*     return gpg_error (GPG_ERR_INV_INDEX); */
+  return 0;
 }
 

Modified: trunk/src/ocsp.h
===================================================================
--- trunk/src/ocsp.h	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/src/ocsp.h	2006-08-31 15:47:49 UTC (rev 254)
@@ -25,6 +25,25 @@
 #include "ksba.h"
 
 
+
+/* A structure to store certificates read from a response. */
+struct ocsp_certlist_s {
+  struct ocsp_certlist_s *next;
+  ksba_cert_t cert;
+};
+
+/* A structre to save a way extensions. */
+struct ocsp_extension_s 
+{
+  struct ocsp_extension_s *next;
+  size_t off;    /* Offset into DATA to the content of the octet string.  */
+  size_t len;    /* Length of the octet string. */
+  int crit;      /* IsCritical flag. */
+  char data[1];  /* This is made up of the OID string followed by the
+                    actual DER data of the extension. */
+};
+
+
 /* A structure to keep a information about a single status request. */
 struct ocsp_reqitem_s {
   struct ocsp_reqitem_s *next;
@@ -44,17 +63,9 @@
   ksba_status_t  status;               /* Set to the status of the target. */
   ksba_isotime_t revocation_time;      /* The indicated revocation time. */
   ksba_crl_reason_t revocation_reason; /* The reason given for revocation. */
+  struct ocsp_extension_s *single_extensions; /* List of extensions. */
 };
 
-
-/* A structure to store certificates read from a response. */
-struct ocsp_certlist_s {
-  struct ocsp_certlist_s *next;
-  ksba_cert_t cert;
-};
-
-
-
 /* A structure used as context for the ocsp subsystem. */
 struct ksba_ocsp_s {
   char *digest_oid;        /* The OID of the digest algorithm to be
@@ -68,8 +79,6 @@
                                increased, check that the created
                                request will still be valid as we use a
                                hacked implementation. */
-  int bad_nonce;            /* The nonce does not match the request. */
-  int good_nonce;           /* The nonce does match the request. */
 
   unsigned char *request_buffer; /* Internal buffer to build the request. */
   size_t request_buflen;
@@ -82,6 +91,14 @@
   ksba_isotime_t produced_at;  /* The time the response was signed. */
   struct ocsp_certlist_s *received_certs; /* Certificates received in
                                              the response. */
+  struct ocsp_extension_s *response_extensions; /* List of extensions. */
+  int bad_nonce;            /* The nonce does not match the request. */
+  int good_nonce;           /* The nonce does match the request. */
+  struct {
+    char *name;             /* Allocated DN. */
+    char *keyid;            /* Allocated key ID. */
+    size_t keyidlen;        /* length of the KeyID. */
+  } responder_id;           /* The reponder ID from the response. */
 };
 
 

Modified: trunk/tests/ChangeLog
===================================================================
--- trunk/tests/ChangeLog	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/tests/ChangeLog	2006-08-31 15:47:49 UTC (rev 254)
@@ -1,3 +1,9 @@
+2006-08-31  Werner Koch  <wk at g10code.com>
+
+	* t-ocsp.c (one_response): Print the responder id.
+	(one_response): Print extension info.
+	(get_oid_desc): New.
+
 2006-08-30  Werner Koch  <wk at g10code.com>
 
 	* t-ocsp.c (one_response): Build the test request with the same nonce.

Modified: trunk/tests/t-common.h
===================================================================
--- trunk/tests/t-common.h	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/tests/t-common.h	2006-08-31 15:47:49 UTC (rev 254)
@@ -80,7 +80,7 @@
 
 
 void
-print_hex (unsigned char *p, size_t n)
+print_hex (const unsigned char *p, size_t n)
 {
   if (!p)
     fputs ("none", stdout);

Modified: trunk/tests/t-ocsp.c
===================================================================
--- trunk/tests/t-ocsp.c	2006-08-30 20:39:53 UTC (rev 253)
+++ trunk/tests/t-ocsp.c	2006-08-31 15:47:49 UTC (rev 254)
@@ -32,11 +32,28 @@
 
 
 #include "t-common.h"
+#include "oidtranstbl.h"
 
+
 int verbose;
 int debug;
 int no_nonce;
 
+/* Return the description for OID; if no description is available 
+   NULL is returned. */
+static const char *
+get_oid_desc (const char *oid)
+{
+  int i;
+
+  if (oid)
+    for (i=0; oidtranstbl[i].oid; i++)
+      if (!strcmp (oidtranstbl[i].oid, oid))
+        return oidtranstbl[i].desc;
+  return NULL;
+}
+
+
 static unsigned char *
 read_file (const char *fname, size_t *r_length)
 {
@@ -210,16 +227,26 @@
       ksba_crl_reason_t reason;
       ksba_isotime_t this_update, next_update, revocation_time, produced_at;
       ksba_sexp_t sigval;
+      char *name;
+      ksba_sexp_t keyid;
 
+      err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid);
+      fail_if_err (err);
+      printf ("responder id .....: ");
+      if (name)
+        printf ("`%s'", name);
+      else
+        print_sexp (keyid);
+      putchar ('\n');
+      ksba_free (name);
+      ksba_free (keyid);
+
       sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
       printf ("signature value ..: ");
       print_sexp (sigval);
       printf ("\nproduced at ......: ");
       print_time (produced_at);
       putchar ('\n');
-      
-
-
       err = ksba_ocsp_get_status (ocsp, cert,
                                   &status, this_update, next_update,
                                   revocation_time, &reason);
@@ -264,6 +291,45 @@
           ksba_cert_release (acert);
         printf ("extra certificates: %d\n", cert_idx );
       }
+
+      {
+        int idx, crit;
+        const char *oid;
+        const unsigned char *der;
+        size_t derlen;
+        
+        for (idx=0; !(err=ksba_ocsp_get_extension (ocsp, NULL, idx,
+                                                   &oid, &crit,
+                                                   &der, &derlen)); idx++)
+          {
+            const char *s = get_oid_desc (oid);
+            printf ("%sresp-extn ..%s: %s%s%s%s  (",
+                    crit? "crit. ":"", 
+                    crit?"":"......", 
+                    s?"(":"", s?s:"", s?") ":"", oid);
+            print_hex (der, derlen);
+            putchar (')');
+            putchar ('\n');
+          }
+        if (err && gpg_err_code (err) != GPG_ERR_EOF)
+          fail_if_err (err);
+
+        for (idx=0; !(err=ksba_ocsp_get_extension (ocsp, cert, idx,
+                                                   &oid, &crit,
+                                                   &der, &derlen)); idx++)
+          {
+            const char *s = get_oid_desc (oid);
+            printf ("%ssngl-extn ..%s: %s%s%s%s  (",
+                    crit? "crit. ":"", 
+                    crit?"":"......", 
+                    s?"(":"", s?s:"", s?") ":"", oid);
+            print_hex (der, derlen);
+            putchar (')');
+            putchar ('\n');
+          }
+        if (err && gpg_err_code (err) != GPG_ERR_EOF)
+          fail_if_err (err);
+      }
     }
   
 




More information about the Gnupg-commits mailing list