LCOV - code coverage report
Current view: top level - kbx - keybox-search.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 232 610 38.0 %
Date: 2016-09-12 13:01:59 Functions: 14 28 50.0 %

          Line data    Source code
       1             : /* keybox-search.c - Search operations
       2             :  * Copyright (C) 2001, 2002, 2003, 2004, 2012,
       3             :  *               2013 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdlib.h>
      23             : #include <stdio.h>
      24             : #include <string.h>
      25             : #include <assert.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "keybox-defs.h"
      29             : #include <gcrypt.h>
      30             : #include "host2net.h"
      31             : #include "mbox-util.h"
      32             : 
      33             : #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
      34             :                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
      35             : #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
      36             : 
      37             : 
      38             : struct sn_array_s {
      39             :     int snlen;
      40             :     unsigned char *sn;
      41             : };
      42             : 
      43             : 
      44             : #define get32(a) buf32_to_ulong ((a))
      45             : #define get16(a) buf16_to_ulong ((a))
      46             : 
      47             : 
      48             : static inline unsigned int
      49       78435 : blob_get_blob_flags (KEYBOXBLOB blob)
      50             : {
      51             :   const unsigned char *buffer;
      52             :   size_t length;
      53             : 
      54       78435 :   buffer = _keybox_get_blob_image (blob, &length);
      55       78435 :   if (length < 8)
      56           0 :     return 0; /* oops */
      57             : 
      58       78435 :   return get16 (buffer + 6);
      59             : }
      60             : 
      61             : 
      62             : /* Return the first keyid from the blob.  Returns true if
      63             :    available.  */
      64             : static int
      65         210 : blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
      66             : {
      67             :   const unsigned char *buffer;
      68             :   size_t length, nkeys, keyinfolen;
      69             : 
      70         210 :   buffer = _keybox_get_blob_image (blob, &length);
      71         210 :   if (length < 48)
      72           0 :     return 0; /* blob too short */
      73             : 
      74         210 :   nkeys = get16 (buffer + 16);
      75         210 :   keyinfolen = get16 (buffer + 18);
      76         210 :   if (!nkeys || keyinfolen < 28)
      77           0 :     return 0; /* invalid blob */
      78             : 
      79         210 :   kid[0] = get32 (buffer + 32);
      80         210 :   kid[1] = get32 (buffer + 36);
      81             : 
      82         210 :   return 1;
      83             : }
      84             : 
      85             : 
      86             : /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
      87             :    Return the offset and the length (in bytes) of the flag in
      88             :    FLAGOFF,FLAG_SIZE. */
      89             : gpg_err_code_t
      90        2527 : _keybox_get_flag_location (const unsigned char *buffer, size_t length,
      91             :                            int what, size_t *flag_off, size_t *flag_size)
      92             : {
      93             :   size_t pos;
      94             :   size_t nkeys, keyinfolen;
      95             :   size_t nuids, uidinfolen;
      96             :   size_t nserial;
      97             :   size_t nsigs, siginfolen, siginfooff;
      98             : 
      99        2527 :   switch (what)
     100             :     {
     101             :     case KEYBOX_FLAG_BLOB:
     102           0 :       if (length < 8)
     103           0 :         return GPG_ERR_INV_OBJ;
     104           0 :       *flag_off = 6;
     105           0 :       *flag_size = 2;
     106           0 :       break;
     107             : 
     108             :     case KEYBOX_FLAG_OWNERTRUST:
     109             :     case KEYBOX_FLAG_VALIDITY:
     110             :     case KEYBOX_FLAG_CREATED_AT:
     111             :     case KEYBOX_FLAG_SIG_INFO:
     112        2527 :       if (length < 20)
     113           0 :         return GPG_ERR_INV_OBJ;
     114             :       /* Key info. */
     115        2527 :       nkeys = get16 (buffer + 16);
     116        2527 :       keyinfolen = get16 (buffer + 18 );
     117        2527 :       if (keyinfolen < 28)
     118           0 :         return GPG_ERR_INV_OBJ;
     119        2527 :       pos = 20 + keyinfolen*nkeys;
     120        2527 :       if (pos+2 > length)
     121           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     122             :       /* Serial number. */
     123        2527 :       nserial = get16 (buffer+pos);
     124        2527 :       pos += 2 + nserial;
     125        2527 :       if (pos+4 > length)
     126           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     127             :       /* User IDs. */
     128        2527 :       nuids = get16 (buffer + pos); pos += 2;
     129        2527 :       uidinfolen = get16 (buffer + pos); pos += 2;
     130        2527 :       if (uidinfolen < 12 )
     131           0 :         return GPG_ERR_INV_OBJ;
     132        2527 :       pos += uidinfolen*nuids;
     133        2527 :       if (pos+4 > length)
     134           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     135             :       /* Signature info. */
     136        2527 :       siginfooff = pos;
     137        2527 :       nsigs = get16 (buffer + pos); pos += 2;
     138        2527 :       siginfolen = get16 (buffer + pos); pos += 2;
     139        2527 :       if (siginfolen < 4 )
     140           0 :         return GPG_ERR_INV_OBJ;
     141        2527 :       pos += siginfolen*nsigs;
     142        2527 :       if (pos+1+1+2+4+4+4+4 > length)
     143           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     144        2527 :       *flag_size = 1;
     145        2527 :       *flag_off = pos;
     146        2527 :       switch (what)
     147             :         {
     148             :         case KEYBOX_FLAG_VALIDITY:
     149           0 :           *flag_off += 1;
     150           0 :           break;
     151             :         case KEYBOX_FLAG_CREATED_AT:
     152           0 :           *flag_size = 4;
     153           0 :           *flag_off += 1+2+4+4+4;
     154           0 :           break;
     155             :         case KEYBOX_FLAG_SIG_INFO:
     156        2527 :           *flag_size = siginfolen * nsigs;
     157        2527 :           *flag_off = siginfooff;
     158        2527 :           break;
     159             :         default:
     160           0 :           break;
     161             :         }
     162        2527 :       break;
     163             : 
     164             :     default:
     165           0 :       return GPG_ERR_INV_FLAG;
     166             :     }
     167        2527 :   return 0;
     168             : }
     169             : 
     170             : 
     171             : 
     172             : /* Return one of the flags WHAT in VALUE from the blob BUFFER of
     173             :    LENGTH bytes.  Return 0 on success or an raw error code. */
     174             : static gpg_err_code_t
     175           0 : get_flag_from_image (const unsigned char *buffer, size_t length,
     176             :                      int what, unsigned int *value)
     177             : {
     178             :   gpg_err_code_t ec;
     179             :   size_t pos, size;
     180             : 
     181           0 :   *value = 0;
     182           0 :   ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
     183           0 :   if (!ec)
     184           0 :     switch (size)
     185             :       {
     186           0 :       case 1: *value = buffer[pos]; break;
     187           0 :       case 2: *value = get16 (buffer + pos); break;
     188           0 :       case 4: *value = get32 (buffer + pos); break;
     189           0 :       default: ec = GPG_ERR_BUG; break;
     190             :       }
     191             : 
     192           0 :   return ec;
     193             : }
     194             : 
     195             : 
     196             : static int
     197           0 : blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
     198             : {
     199             :   const unsigned char *buffer;
     200             :   size_t length;
     201             :   size_t pos, off;
     202             :   size_t nkeys, keyinfolen;
     203             :   size_t nserial;
     204             : 
     205           0 :   buffer = _keybox_get_blob_image (blob, &length);
     206           0 :   if (length < 40)
     207           0 :     return 0; /* blob too short */
     208             : 
     209             :   /*keys*/
     210           0 :   nkeys = get16 (buffer + 16);
     211           0 :   keyinfolen = get16 (buffer + 18 );
     212           0 :   if (keyinfolen < 28)
     213           0 :     return 0; /* invalid blob */
     214           0 :   pos = 20 + keyinfolen*nkeys;
     215           0 :   if (pos+2 > length)
     216           0 :     return 0; /* out of bounds */
     217             : 
     218             :   /*serial*/
     219           0 :   nserial = get16 (buffer+pos);
     220           0 :   off = pos + 2;
     221           0 :   if (off+nserial > length)
     222           0 :     return 0; /* out of bounds */
     223             : 
     224           0 :   return nserial == snlen && !memcmp (buffer+off, sn, snlen);
     225             : }
     226             : 
     227             : 
     228             : /* Returns 0 if not found or the number of the key which was found.
     229             :    For X.509 this is always 1, for OpenPGP this is 1 for the primary
     230             :    key and 2 and more for the subkeys.  */
     231             : static int
     232        5124 : blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
     233             : {
     234             :   const unsigned char *buffer;
     235             :   size_t length;
     236             :   size_t pos, off;
     237             :   size_t nkeys, keyinfolen;
     238             :   int idx;
     239             : 
     240        5124 :   buffer = _keybox_get_blob_image (blob, &length);
     241        5124 :   if (length < 40)
     242           0 :     return 0; /* blob too short */
     243             : 
     244             :   /*keys*/
     245        5124 :   nkeys = get16 (buffer + 16);
     246        5124 :   keyinfolen = get16 (buffer + 18 );
     247        5124 :   if (keyinfolen < 28)
     248           0 :     return 0; /* invalid blob */
     249        5124 :   pos = 20;
     250        5124 :   if (pos + keyinfolen*nkeys > length)
     251           0 :     return 0; /* out of bounds */
     252             : 
     253       14569 :   for (idx=0; idx < nkeys; idx++)
     254             :     {
     255        9585 :       off = pos + idx*keyinfolen;
     256        9585 :       if (!memcmp (buffer + off, fpr, 20))
     257         140 :         return idx+1; /* found */
     258             :     }
     259        4984 :   return 0; /* not found */
     260             : }
     261             : 
     262             : static int
     263       69256 : blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
     264             :                    int fproff, int fprlen)
     265             : {
     266             :   const unsigned char *buffer;
     267             :   size_t length;
     268             :   size_t pos, off;
     269             :   size_t nkeys, keyinfolen;
     270             :   int idx;
     271             : 
     272       69256 :   buffer = _keybox_get_blob_image (blob, &length);
     273       69256 :   if (length < 40)
     274           0 :     return 0; /* blob too short */
     275             : 
     276             :   /*keys*/
     277       69256 :   nkeys = get16 (buffer + 16);
     278       69256 :   keyinfolen = get16 (buffer + 18 );
     279       69256 :   if (keyinfolen < 28)
     280           0 :     return 0; /* invalid blob */
     281       69256 :   pos = 20;
     282       69256 :   if (pos + keyinfolen*nkeys > length)
     283           0 :     return 0; /* out of bounds */
     284             : 
     285      197369 :   for (idx=0; idx < nkeys; idx++)
     286             :     {
     287      130279 :       off = pos + idx*keyinfolen;
     288      130279 :       if (!memcmp (buffer + off + fproff, fpr, fprlen))
     289        2166 :         return idx+1; /* found */
     290             :     }
     291       67090 :   return 0; /* not found */
     292             : }
     293             : 
     294             : 
     295             : static int
     296        4408 : blob_cmp_name (KEYBOXBLOB blob, int idx,
     297             :                const char *name, size_t namelen, int substr, int x509)
     298             : {
     299             :   const unsigned char *buffer;
     300             :   size_t length;
     301             :   size_t pos, off, len;
     302             :   size_t nkeys, keyinfolen;
     303             :   size_t nuids, uidinfolen;
     304             :   size_t nserial;
     305             : 
     306        4408 :   buffer = _keybox_get_blob_image (blob, &length);
     307        4408 :   if (length < 40)
     308           0 :     return 0; /* blob too short */
     309             : 
     310             :   /*keys*/
     311        4408 :   nkeys = get16 (buffer + 16);
     312        4408 :   keyinfolen = get16 (buffer + 18 );
     313        4408 :   if (keyinfolen < 28)
     314           0 :     return 0; /* invalid blob */
     315        4408 :   pos = 20 + keyinfolen*nkeys;
     316        4408 :   if (pos+2 > length)
     317           0 :     return 0; /* out of bounds */
     318             : 
     319             :   /*serial*/
     320        4408 :   nserial = get16 (buffer+pos);
     321        4408 :   pos += 2 + nserial;
     322        4408 :   if (pos+4 > length)
     323           0 :     return 0; /* out of bounds */
     324             : 
     325             :   /* user ids*/
     326        4408 :   nuids = get16 (buffer + pos);  pos += 2;
     327        4408 :   uidinfolen = get16 (buffer + pos);  pos += 2;
     328        4408 :   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
     329           0 :     return 0; /* invalid blob */
     330        4408 :   if (pos + uidinfolen*nuids > length)
     331           0 :     return 0; /* out of bounds */
     332             : 
     333        4408 :   if (idx < 0)
     334             :     { /* Compare all names.  Note that for X.509 we start with index 1
     335             :          so to skip the issuer at index 0.  */
     336        9564 :       for (idx = !!x509; idx < nuids; idx++)
     337             :         {
     338        5294 :           size_t mypos = pos;
     339             : 
     340        5294 :           mypos += idx*uidinfolen;
     341        5294 :           off = get32 (buffer+mypos);
     342        5294 :           len = get32 (buffer+mypos+4);
     343        5294 :           if (off+len > length)
     344           0 :             return 0; /* error: better stop here out of bounds */
     345        5294 :           if (len < 1)
     346           0 :             continue; /* empty name */
     347        5294 :           if (substr)
     348             :             {
     349        5294 :               if (ascii_memcasemem (buffer+off, len, name, namelen))
     350         138 :                 return idx+1; /* found */
     351             :             }
     352             :           else
     353             :             {
     354           0 :               if (len == namelen && !memcmp (buffer+off, name, len))
     355           0 :                 return idx+1; /* found */
     356             :             }
     357             :         }
     358             :     }
     359             :   else
     360             :     {
     361           0 :       if (idx > nuids)
     362           0 :         return 0; /* no user ID with that idx */
     363           0 :       pos += idx*uidinfolen;
     364           0 :       off = get32 (buffer+pos);
     365           0 :       len = get32 (buffer+pos+4);
     366           0 :       if (off+len > length)
     367           0 :         return 0; /* out of bounds */
     368           0 :       if (len < 1)
     369           0 :         return 0; /* empty name */
     370             : 
     371           0 :       if (substr)
     372             :         {
     373           0 :           if (ascii_memcasemem (buffer+off, len, name, namelen))
     374           0 :             return idx+1; /* found */
     375             :         }
     376             :       else
     377             :         {
     378           0 :           if (len == namelen && !memcmp (buffer+off, name, len))
     379           0 :             return idx+1; /* found */
     380             :         }
     381             :     }
     382        4270 :   return 0; /* not found */
     383             : }
     384             : 
     385             : 
     386             : /* Compare all email addresses of the subject.  With SUBSTR given as
     387             :    True a substring search is done in the mail address.  The X509 flag
     388             :    indicated whether the search is done on an X.509 blob.  */
     389             : static int
     390           0 : blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
     391             :                int x509)
     392             : {
     393             :   const unsigned char *buffer;
     394             :   size_t length;
     395             :   size_t pos, off, len;
     396             :   size_t nkeys, keyinfolen;
     397             :   size_t nuids, uidinfolen;
     398             :   size_t nserial;
     399             :   int idx;
     400             : 
     401             :   /* fixme: this code is common to blob_cmp_mail */
     402           0 :   buffer = _keybox_get_blob_image (blob, &length);
     403           0 :   if (length < 40)
     404           0 :     return 0; /* blob too short */
     405             : 
     406             :   /*keys*/
     407           0 :   nkeys = get16 (buffer + 16);
     408           0 :   keyinfolen = get16 (buffer + 18 );
     409           0 :   if (keyinfolen < 28)
     410           0 :     return 0; /* invalid blob */
     411           0 :   pos = 20 + keyinfolen*nkeys;
     412           0 :   if (pos+2 > length)
     413           0 :     return 0; /* out of bounds */
     414             : 
     415             :   /*serial*/
     416           0 :   nserial = get16 (buffer+pos);
     417           0 :   pos += 2 + nserial;
     418           0 :   if (pos+4 > length)
     419           0 :     return 0; /* out of bounds */
     420             : 
     421             :   /* user ids*/
     422           0 :   nuids = get16 (buffer + pos);  pos += 2;
     423           0 :   uidinfolen = get16 (buffer + pos);  pos += 2;
     424           0 :   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
     425           0 :     return 0; /* invalid blob */
     426           0 :   if (pos + uidinfolen*nuids > length)
     427           0 :     return 0; /* out of bounds */
     428             : 
     429           0 :   if (namelen < 1)
     430           0 :     return 0;
     431             : 
     432             :   /* Note that for X.509 we start at index 1 because index 0 is used
     433             :      for the issuer name.  */
     434           0 :   for (idx=!!x509 ;idx < nuids; idx++)
     435             :     {
     436           0 :       size_t mypos = pos;
     437             :       size_t mylen;
     438             : 
     439           0 :       mypos += idx*uidinfolen;
     440           0 :       off = get32 (buffer+mypos);
     441           0 :       len = get32 (buffer+mypos+4);
     442           0 :       if (off+len > length)
     443           0 :         return 0; /* error: better stop here - out of bounds */
     444           0 :       if (x509)
     445             :         {
     446           0 :           if (len < 2 || buffer[off] != '<')
     447           0 :             continue; /* empty name or trailing 0 not stored */
     448           0 :           len--; /* one back */
     449           0 :           if ( len < 3 || buffer[off+len] != '>')
     450           0 :             continue; /* not a proper email address */
     451           0 :           off++;
     452           0 :           len--;
     453             :         }
     454             :       else /* OpenPGP.  */
     455             :         {
     456             :           /* We need to forward to the mailbox part.  */
     457           0 :           mypos = off;
     458           0 :           mylen = len;
     459           0 :           for ( ; len && buffer[off] != '<'; len--, off++)
     460             :             ;
     461           0 :           if (len < 2 || buffer[off] != '<')
     462             :             {
     463             :               /* Mailbox not explicitly given or too short.  Restore
     464             :                  OFF and LEN and check whether the entire string
     465             :                  resembles a mailbox without the angle brackets.  */
     466           0 :               off = mypos;
     467           0 :               len = mylen;
     468           0 :               if (!is_valid_mailbox_mem (buffer+off, len))
     469           0 :                 continue; /* Not a mail address. */
     470             :             }
     471             :           else /* Seems to be standard user id with mail address.  */
     472             :             {
     473           0 :               off++; /* Point to first char of the mail address.  */
     474           0 :               len--;
     475             :               /* Search closing '>'.  */
     476           0 :               for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
     477             :                 ;
     478           0 :               if (!len || buffer[mypos] != '>' || off == mypos)
     479           0 :                 continue; /* Not a proper mail address.  */
     480           0 :               len = mypos - off;
     481             :             }
     482             : 
     483             :         }
     484             : 
     485           0 :       if (substr)
     486             :         {
     487           0 :           if (ascii_memcasemem (buffer+off, len, name, namelen))
     488           0 :             return idx+1; /* found */
     489             :         }
     490             :       else
     491             :         {
     492           0 :           if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
     493           0 :             return idx+1; /* found */
     494             :         }
     495             :     }
     496           0 :   return 0; /* not found */
     497             : }
     498             : 
     499             : 
     500             : #ifdef KEYBOX_WITH_X509
     501             : /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
     502             :    We don't have the keygrips as meta data, thus we need to parse the
     503             :    certificate. Fixme: We might want to return proper error codes
     504             :    instead of failing a search for invalid certificates etc.  */
     505             : static int
     506           0 : blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
     507             : {
     508             :   int rc;
     509             :   const unsigned char *buffer;
     510             :   size_t length;
     511             :   size_t cert_off, cert_len;
     512           0 :   ksba_reader_t reader = NULL;
     513           0 :   ksba_cert_t cert = NULL;
     514           0 :   ksba_sexp_t p = NULL;
     515             :   gcry_sexp_t s_pkey;
     516             :   unsigned char array[20];
     517             :   unsigned char *rcp;
     518             :   size_t n;
     519             : 
     520           0 :   buffer = _keybox_get_blob_image (blob, &length);
     521           0 :   if (length < 40)
     522           0 :     return 0; /* Too short. */
     523           0 :   cert_off = get32 (buffer+8);
     524           0 :   cert_len = get32 (buffer+12);
     525           0 :   if (cert_off+cert_len > length)
     526           0 :     return 0; /* Too short.  */
     527             : 
     528           0 :   rc = ksba_reader_new (&reader);
     529           0 :   if (rc)
     530           0 :     return 0; /* Problem with ksba. */
     531           0 :   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
     532           0 :   if (rc)
     533           0 :     goto failed;
     534           0 :   rc = ksba_cert_new (&cert);
     535           0 :   if (rc)
     536           0 :     goto failed;
     537           0 :   rc = ksba_cert_read_der (cert, reader);
     538           0 :   if (rc)
     539           0 :     goto failed;
     540           0 :   p = ksba_cert_get_public_key (cert);
     541           0 :   if (!p)
     542           0 :     goto failed;
     543           0 :   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
     544           0 :   if (!n)
     545           0 :     goto failed;
     546           0 :   rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
     547           0 :   if (rc)
     548             :     {
     549           0 :       gcry_sexp_release (s_pkey);
     550           0 :       goto failed;
     551             :     }
     552           0 :   rcp = gcry_pk_get_keygrip (s_pkey, array);
     553           0 :   gcry_sexp_release (s_pkey);
     554           0 :   if (!rcp)
     555           0 :     goto failed; /* Can't calculate keygrip. */
     556             : 
     557           0 :   xfree (p);
     558           0 :   ksba_cert_release (cert);
     559           0 :   ksba_reader_release (reader);
     560           0 :   return !memcmp (array, grip, 20);
     561             :  failed:
     562           0 :   xfree (p);
     563           0 :   ksba_cert_release (cert);
     564           0 :   ksba_reader_release (reader);
     565           0 :   return 0;
     566             : }
     567             : #endif /*KEYBOX_WITH_X509*/
     568             : 
     569             : 
     570             : 
     571             : /*
     572             :   The has_foo functions are used as helpers for search
     573             : */
     574             : static inline int
     575       10157 : has_short_kid (KEYBOXBLOB blob, u32 lkid)
     576             : {
     577             :   unsigned char buf[4];
     578       10157 :   buf[0] = lkid >> 24;
     579       10157 :   buf[1] = lkid >> 16;
     580       10157 :   buf[2] = lkid >> 8;
     581       10157 :   buf[3] = lkid;
     582       10157 :   return blob_cmp_fpr_part (blob, buf, 16, 4);
     583             : }
     584             : 
     585             : static inline int
     586       59099 : has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
     587             : {
     588             :   unsigned char buf[8];
     589       59099 :   buf[0] = mkid >> 24;
     590       59099 :   buf[1] = mkid >> 16;
     591       59099 :   buf[2] = mkid >> 8;
     592       59099 :   buf[3] = mkid;
     593       59099 :   buf[4] = lkid >> 24;
     594       59099 :   buf[5] = lkid >> 16;
     595       59099 :   buf[6] = lkid >> 8;
     596       59099 :   buf[7] = lkid;
     597       59099 :   return blob_cmp_fpr_part (blob, buf, 12, 8);
     598             : }
     599             : 
     600             : static inline int
     601        5124 : has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
     602             : {
     603        5124 :   return blob_cmp_fpr (blob, fpr);
     604             : }
     605             : 
     606             : static inline int
     607           0 : has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
     608             : {
     609             : #ifdef KEYBOX_WITH_X509
     610           0 :   if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
     611           0 :     return blob_x509_has_grip (blob, grip);
     612             : #else
     613             :   (void)blob;
     614             :   (void)grip;
     615             : #endif
     616           0 :   return 0;
     617             : }
     618             : 
     619             : 
     620             : static inline int
     621           0 : has_issuer (KEYBOXBLOB blob, const char *name)
     622             : {
     623             :   size_t namelen;
     624             : 
     625           0 :   return_val_if_fail (name, 0);
     626             : 
     627           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     628           0 :     return 0;
     629             : 
     630           0 :   namelen = strlen (name);
     631           0 :   return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
     632             : }
     633             : 
     634             : static inline int
     635           0 : has_issuer_sn (KEYBOXBLOB blob, const char *name,
     636             :                const unsigned char *sn, int snlen)
     637             : {
     638             :   size_t namelen;
     639             : 
     640           0 :   return_val_if_fail (name, 0);
     641           0 :   return_val_if_fail (sn, 0);
     642             : 
     643           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     644           0 :     return 0;
     645             : 
     646           0 :   namelen = strlen (name);
     647             : 
     648           0 :   return (blob_cmp_sn (blob, sn, snlen)
     649           0 :           && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
     650             : }
     651             : 
     652             : static inline int
     653           0 : has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
     654             : {
     655           0 :   return_val_if_fail (sn, 0);
     656             : 
     657           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     658           0 :     return 0;
     659           0 :   return blob_cmp_sn (blob, sn, snlen);
     660             : }
     661             : 
     662             : static inline int
     663           0 : has_subject (KEYBOXBLOB blob, const char *name)
     664             : {
     665             :   size_t namelen;
     666             : 
     667           0 :   return_val_if_fail (name, 0);
     668             : 
     669           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     670           0 :     return 0;
     671             : 
     672           0 :   namelen = strlen (name);
     673           0 :   return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
     674             : }
     675             : 
     676             : 
     677             : static inline int
     678        4408 : has_username (KEYBOXBLOB blob, const char *name, int substr)
     679             : {
     680             :   size_t namelen;
     681             :   int btype;
     682             : 
     683        4408 :   return_val_if_fail (name, 0);
     684             : 
     685        4408 :   btype = blob_get_type (blob);
     686        4408 :   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
     687           0 :     return 0;
     688             : 
     689        4408 :   namelen = strlen (name);
     690        4408 :   return blob_cmp_name (blob, -1 /* all subject/user names */, name,
     691             :                         namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
     692             : }
     693             : 
     694             : 
     695             : static inline int
     696           0 : has_mail (KEYBOXBLOB blob, const char *name, int substr)
     697             : {
     698             :   size_t namelen;
     699             :   int btype;
     700             : 
     701           0 :   return_val_if_fail (name, 0);
     702             : 
     703           0 :   btype = blob_get_type (blob);
     704           0 :   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
     705           0 :     return 0;
     706             : 
     707           0 :   if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
     708           0 :     name++; /* Hack to remove the leading '<' for gpg.  */
     709             : 
     710           0 :   namelen = strlen (name);
     711           0 :   if (namelen && name[namelen-1] == '>')
     712           0 :     namelen--;
     713           0 :   return blob_cmp_mail (blob, name, namelen, substr,
     714             :                         (btype == KEYBOX_BLOBTYPE_X509));
     715             : }
     716             : 
     717             : 
     718             : static void
     719           0 : release_sn_array (struct sn_array_s *array, size_t size)
     720             : {
     721             :   size_t n;
     722             : 
     723           0 :   for (n=0; n < size; n++)
     724           0 :     xfree (array[n].sn);
     725           0 :   xfree (array);
     726           0 : }
     727             : 
     728             : 
     729             : /*
     730             : 
     731             :   The search API
     732             : 
     733             : */
     734             : 
     735             : gpg_error_t
     736         164 : keybox_search_reset (KEYBOX_HANDLE hd)
     737             : {
     738         164 :   if (!hd)
     739           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     740             : 
     741         164 :   if (hd->found.blob)
     742             :     {
     743           5 :       _keybox_release_blob (hd->found.blob);
     744           5 :       hd->found.blob = NULL;
     745             :     }
     746             : 
     747         164 :   if (hd->fp)
     748             :     {
     749           8 :       fclose (hd->fp);
     750           8 :       hd->fp = NULL;
     751             :     }
     752         164 :   hd->error = 0;
     753         164 :   hd->eof = 0;
     754         164 :   return 0;
     755             : }
     756             : 
     757             : 
     758             : /* Note: When in ephemeral mode the search function does visit all
     759             :    blobs but in standard mode, blobs flagged as ephemeral are ignored.
     760             :    If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
     761             :    The value at R_SKIPPED is updated by the number of skipped long
     762             :    records (counts PGP and X.509). */
     763             : gpg_error_t
     764        2713 : keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
     765             :                keybox_blobtype_t want_blobtype,
     766             :                size_t *r_descindex, unsigned long *r_skipped)
     767             : {
     768             :   gpg_error_t rc;
     769             :   size_t n;
     770             :   int need_words, any_skip;
     771        2713 :   KEYBOXBLOB blob = NULL;
     772        2713 :   struct sn_array_s *sn_array = NULL;
     773             :   int pk_no, uid_no;
     774             : 
     775        2713 :   if (!hd)
     776           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     777             : 
     778             :   /* clear last found result */
     779        2713 :   if (hd->found.blob)
     780             :     {
     781         110 :       _keybox_release_blob (hd->found.blob);
     782         110 :       hd->found.blob = NULL;
     783             :     }
     784             : 
     785        2713 :   if (hd->error)
     786           0 :     return hd->error; /* still in error state */
     787        2713 :   if (hd->eof)
     788           0 :     return -1; /* still EOF */
     789             : 
     790             :   /* figure out what information we need */
     791        2713 :   need_words = any_skip = 0;
     792        5448 :   for (n=0; n < ndesc; n++)
     793             :     {
     794        2735 :       switch (desc[n].mode)
     795             :         {
     796             :         case KEYDB_SEARCH_MODE_WORDS:
     797           0 :           need_words = 1;
     798           0 :           break;
     799             :         case KEYDB_SEARCH_MODE_FIRST:
     800             :           /* always restart the search in this mode */
     801          85 :           keybox_search_reset (hd);
     802          85 :           break;
     803             :         default:
     804        2650 :           break;
     805             :         }
     806        2735 :       if (desc[n].skipfnc)
     807         210 :         any_skip = 1;
     808        2735 :       if (desc[n].snlen == -1 && !sn_array)
     809             :         {
     810           0 :           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
     811           0 :           if (!sn_array)
     812           0 :             return (hd->error = gpg_error_from_syserror ());
     813             :         }
     814             :     }
     815             : 
     816             :   (void)need_words;  /* Not yet implemented.  */
     817             : 
     818        2713 :   if (!hd->fp)
     819             :     {
     820        2603 :       hd->fp = fopen (hd->kb->fname, "rb");
     821        2603 :       if (!hd->fp)
     822             :         {
     823           0 :           hd->error = gpg_error_from_syserror ();
     824           0 :           xfree (sn_array);
     825           0 :           return hd->error;
     826             :         }
     827             :     }
     828             : 
     829             :   /* Kludge: We need to convert an SN given as hexstring to its binary
     830             :      representation - in some cases we are not able to store it in the
     831             :      search descriptor, because due to the way we use it, it is not
     832             :      possible to free allocated memory. */
     833        2713 :   if (sn_array)
     834             :     {
     835             :       const unsigned char *s;
     836             :       int i, odd;
     837             :       size_t snlen;
     838             : 
     839           0 :       for (n=0; n < ndesc; n++)
     840             :         {
     841           0 :           if (!desc[n].sn)
     842             :             ;
     843           0 :           else if (desc[n].snlen == -1)
     844             :             {
     845             :               unsigned char *sn;
     846             : 
     847           0 :               s = desc[n].sn;
     848           0 :               for (i=0; *s && *s != '/'; s++, i++)
     849             :                 ;
     850           0 :               odd = (i & 1);
     851           0 :               snlen = (i+1)/2;
     852           0 :               sn_array[n].sn = xtrymalloc (snlen);
     853           0 :               if (!sn_array[n].sn)
     854             :                 {
     855           0 :                   hd->error = gpg_error_from_syserror ();
     856           0 :                   release_sn_array (sn_array, n);
     857           0 :                   return hd->error;
     858             :                 }
     859           0 :               sn_array[n].snlen = snlen;
     860           0 :               sn = sn_array[n].sn;
     861           0 :               s = desc[n].sn;
     862           0 :               if (odd)
     863             :                 {
     864           0 :                   *sn++ = xtoi_1 (s);
     865           0 :                   s++;
     866             :                 }
     867           0 :               for (; *s && *s != '/';  s += 2)
     868           0 :                 *sn++ = xtoi_2 (s);
     869             :             }
     870             :           else
     871             :             {
     872             :               const unsigned char *sn;
     873             : 
     874           0 :               sn = desc[n].sn;
     875           0 :               snlen = desc[n].snlen;
     876           0 :               sn_array[n].sn = xtrymalloc (snlen);
     877           0 :               if (!sn_array[n].sn)
     878             :                 {
     879           0 :                   hd->error = gpg_error_from_syserror ();
     880           0 :                   release_sn_array (sn_array, n);
     881           0 :                   return hd->error;
     882             :                 }
     883           0 :               sn_array[n].snlen = snlen;
     884           0 :               memcpy (sn_array[n].sn, sn, snlen);
     885             :             }
     886             :         }
     887             :     }
     888             : 
     889             : 
     890        2713 :   pk_no = uid_no = 0;
     891             :   for (;;)
     892             :     {
     893             :       unsigned int blobflags;
     894             :       int blobtype;
     895             : 
     896       81222 :       _keybox_release_blob (blob); blob = NULL;
     897       81222 :       rc = _keybox_read_blob (&blob, hd->fp);
     898       81222 :       if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
     899           0 :           && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
     900             :         {
     901           0 :           ++*r_skipped;
     902           0 :           continue; /* Skip too large records.  */
     903             :         }
     904             : 
     905       81222 :       if (rc)
     906         184 :         break;
     907             : 
     908       81038 :       blobtype = blob_get_type (blob);
     909       81038 :       if (blobtype == KEYBOX_BLOBTYPE_HEADER)
     910        2603 :         continue;
     911       78435 :       if (want_blobtype && blobtype != want_blobtype)
     912           0 :         continue;
     913             : 
     914       78435 :       blobflags = blob_get_blob_flags (blob);
     915       78435 :       if (!hd->ephemeral && (blobflags & 2))
     916           0 :         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
     917             : 
     918      154779 :       for (n=0; n < ndesc; n++)
     919             :         {
     920       78873 :           switch (desc[n].mode)
     921             :             {
     922             :             case KEYDB_SEARCH_MODE_NONE:
     923           0 :               never_reached ();
     924           0 :               break;
     925             :             case KEYDB_SEARCH_MODE_EXACT:
     926           0 :               uid_no = has_username (blob, desc[n].u.name, 0);
     927           0 :               if (uid_no)
     928           0 :                 goto found;
     929           0 :               break;
     930             :             case KEYDB_SEARCH_MODE_MAIL:
     931           0 :               uid_no = has_mail (blob, desc[n].u.name, 0);
     932           0 :               if (uid_no)
     933           0 :                 goto found;
     934           0 :               break;
     935             :             case KEYDB_SEARCH_MODE_MAILSUB:
     936           0 :               uid_no = has_mail (blob, desc[n].u.name, 1);
     937           0 :               if (uid_no)
     938           0 :                 goto found;
     939           0 :               break;
     940             :             case KEYDB_SEARCH_MODE_SUBSTR:
     941        4408 :               uid_no =  has_username (blob, desc[n].u.name, 1);
     942        4408 :               if (uid_no)
     943         138 :                 goto found;
     944        4270 :               break;
     945             :             case KEYDB_SEARCH_MODE_MAILEND:
     946             :             case KEYDB_SEARCH_MODE_WORDS:
     947             :               /* not yet implemented */
     948           0 :               break;
     949             :             case KEYDB_SEARCH_MODE_ISSUER:
     950           0 :               if (has_issuer (blob, desc[n].u.name))
     951           0 :                 goto found;
     952           0 :               break;
     953             :             case KEYDB_SEARCH_MODE_ISSUER_SN:
     954           0 :               if (has_issuer_sn (blob, desc[n].u.name,
     955           0 :                                  sn_array? sn_array[n].sn : desc[n].sn,
     956           0 :                                  sn_array? sn_array[n].snlen : desc[n].snlen))
     957           0 :                 goto found;
     958           0 :               break;
     959             :             case KEYDB_SEARCH_MODE_SN:
     960           0 :               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
     961           0 :                                 sn_array? sn_array[n].snlen : desc[n].snlen))
     962           0 :                 goto found;
     963           0 :               break;
     964             :             case KEYDB_SEARCH_MODE_SUBJECT:
     965           0 :               if (has_subject (blob, desc[n].u.name))
     966           0 :                 goto found;
     967           0 :               break;
     968             :             case KEYDB_SEARCH_MODE_SHORT_KID:
     969       10157 :               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
     970       10157 :               if (pk_no)
     971         228 :                 goto found;
     972        9929 :               break;
     973             :             case KEYDB_SEARCH_MODE_LONG_KID:
     974       59099 :               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
     975       59099 :               if (pk_no)
     976        1938 :                 goto found;
     977       57161 :               break;
     978             :             case KEYDB_SEARCH_MODE_FPR:
     979             :             case KEYDB_SEARCH_MODE_FPR20:
     980        5124 :               pk_no = has_fingerprint (blob, desc[n].u.fpr);
     981        5124 :               if (pk_no)
     982         140 :                 goto found;
     983        4984 :               break;
     984             :             case KEYDB_SEARCH_MODE_KEYGRIP:
     985           0 :               if (has_keygrip (blob, desc[n].u.grip))
     986           0 :                 goto found;
     987           0 :               break;
     988             :             case KEYDB_SEARCH_MODE_FIRST:
     989          85 :               goto found;
     990             :               break;
     991             :             case KEYDB_SEARCH_MODE_NEXT:
     992           0 :               goto found;
     993             :               break;
     994             :             default:
     995           0 :               rc = gpg_error (GPG_ERR_INV_VALUE);
     996           0 :               goto found;
     997             :             }
     998             :         }
     999       75906 :       continue;
    1000             :     found:
    1001             :       /* Record which DESC we matched on.  Note this value is only
    1002             :          meaningful if this function returns with no errors. */
    1003        2529 :       if(r_descindex)
    1004           7 :         *r_descindex = n;
    1005        2739 :       for (n=any_skip?0:ndesc; n < ndesc; n++)
    1006             :         {
    1007             :           u32 kid[2];
    1008             : 
    1009         210 :           if (desc[n].skipfnc
    1010         210 :               && blob_get_first_keyid (blob, kid)
    1011         210 :               && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
    1012           0 :                 break;
    1013             :         }
    1014        2529 :       if (n == ndesc)
    1015        2529 :         break; /* got it */
    1016       78509 :     }
    1017             : 
    1018        2713 :   if (!rc)
    1019             :     {
    1020        2529 :       hd->found.blob = blob;
    1021        2529 :       hd->found.pk_no = pk_no;
    1022        2529 :       hd->found.uid_no = uid_no;
    1023             :     }
    1024         184 :   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
    1025             :     {
    1026         184 :       _keybox_release_blob (blob);
    1027         184 :       hd->eof = 1;
    1028             :     }
    1029             :   else
    1030             :     {
    1031           0 :       _keybox_release_blob (blob);
    1032           0 :       hd->error = rc;
    1033             :     }
    1034             : 
    1035        2713 :   if (sn_array)
    1036           0 :     release_sn_array (sn_array, ndesc);
    1037             : 
    1038        2713 :   return rc;
    1039             : }
    1040             : 
    1041             : 
    1042             : 
    1043             : 
    1044             : /*
    1045             :    Functions to return a certificate or a keyblock.  To be used after
    1046             :    a successful search operation.
    1047             : */
    1048             : 
    1049             : 
    1050             : /* Return the last found keyblock.  Returns 0 on success and stores a
    1051             :    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
    1052             :    in that case.  R_UID_NO and R_PK_NO are used to retun the number of
    1053             :    the key or user id which was matched the search criteria; if not
    1054             :    known they are set to 0. */
    1055             : gpg_error_t
    1056        2527 : keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
    1057             :                      int *r_pk_no, int *r_uid_no, u32 **r_sigstatus)
    1058             : {
    1059             :   gpg_error_t err;
    1060             :   const unsigned char *buffer, *p;
    1061             :   size_t length;
    1062             :   size_t image_off, image_len;
    1063             :   size_t siginfo_off, siginfo_len;
    1064             :   u32 *sigstatus, n, n_sigs, sigilen;
    1065             : 
    1066        2527 :   *r_iobuf = NULL;
    1067        2527 :   *r_sigstatus = NULL;
    1068             : 
    1069        2527 :   if (!hd)
    1070           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1071        2527 :   if (!hd->found.blob)
    1072           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1073             : 
    1074        2527 :   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
    1075           0 :     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
    1076             : 
    1077        2527 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1078        2527 :   if (length < 40)
    1079           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1080        2527 :   image_off = get32 (buffer+8);
    1081        2527 :   image_len = get32 (buffer+12);
    1082        2527 :   if (image_off+image_len > length)
    1083           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1084             : 
    1085        2527 :   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
    1086             :                                    &siginfo_off, &siginfo_len);
    1087        2527 :   if (err)
    1088           0 :     return err;
    1089        2527 :   n_sigs  = get16 (buffer + siginfo_off);
    1090        2527 :   sigilen = get16 (buffer + siginfo_off + 2);
    1091        2527 :   p = buffer + siginfo_off + 4;
    1092        2527 :   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
    1093        2527 :   if (!sigstatus)
    1094           0 :     return gpg_error_from_syserror ();
    1095        2527 :   sigstatus[0] = n_sigs;
    1096        8817 :   for (n=1; n <= n_sigs; n++, p += sigilen)
    1097        6290 :     sigstatus[n] = get32 (p);
    1098             : 
    1099        2527 :   *r_pk_no  = hd->found.pk_no;
    1100        2527 :   *r_uid_no = hd->found.uid_no;
    1101        2527 :   *r_sigstatus = sigstatus;
    1102        2527 :   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
    1103        2527 :   return 0;
    1104             : }
    1105             : 
    1106             : 
    1107             : #ifdef KEYBOX_WITH_X509
    1108             : /*
    1109             :   Return the last found cert.  Caller must free it.
    1110             :  */
    1111             : int
    1112           0 : keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
    1113             : {
    1114             :   const unsigned char *buffer;
    1115             :   size_t length;
    1116             :   size_t cert_off, cert_len;
    1117           0 :   ksba_reader_t reader = NULL;
    1118           0 :   ksba_cert_t cert = NULL;
    1119             :   int rc;
    1120             : 
    1121           0 :   if (!hd)
    1122           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1123           0 :   if (!hd->found.blob)
    1124           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1125             : 
    1126           0 :   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
    1127           0 :     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
    1128             : 
    1129           0 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1130           0 :   if (length < 40)
    1131           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1132           0 :   cert_off = get32 (buffer+8);
    1133           0 :   cert_len = get32 (buffer+12);
    1134           0 :   if (cert_off+cert_len > length)
    1135           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1136             : 
    1137           0 :   rc = ksba_reader_new (&reader);
    1138           0 :   if (rc)
    1139           0 :     return rc;
    1140           0 :   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
    1141           0 :   if (rc)
    1142             :     {
    1143           0 :       ksba_reader_release (reader);
    1144             :       /* fixme: need to map the error codes */
    1145           0 :       return gpg_error (GPG_ERR_GENERAL);
    1146             :     }
    1147             : 
    1148           0 :   rc = ksba_cert_new (&cert);
    1149           0 :   if (rc)
    1150             :     {
    1151           0 :       ksba_reader_release (reader);
    1152           0 :       return rc;
    1153             :     }
    1154             : 
    1155           0 :   rc = ksba_cert_read_der (cert, reader);
    1156           0 :   if (rc)
    1157             :     {
    1158           0 :       ksba_cert_release (cert);
    1159           0 :       ksba_reader_release (reader);
    1160             :       /* fixme: need to map the error codes */
    1161           0 :       return gpg_error (GPG_ERR_GENERAL);
    1162             :     }
    1163             : 
    1164           0 :   *r_cert = cert;
    1165           0 :   ksba_reader_release (reader);
    1166           0 :   return 0;
    1167             : }
    1168             : 
    1169             : #endif /*KEYBOX_WITH_X509*/
    1170             : 
    1171             : /* Return the flags named WHAT at the address of VALUE. IDX is used
    1172             :    only for certain flags and should be 0 if not required. */
    1173             : int
    1174           0 : keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
    1175             : {
    1176             :   const unsigned char *buffer;
    1177             :   size_t length;
    1178             :   gpg_err_code_t ec;
    1179             : 
    1180             :   (void)idx; /* Not yet used.  */
    1181             : 
    1182           0 :   if (!hd)
    1183           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1184           0 :   if (!hd->found.blob)
    1185           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1186             : 
    1187           0 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1188           0 :   ec = get_flag_from_image (buffer, length, what, value);
    1189           0 :   return ec? gpg_error (ec):0;
    1190             : }
    1191             : 
    1192             : off_t
    1193         105 : keybox_offset (KEYBOX_HANDLE hd)
    1194             : {
    1195         105 :   if (!hd->fp)
    1196           0 :     return 0;
    1197         105 :   return ftello (hd->fp);
    1198             : }
    1199             : 
    1200             : gpg_error_t
    1201           0 : keybox_seek (KEYBOX_HANDLE hd, off_t offset)
    1202             : {
    1203             :   int err;
    1204             : 
    1205           0 :   if (hd->error)
    1206           0 :     return hd->error; /* still in error state */
    1207             : 
    1208           0 :   if (! hd->fp)
    1209             :     {
    1210           0 :       if (offset == 0)
    1211             :         /* No need to open the file.  An unopened file is effectively at
    1212             :            offset 0.  */
    1213           0 :         return 0;
    1214             : 
    1215           0 :       hd->fp = fopen (hd->kb->fname, "rb");
    1216           0 :       if (!hd->fp)
    1217             :         {
    1218           0 :           hd->error = gpg_error_from_syserror ();
    1219           0 :           return hd->error;
    1220             :         }
    1221             :     }
    1222             : 
    1223           0 :   err = fseeko (hd->fp, offset, SEEK_SET);
    1224           0 :   hd->error = gpg_error_from_errno (err);
    1225             : 
    1226           0 :   return hd->error;
    1227             : }

Generated by: LCOV version 1.11