Fixed an email/DN bug.
[gnupg.git] / kbx / keybox-blob.c
index 3d81532..a45c421 100644 (file)
@@ -1,11 +1,11 @@
 /* keybox-blob.c - KBX Blob handling
- *     Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 
 /* The keybox data formats
 
 The KeyBox uses an augmented OpenPGP/X.509 key format.  This makes
-random access to a keyblock/Certificate easier and also gives the
+random access to a keyblock/certificate easier and also gives the
 opportunity to store additional information (e.g. the fingerprint)
 along with the key.  All integers are stored in network byte order,
 offsets are counted from the beginning of the Blob.
@@ -35,11 +34,13 @@ The first record of a plain KBX file has a special format:
  byte reserved
  byte reserved
  u32  magic 'KBXf'
- byte pgp_marginals  used for validity calculation of this file
- byte pgp_completes  ditto.
- byte pgp_cert_depth ditto.
+ u32  reserved
+ u32  file_created_at
+ u32  last_maintenance_run
+ u32  reserved
+ u32  reserved
 
-The OpenPGP and X.509 blob are verry similiar, things which are
+The OpenPGP and X.509 blob are very similiar, things which are
 X.509 specific are noted like [X.509: xxx]
 
  u32  length of this blob (including these 4 bytes)
@@ -57,9 +58,9 @@ X.509 specific are noted like [X.509: xxx]
    b20 The keys fingerprint
        (fingerprints are always 20 bytes, MD5 left padded with zeroes)
    u32 offset to the n-th key's keyID (a keyID is always 8 byte)
-        or 0 if not known which is the case opnly for X509.
+        or 0 if not known which is the case only for X509.
    u16 special key flags
-        bit 0 =
+        bit 0 = qualified signature (not yet implemented}
    u16 reserved
  u16  size of serialnumber(may be zero) 
    n  u16 (see above) bytes of serial number
@@ -82,8 +83,11 @@ X.509 specific are noted like [X.509: xxx]
        0x00000002 = bad signature
        0x10000000 = valid and expires at some date in 1978.
        0xffffffff = valid and does not expire
- u8    assigned ownertrust [X509: no used]
- u8    all_validity        [X509: no used]
+ u8    assigned ownertrust [X509: not used]
+ u8    all_validity 
+           OpenPGP:  see ../g10/trustdb/TRUST_* [not yet used]
+           X509: Bit 4 set := key has been revoked.  Note that this value
+                              matches TRUST_FLAG_REVOKED
  u16   reserved
  u32   recheck_after
  u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
@@ -99,7 +103,7 @@ X.509 specific are noted like [X.509: xxx]
 
  b16   MD5 checksum  (useful for KS syncronisation), we might also want to use
     a mac here.
- b4    resevered
+ b4    reserved
 
 */
 
@@ -641,8 +645,8 @@ static int
 create_blob_finish (KEYBOXBLOB blob)
 {
   struct membuf *a = blob->buf;
-  byte *p;
-  char *pp;
+  unsigned char *p;
+  unsigned char *pp;
   int i;
   size_t n;
 
@@ -651,6 +655,7 @@ create_blob_finish (KEYBOXBLOB blob)
     put32 (a, 0);  /* Hmmm: why put32() ?? */
   
   /* get the memory area */
+  n = 0; /* (Just to avoid compiler warning.) */
   p = get_membuf (a, &n);
   if (!p)
     return gpg_error (GPG_ERR_ENOMEM);
@@ -773,34 +778,46 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral)
 
 #ifdef KEYBOX_WITH_X509
 
-/* return an allocated string with the email address extracted from a
-   DN */
+/* Return an allocated string with the email address extracted from a
+   DN.  Note hat we use this code also in ../sm/keylist.c.  */
 static char *
 x509_email_kludge (const char *name)
 {
-  const unsigned char *p;
+  const char *p, *string;
   unsigned char *buf;
   int n;
 
-  if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
-    return NULL;
+  string = name;
+  for (;;)
+    {
+      p = strstr (string, "1.2.840.113549.1.9.1=#");
+      if (!p)
+        return NULL;
+      if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
+        {
+          name = p + 22;
+          break;
+        }
+      string = p + 22;
+    }
+
+
   /* This looks pretty much like an email address in the subject's DN
      we use this to add an additional user ID entry.  This way,
-     openSSL generated keys get a nicer and usable listing */
-  name += 22;    
+     OpenSSL generated keys get a nicer and usable listing.  */
   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
     ;
-  if (*p != '#' || !n)
+  if (!n)
     return NULL;
   buf = xtrymalloc (n+3);
   if (!buf)
     return NULL; /* oops, out of core */
   *buf = '<';
-  for (n=1, p=name; *p != '#'; p +=2, n++)
+  for (n=1, p=name; hexdigitp (p); p +=2, n++)
     buf[n] = xtoi_2 (p);
   buf[n++] = '>';
   buf[n] = 0;
-  return buf;
+  return (char*)buf;
 }
 
 
@@ -813,8 +830,9 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
 {
   int i, rc = 0;
   KEYBOXBLOB blob;
-  unsigned char *p;
-  unsigned char **names = NULL;
+  unsigned char *sn;
+  char *p;
+  char **names = NULL;
   size_t max_names;
 
   *r_blob = NULL;
@@ -822,28 +840,28 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
   if( !blob )
     return gpg_error (gpg_err_code_from_errno (errno));
 
-  p = ksba_cert_get_serial (cert);
-  if (p)
+  sn = ksba_cert_get_serial (cert);
+  if (sn)
     {
       size_t n, len;
-      n = gcry_sexp_canon_len (p, 0, NULL, NULL);
+      n = gcry_sexp_canon_len (sn, 0, NULL, NULL);
       if (n < 2)
         {
-          xfree (p);
+          xfree (sn);
           return gpg_error (GPG_ERR_GENERAL);
         }
-      blob->serialbuf = p;
-      p++; n--; /* skip '(' */
-      for (len=0; n && *p && *p != ':' && digitp (p); n--, p++)
-        len = len*10 + atoi_1 (p);
-      if (*p != ':')
+      blob->serialbuf = sn;
+      sn++; n--; /* skip '(' */
+      for (len=0; n && *sn && *sn != ':' && digitp (sn); n--, sn++)
+        len = len*10 + atoi_1 (sn);
+      if (*sn != ':')
         {
           xfree (blob->serialbuf);
           blob->serialbuf = NULL;
           return gpg_error (GPG_ERR_GENERAL);
         }
-      p++;
-      blob->serial = p;
+      sn++;
+      blob->serial = sn;
       blob->seriallen = len;
     }
 
@@ -858,6 +876,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
       rc = gpg_error (gpg_err_code_from_errno (errno));
       goto leave;
     }
+  
   p = ksba_cert_get_issuer (cert, 0);
   if (!p)
     {
@@ -867,10 +886,9 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
   names[blob->nuids++] = p;
   for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
     {
-
       if (blob->nuids >= max_names)
         {
-          unsigned char **tmp;
+          char **tmp;
           
           max_names += 100;
           tmp = xtryrealloc (names, max_names * sizeof *names);
@@ -959,7 +977,8 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
 
 \f
 int
-_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off)
+_keybox_new_blob (KEYBOXBLOB *r_blob,
+                  unsigned char *image, size_t imagelen, off_t off)
 {
   KEYBOXBLOB blob;
   
@@ -975,6 +994,7 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off)
   return 0;
 }
 
+
 void
 _keybox_release_blob (KEYBOXBLOB blob)
 {
@@ -994,7 +1014,7 @@ _keybox_release_blob (KEYBOXBLOB blob)
 
 
 
-const char *
+const unsigned char *
 _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
 {
   *n = blob->bloblen;
@@ -1007,3 +1027,19 @@ _keybox_get_blob_fileoffset (KEYBOXBLOB blob)
   return blob->fileoffset;
 }
 
+
+
+void
+_keybox_update_header_blob (KEYBOXBLOB blob)
+{
+  if (blob->bloblen >= 32 && blob->blob[4] == BLOBTYPE_HEADER)
+    {
+      u32 val = make_timestamp ();
+
+      /* Update the last maintenance run times tamp. */
+      blob->blob[20]   = (val >> 24);
+      blob->blob[20+1] = (val >> 16);
+      blob->blob[20+2] = (val >>  8);
+      blob->blob[20+3] = (val      );
+    }
+}