* keybox-search.c (blob_cmp_name): Kludge to allow searching for
authorWerner Koch <wk@gnupg.org>
Thu, 13 Dec 2001 13:10:58 +0000 (13:10 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 13 Dec 2001 13:10:58 +0000 (13:10 +0000)
more than one name.
(has_subject_or_alt): New.
(blob_cmp_mail): New.
(has_mail): New.
(keybox_search): Implemented exact search and exact mail search.

* kbx/keybox-blob.c (_keybox_create_x509_blob): Insert alternate
names.

kbx/ChangeLog [new file with mode: 0644]
kbx/keybox-blob.c
kbx/keybox-errors.c
kbx/keybox-search.c
kbx/keybox.h

diff --git a/kbx/ChangeLog b/kbx/ChangeLog
new file mode 100644 (file)
index 0000000..8451dd2
--- /dev/null
@@ -0,0 +1,23 @@
+2001-12-13  Werner Koch  <wk@gnupg.org>
+
+       * keybox-search.c (blob_cmp_name): Kludge to allow searching for
+       more than one name.
+       (has_subject_or_alt): New.
+       (blob_cmp_mail): New.
+       (has_mail): New.
+       (keybox_search): Implemented exact search and exact mail search.
+
+       * kbx/keybox-blob.c (_keybox_create_x509_blob): Insert alternate
+       names.
+
+
+ Copyright 2001 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
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+       
\ No newline at end of file
index 84ebc90..18503a5 100644 (file)
@@ -774,9 +774,11 @@ int
 _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
                           unsigned char *sha1_digest)
 {
-  int rc = 0;
+  int i, rc = 0;
   KEYBOXBLOB blob;
   unsigned char *p;
+  unsigned char **names = NULL;
+  size_t max_names;
 
   *r_blob = NULL;
   blob = xtrycalloc (1, sizeof *blob);
@@ -790,10 +792,43 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
       blob->seriallen = n;
       blob->serial = p;
     }
-      
 
   blob->nkeys = 1;
-  blob->nuids = 2; /* issuer and subject - fixme: count alternate names */
+
+  /* create list of names */
+  blob->nuids = 0;
+  max_names = 100;
+  names = xtrymalloc (max_names * sizeof *names);
+  if (!names)
+    {
+      rc = KEYBOX_Out_Of_Core;
+      goto leave;
+    }
+  p = ksba_cert_get_issuer (cert, 0);
+  if (!p)
+    {
+      rc =  KEYBOX_Missing_Value;
+      goto leave;
+    }
+  names[blob->nuids++] = p;
+  for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
+    {
+      if (blob->nuids >= max_names)
+        {
+          unsigned char **tmp;
+          
+          max_names += 100;
+          tmp = xtryrealloc (names, max_names * sizeof *names);
+          if (!tmp)
+            {
+              rc = KEYBOX_Out_Of_Core;
+              goto leave;
+            }
+        }
+      names[blob->nuids++] = p;
+    }
+  
+  /* space for signature information */
   blob->nsigs = 1; 
 
   blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
@@ -809,21 +844,17 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
   blob->keys[0].off_kid = 0; /* We don't have keyids */
   blob->keys[0].flags = 0;
 
-  /* issuer */
-  p = ksba_cert_get_issuer (cert);
-  blob->uids[0].name = p;
-  blob->uids[0].len = p? (strlen(p)+1):0;
-  blob->uids[0].flags = 0;
-  blob->uids[0].validity = 0;
-
-  /* subject */
-  p = ksba_cert_get_subject (cert);
-  blob->uids[1].name = p;
-  blob->uids[1].len = p? (strlen(p)+1):0;
-  blob->uids[1].flags = 0;
-  blob->uids[1].validity = 0;
-
-  /* fixme: add alternate names */
+  /* issuer and subject names */
+  for (i=0; i < blob->nuids; i++)
+    {
+      blob->uids[i].name = names[i];
+      blob->uids[i].len = strlen(names[i]);
+      names[i] = NULL;
+      blob->uids[i].flags = 0;
+      blob->uids[i].validity = 0;
+    }
+  xfree (names);
+  names = NULL;
 
   /* signatures */
   blob->sigs[0] = 0;   /* not yet checked */
@@ -849,6 +880,12 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
  leave:
   release_kid_list (blob->temp_kids);
   blob->temp_kids = NULL;
+  if (blob && names)
+    {
+      for (i=0; i < blob->nuids; i++)
+        xfree (names[i]); 
+    }
+  xfree (names);
   if (rc)
     {
       _keybox_release_blob (blob);
index e75373c..e11efc1 100644 (file)
@@ -38,6 +38,7 @@ keybox_strerror (KeyboxError err)
     case KEYBOX_File_Close_Error: s="file close error"; break;
     case KEYBOX_Nothing_Found: s="nothing found"; break;
     case KEYBOX_Wrong_Blob_Type: s="wrong blob type"; break;
+    case KEYBOX_Missing_Value: s="missing value"; break;
     default:  sprintf (buf, "ec=%d", err ); s=buf; break;
     }
 
index 23543ec..e168d2b 100644 (file)
@@ -102,6 +102,7 @@ blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn)
   return nserial == snlen && !memcmp (buffer+off, sn, snlen);
 }
 
+
 static int
 blob_cmp_name (KEYBOXBLOB blob, int idx, const char *name, size_t namelen)
 {
@@ -139,18 +140,105 @@ blob_cmp_name (KEYBOXBLOB blob, int idx, const char *name, size_t namelen)
   if (pos + uidinfolen*nuids > length)
     return 0; /* out of bounds */
 
-  if (idx > nuids)
-    return 0; /* no user ID with that idx */
-  pos += idx*uidinfolen;
-  off = get32 (buffer+pos);
-  len = get32 (buffer+pos+4);
-  if (off+len > length)
+  if (idx < 0)
+    { /* compare all names starting with that (negated) index */
+      idx = -idx;
+      
+      for ( ;idx < nuids; idx++)
+        {
+          size_t mypos = pos;
+
+          mypos += idx*uidinfolen;
+          off = get32 (buffer+mypos);
+          len = get32 (buffer+mypos+4);
+          if (off+len > length)
+            return 0; /* error: better stop here out of bounds */
+          if (len < 2)
+            continue; /* empty name or 0 not stored */
+          len--;
+          if (len == namelen && !memcmp (buffer+off, name, len))
+            return 1; /* found */
+        }
+      return 0; /* not found */
+    }
+  else
+    {
+      if (idx > nuids)
+        return 0; /* no user ID with that idx */
+      pos += idx*uidinfolen;
+      off = get32 (buffer+pos);
+      len = get32 (buffer+pos+4);
+      if (off+len > length)
+        return 0; /* out of bounds */
+      if (len < 2)
+        return 0; /* empty name or 0 not stored */
+      len--;
+      
+      return len == namelen && !memcmp (buffer+off, name, len);
+    }
+}
+
+
+/* compare all email addresses of the subject */
+static int
+blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen)
+{
+  const unsigned char *buffer;
+  size_t length;
+  size_t pos, off, len;
+  size_t nkeys, keyinfolen;
+  size_t nuids, uidinfolen;
+  size_t nserial;
+  int idx;
+
+  /* fixme: this code is common to blob_cmp_mail */
+  buffer = _keybox_get_blob_image (blob, &length);
+  if (length < 40)
+    return 0; /* blob too short */
+
+  /*keys*/
+  nkeys = get16 (buffer + 16);
+  keyinfolen = get16 (buffer + 18 );
+  if (keyinfolen < 28)
+    return 0; /* invalid blob */
+  pos = 20 + keyinfolen*nkeys;
+  if (pos+2 > length)
     return 0; /* out of bounds */
-  if (len < 2)
-    return 0; /* empty name or 0 not stored */
-  len--;
-  
-  return len == namelen && !memcmp (buffer+off, name, len);
+
+  /*serial*/
+  nserial = get16 (buffer+pos); 
+  pos += 2 + nserial;
+  if (pos+4 > length)
+    return 0; /* out of bounds */
+
+  /* user ids*/
+  nuids = get16 (buffer + pos);  pos += 2;
+  uidinfolen = get16 (buffer + pos);  pos += 2;
+  if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
+    return 0; /* invalid blob */
+  if (pos + uidinfolen*nuids > length)
+    return 0; /* out of bounds */
+
+  for (idx=1 ;idx < nuids; idx++)
+    {
+      size_t mypos = pos;
+      
+      mypos += idx*uidinfolen;
+      off = get32 (buffer+mypos);
+      len = get32 (buffer+mypos+4);
+      if (off+len > length)
+        return 0; /* error: better stop here out of bounds */
+      if (len < 2 || buffer[off] != '<')
+        continue; /* empty name or trailing 0 not stored */
+      len--; /* remove the null */
+      if ( len < 3 || buffer[off+len-1] != '>')
+        continue; /* not a prober email address */
+      off++; len--;   /* skip the leading angle bracket */
+      len--;          /* don't compare the trailing one */
+      if (len == namelen && !memcmp (buffer+off, name, len))
+        return 1; /* found */
+    }
+  return 0; /* not found */
 }
 
 
@@ -235,6 +323,35 @@ has_subject (KEYBOXBLOB blob, const char *name)
   return blob_cmp_name (blob, 1 /* subject */, name, namelen);
 }
 
+static int
+has_subject_or_alt (KEYBOXBLOB blob, const char *name)
+{
+  size_t namelen;
+
+  return_val_if_fail (name, 0);
+
+  if (blob_get_type (blob) != BLOBTYPE_X509)
+    return 0;
+
+  namelen = strlen (name);
+  return blob_cmp_name (blob, -1 /* all subject names*/, name, namelen);
+}
+
+
+static int
+has_mail (KEYBOXBLOB blob, const char *name)
+{
+  size_t namelen;
+
+  return_val_if_fail (name, 0);
+
+  if (blob_get_type (blob) != BLOBTYPE_X509)
+    return 0;
+
+  namelen = strlen (name);
+  return blob_cmp_mail (blob, name, namelen);
+}
+
 
 static void
 release_sn_array (unsigned char **array, size_t size)
@@ -413,8 +530,14 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
               never_reached ();
               break;
             case KEYDB_SEARCH_MODE_EXACT: 
-            case KEYDB_SEARCH_MODE_SUBSTR:
+              if (has_subject_or_alt (blob, desc[n].u.name))
+                goto found;
+              break;
             case KEYDB_SEARCH_MODE_MAIL:
+              if (has_mail (blob, desc[n].u.name))
+                goto found;
+              break;
+            case KEYDB_SEARCH_MODE_SUBSTR:
             case KEYDB_SEARCH_MODE_MAILSUB:
             case KEYDB_SEARCH_MODE_MAILEND:
             case KEYDB_SEARCH_MODE_WORDS: 
index 645f1e7..fcacc49 100644 (file)
@@ -60,6 +60,7 @@ typedef enum {
   KEYBOX_File_Close_Error = 13,
   KEYBOX_Nothing_Found = 14,
   KEYBOX_Wrong_Blob_Type = 15,
+  KEYBOX_Missing_Value = 16,
 } KeyboxError;