g10: clean up of headers for card.
[gnupg.git] / kbx / keybox-search.c
index 0a3ed43..1edb4ae 100644 (file)
 #include <assert.h>
 #include <errno.h>
 
-#include "../common/stringhelp.h" /* ascii_xxxx() */
-
 #include "keybox-defs.h"
 #include <gcrypt.h>
-
+#include "host2net.h"
+#include "mbox-util.h"
 
 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
@@ -42,27 +41,8 @@ struct sn_array_s {
 };
 
 
-
-static inline ulong
-get32 (const byte *buffer)
-{
-  ulong a;
-  a =  *buffer << 24;
-  a |= buffer[1] << 16;
-  a |= buffer[2] << 8;
-  a |= buffer[3];
-  return a;
-}
-
-static inline ulong
-get16 (const byte *buffer)
-{
-  ulong a;
-  a =  *buffer << 8;
-  a |= buffer[1];
-  return a;
-}
-
+#define get32(a) buf32_to_ulong ((a))
+#define get16(a) buf16_to_ulong ((a))
 
 
 static inline unsigned int
@@ -189,7 +169,7 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
 
 
 
-/* Return one of the flags WHAT in VALUE from teh blob BUFFER of
+/* Return one of the flags WHAT in VALUE from the blob BUFFER of
    LENGTH bytes.  Return 0 on success or an raw error code. */
 static gpg_err_code_t
 get_flag_from_image (const unsigned char *buffer, size_t length,
@@ -404,8 +384,8 @@ blob_cmp_name (KEYBOXBLOB blob, int idx,
 
 
 /* Compare all email addresses of the subject.  With SUBSTR given as
-   True a substring search is done in the mail address.  If X509
-   states whether thr search is done on an X.509 blob.  */
+   True a substring search is done in the mail address.  The X509 flag
+   indicated whether the search is done on an X.509 blob.  */
 static int
 blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
                int x509)
@@ -449,37 +429,67 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
   if (namelen < 1)
     return 0;
 
-  /* Note that for X.509 we start at index 1 becuase index 0 is used
+  /* Note that for X.509 we start at index 1 because index 0 is used
      for the issuer name.  */
   for (idx=!!x509 ;idx < nuids; idx++)
     {
       size_t mypos = pos;
+      size_t mylen;
 
       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 (!x509)
+        return 0; /* error: better stop here - out of bounds */
+      if (x509)
+        {
+          if (len < 2 || buffer[off] != '<')
+            continue; /* empty name or trailing 0 not stored */
+          len--; /* one back */
+          if ( len < 3 || buffer[off+len] != '>')
+            continue; /* not a proper email address */
+          off++;
+          len--;
+        }
+      else /* OpenPGP.  */
         {
-          /* For OpenPGP we need to forward to the mailbox part.  */
-          for ( ;len && buffer[off] != '<'; len--, off++)
+          /* We need to forward to the mailbox part.  */
+          mypos = off;
+          mylen = len;
+          for ( ; len && buffer[off] != '<'; len--, off++)
             ;
+          if (len < 2 || buffer[off] != '<')
+            {
+              /* Mailbox not explicitly given or too short.  Restore
+                 OFF and LEN and check whether the entire string
+                 resembles a mailbox without the angle brackets.  */
+              off = mypos;
+              len = mylen;
+              if (!is_valid_mailbox_mem (buffer+off, len))
+                continue; /* Not a mail address. */
+            }
+          else /* Seems to be standard user id with mail address.  */
+            {
+              off++; /* Point to first char of the mail address.  */
+              len--;
+              /* Search closing '>'.  */
+              for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
+                ;
+              if (!len || buffer[mypos] != '>' || off == mypos)
+                continue; /* Not a proper mail address.  */
+              len = mypos - off;
+            }
+
         }
-      if (len < 2 || buffer[off] != '<')
-        continue; /* empty name or trailing 0 not stored */
-      len--; /* one back */
-      if ( len < 3 || buffer[off+len] != '>')
-        continue; /* not a proper email address */
-      len--;
+
       if (substr)
         {
-          if (ascii_memcasemem (buffer+off+1, len, name, namelen))
+          if (ascii_memcasemem (buffer+off, len, name, namelen))
             return idx+1; /* found */
         }
       else
         {
-          if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len))
+          if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
             return idx+1; /* found */
         }
     }
@@ -599,6 +609,9 @@ has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
 #ifdef KEYBOX_WITH_X509
   if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
     return blob_x509_has_grip (blob, grip);
+#else
+  (void)blob;
+  (void)grip;
 #endif
   return 0;
 }
@@ -995,8 +1008,8 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
 
           if (desc[n].skipfnc
               && blob_get_first_keyid (blob, kid)
-              && desc[n].skipfnc (desc[n].skipfncvalue, kid, NULL))
-            break;
+             && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
+               break;
         }
       if (n == ndesc)
         break; /* got it */
@@ -1175,3 +1188,40 @@ keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
   ec = get_flag_from_image (buffer, length, what, value);
   return ec? gpg_error (ec):0;
 }
+
+off_t
+keybox_offset (KEYBOX_HANDLE hd)
+{
+  if (!hd->fp)
+    return 0;
+  return ftello (hd->fp);
+}
+
+gpg_error_t
+keybox_seek (KEYBOX_HANDLE hd, off_t offset)
+{
+  int err;
+
+  if (hd->error)
+    return hd->error; /* still in error state */
+
+  if (! hd->fp)
+    {
+      if (offset == 0)
+        /* No need to open the file.  An unopened file is effectively at
+           offset 0.  */
+        return 0;
+
+      hd->fp = fopen (hd->kb->fname, "rb");
+      if (!hd->fp)
+        {
+          hd->error = gpg_error_from_syserror ();
+          return hd->error;
+        }
+    }
+
+  err = fseeko (hd->fp, offset, SEEK_SET);
+  hd->error = gpg_error_from_errno (err);
+
+  return hd->error;
+}