Added user data feature for ksba_cert_t
authorWerner Koch <wk@gnupg.org>
Fri, 11 Nov 2005 15:32:08 +0000 (15:32 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 11 Nov 2005 15:32:08 +0000 (15:32 +0000)
NEWS
configure.ac
doc/ksba.texi
src/ChangeLog
src/cert.c
src/cert.h
src/libksba.vers
src/util.c

diff --git a/NEWS b/NEWS
index cfff26b..00662fe 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+Noteworthy changes in version 0.9.13
+-------------------------------------------------
+
+ * New functions to associate user data with a certificate object.
+
+ * Interface changes relative to the 0.9.12 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ksba_cert_set_user_data        NEW
+ ksba_cert_get_user_data        NEW
+
+
 Noteworthy changes in version 0.9.12 (2005-08-01)
 -------------------------------------------------
 
index 007af57..9f3bc07 100644 (file)
@@ -23,7 +23,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.12, gpa-dev@gnupg.org)
+AC_INIT(libksba, 0.9.13-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 ce3e39b..79eb94b 100644 (file)
@@ -119,6 +119,7 @@ Certificate Handling
 * Creating certificates::       How to create a certificate object.
 * Retrieving attributes::       How to get the attributes of a certificate.
 * Setting attributes::          How to set certicates attributes.
+* User data::                   How to associate other data with a certificate.
 
 Mastering the Cryptographic Message Syntax
 
@@ -170,7 +171,7 @@ Anybody can use, modify, and redistribute it under the terms of the GNU
 General Public License (@pxref{Copying}).
 
 @item It hides the low level stuff
-`KSBA' a higlevel interface to the implemented protocols and presents
+`KSBA' a highlevel interface to the implemented protocols and presents
 the data in a consistent way.  There is no more need to worry about all
 the nasty details of the protocols.  The API gives the C programmer a
 more usual way of interacting with the data.
@@ -316,6 +317,7 @@ an S-expression is intrinsic available.
 * Creating certificates::       How to create a certificate object.
 * Retrieving attributes::       How to get the attributes of a certificate.
 * Setting attributes::          How to set certicates attributes.
+* User data::                   How to associate other data with a certificate.
 @end menu
 
 
@@ -657,6 +659,49 @@ See RFC-2459, section 4.2.2.2 for the defintion of this attribute.
 
 [This needs to be written.  For example code see newpg/sm/sign.c]
 
+@node User data
+@section How to associate other data with a certificate.
+
+Certificate objects play a central role in many applications and often
+it is desirable to associate other data with the certificate to avoid
+wrapping the certificate object into an own object.  `KSBA' provides a
+mechanism for this by means of two functions:
+
+@deftypefun gpg_error_t ksba_cert_set_user_data (@w{ksba_cert_t @var{cert}, const char *@var{key}, const void *@var{data}, size_t @var{datalen}})
+
+
+Stores arbitrary data along with a certificate.  The data is expected in
+the buffer @var{data} of length @var{datalen}. It will be stored under
+the string @var{key}.  If data is already stored under this key it will
+be replaced by the new data. Using @code{NULL} for @var{data} will
+effectivly delete the data.
+
+On error (i.e. out of memory) an already existing data object
+stored under @var{key} may get deleted.
+
+@strong{Caution:} This function is definitely not thread safe because we
+don't employ any locking mechanisms.
+@end deftypefun
+
+
+@deftypefun gpg_error_t ksba_cert_get_user_data (@w{ksba_cert_t @var{cert},} @w{const char *@var{key},} @w{void *@var{buffer},} @w{size_t @var{bufferlen},} @w{size_t *@var{datalen}})
+
+Return user data for certificate @var{cert} stored under the string
+@var{key}. The caller needs to provide a suitable large @var{buffer} and
+the usable length of this buffer in @var{bufferlen}.  If @var{datalen}
+is not @code{NULL}, the length of the data stored in @var{buffer} will
+be stored there.
+
+If @var{buffer} is given as @code{NULL}, @var{bufferlen} will be ignored
+and the required length of the buffer will be returned at @var{datalen}.
+
+On success 0 is returned.  If no data is stored under thengiven key,
+@code{GPG_ERR_NOT_FOUND} is returned.  If the provided buffer is too
+short and @var{buffer} is not @code{NULL},
+@code{GPG_ERR_BUFFER_TOO_SHORT} will be returned.
+@end deftypefun
+
+
 \f
 @node CMS
 @chapter Mastering the Cryptographic Message Syntax
index 290917f..8aeb736 100644 (file)
@@ -1,3 +1,11 @@
+2005-11-11  Werner Koch  <wk@g10code.com>
+
+       * cert.h (struct cert_user_data): New.
+       (struct ksba_cert_s): New field UDATA.
+       * cert.c (ksba_cert_release): Release the UDATA list.
+       (ksba_cert_set_user_data, ksba_cert_get_user_data): New.
+       * libksba.vers:  Add the new functions.
+
 2005-09-28  Marcus Brinkmann  <marcus@g10code.de>
 
        * Makefile.am (AM_CCPFLAGS): Renamed to AM_CPPFLAGS.
index 53d2955..e44c707 100644 (file)
@@ -1,4 +1,4 @@
-/* cert.c - main function for the certificate handling
+g/* cert.c - main function for the certificate handling
  *      Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
  *
  * This file is part of KSBA.
@@ -95,6 +95,21 @@ ksba_cert_release (ksba_cert_t cert)
   if (--cert->ref_count)
     return;
 
+  if (cert->udata)
+    {
+      struct cert_user_data *ud = cert->udata;
+      cert->udata = NULL;  
+      do
+        {
+          struct cert_user_data *ud2 = ud->next;
+          if (ud->data && ud->data != ud->databuf)
+            xfree (ud->data);
+          xfree (ud);
+          ud = ud2;
+        }
+      while (ud);
+    }
+  
   xfree (cert->cache.digest_algo);
   if (cert->cache.extns_valid)
     {
@@ -103,11 +118,123 @@ ksba_cert_release (ksba_cert_t cert)
       xfree (cert->cache.extns);
     }
 
+
   /* FIXME: release cert->root, ->asn_tree */
   xfree (cert);
 }
 
 
+/* Store arbitrary data along with a certificate.  The DATA of length
+   DATALEN will be stored under the string KEY.  If some data is
+   already stored under this key it will be replaced by the new data.
+   Using NULL for DATA will effectivly delete the data.
+
+   On error (i.e. out or memory) an already existing data object
+   stored under KEY may get deleted.
+
+   This function is not thread safe because we don't have employ any
+   locking. */
+gpg_error_t
+ksba_cert_set_user_data (ksba_cert_t cert,
+                         const char *key, const void *data, size_t datalen)
+{
+  struct cert_user_data *ud;
+
+  if (!cert || !key || !*key)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  for (ud=cert->udata; ud; ud = ud->next)
+    if (!strcmp (ud->key, key))
+      break;
+  if (ud)  /* Update the data stored under this key or reuse this item. */
+    {
+      if (ud->data && ud->data != ud->databuf)
+        xfree (ud->data);
+      ud->data = NULL;
+      if (data && datalen <= sizeof ud->databuf)
+        {
+          memcpy (ud->databuf, data, datalen);
+          ud->data = ud->databuf;
+          ud->datalen = datalen;
+        }
+      else if (data)
+        {
+          ud->data = xtrymalloc (datalen);
+          if (!ud->data)
+            return gpg_error_from_errno (errno);
+          memcpy (ud->data, data, datalen);
+          ud->datalen = datalen;
+        }
+    }
+  else if (data) /* Insert as a new item. */
+    {
+      ud = xtrycalloc (1, sizeof *ud + strlen (key));
+      if (!ud->data)
+        return gpg_error_from_errno (errno);
+      strcpy (ud->key, key);
+      if (datalen <= sizeof ud->databuf)
+        {
+          memcpy (ud->databuf, data, datalen);
+          ud->data = ud->databuf;
+          ud->datalen = datalen;
+        }
+      else
+        {
+          ud->data = xtrymalloc (datalen);
+          if (!ud->data)
+            {
+              xfree (ud);
+              return gpg_error_from_errno (errno);
+            }
+          memcpy (ud->data, data, datalen);
+          ud->datalen = datalen;
+        }
+    }
+
+  return 0;
+}
+
+
+
+/* Return user data for certificate CERT stored under the string
+   KEY. The caller needs to provide a suitable large BUFFER and pass
+   the usable length of the buffer in BUFFERLEN.  If DATALEN is not
+   NULL, the length of the data stored at BUFFER will be stored there.
+
+   If BUFFER is NULL, BUFFERLEN will be ignored and the required
+   length of the buffer will be returned at DATALEN.
+
+   On success 0 is returned.  If no data is stored under KEY
+   GPG_ERR_NOT_FOUND is returned.  If the provided buffer is too
+   short, GPG_ERR_BUFFER_TOO_SHORT will be returned (note, that this
+   is not the case if BUFFER is NULL).
+*/
+gpg_error_t
+ksba_cert_get_user_data (ksba_cert_t cert, const char *key,
+                         void *buffer, size_t bufferlen, size_t *datalen)
+{
+  struct cert_user_data *ud;
+
+  if (!cert || !key || !*key)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  for (ud=cert->udata; ud; ud = ud->next)
+    if (!strcmp (ud->key, key))
+      break;
+  if (!ud || !ud->data)
+    return gpg_error (GPG_ERR_NOT_FOUND);
+  if (datalen)
+    *datalen = ud->datalen;
+  if (buffer)
+    {
+      if (ud->datalen > bufferlen)
+        return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
+      memcpy (buffer, ud->data, ud->datalen);
+    }
+  return 0;
+}
+
+
 /**
  * ksba_cert_read_der:
  * @cert: An unitialized certificate object
index 0b1333a..d103168 100644 (file)
 
 #include "asn1-func.h"
 
-
-struct cert_extn_info {
+/* An object to keep parsed information about an extension. */
+struct cert_extn_info 
+{
   char *oid;
   int crit;
   int off, len;
 };
 
 
-struct ksba_cert_s {
-  int initialized;
+/* An object to store user supplied data to be associated with a
+   certificates.  This is implemented as a linked list with the
+   constrained that a given key may only occur once. */
+struct cert_user_data
+{
+  struct cert_user_data *next;  /* Link to next item. */
+
+  /* The length of the data store at DATA. */
+  size_t datalen;
+
+  /* The stored data.  This is either malloced storage or points to
+     DATABUF below.  If it is NULL, no data is actually stored under
+     the key. */
+  void *data;
+
+ /* Often we need to store only a few bytes as data.  By providing a
+    fixed buffer we are able to avoid an extra malloc in this case. */
+  char databuf[sizeof (int)];  
+
+  /* The key used to store the data object.  Dynamically allocated at
+     object creation time.  */
+  char key[1];
+};
+
+
+/* The internal certificate object. */
+struct ksba_cert_s 
+{
+  /* Certificate objects often play a central role and applications
+     might want to associate other data with the certificate to avoid
+     wrapping the certificate object into an own object.  This UDATA
+     linked list provides the means to do that.  It gets accessed by
+     ksba_cert_set_user_data and ksba_cert_get_user_data.  */
+  struct cert_user_data *udata;
+
+  /* This object has been initialized with an actual certificate.
+     Note that UDATA may be used even without an initialized
+     certificate. */
+  int initialized;    
+
+  /* Because we often need to pass certificate objects to other
+     functions, we use reference counting to keep resource overhead
+     low.  Note, that this object usually gets only read and not
+     modified. */
   int ref_count;
+
   ksba_asn_tree_t asn_tree;
-  AsnNode root;  /* root of the tree with the values */
+  AsnNode root;              /* Root of the tree with the values */
+
   unsigned char *image;
   size_t imagelen;
+
   gpg_error_t last_error;
   struct {
     char *digest_algo;
@@ -48,6 +94,8 @@ struct ksba_cert_s {
 };
 
 
+/*** Internal functions ***/
+
 int _ksba_cert_cmp (ksba_cert_t a, ksba_cert_t b);
 
 gpg_error_t _ksba_cert_get_serial_ptr (ksba_cert_t cert,
index 67858f9..5d67fb7 100644 (file)
@@ -37,6 +37,7 @@ KSBA_0.9 {
     ksba_cert_read_der; ksba_cert_ref; ksba_cert_release;
     ksba_cert_get_authority_info_access; ksba_cert_get_subject_info_access;
     ksba_cert_get_subj_key_id;
+    ksba_cert_set_user_data; ksba_cert_get_user_data;
 
     ksba_certreq_add_subject; ksba_certreq_build; ksba_certreq_new;
     ksba_certreq_release; ksba_certreq_set_hash_function; 
index ffc385b..b56ed5b 100644 (file)
@@ -37,6 +37,8 @@ static void *hash_buffer_fnc_arg;
 
 
 
+/* Note, that we expect that the free fucntion does not change
+   ERRNO. */
 void
 ksba_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
                         void *(*new_realloc_func)(void *p, size_t n),