LCOV - code coverage report
Current view: top level - kbx - keybox-search.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 238 610 39.0 %
Date: 2016-11-29 15:00:56 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 <https://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       96322 : blob_get_blob_flags (KEYBOXBLOB blob)
      50             : {
      51             :   const unsigned char *buffer;
      52             :   size_t length;
      53             : 
      54       96322 :   buffer = _keybox_get_blob_image (blob, &length);
      55       96322 :   if (length < 8)
      56           0 :     return 0; /* oops */
      57             : 
      58       96322 :   return get16 (buffer + 6);
      59             : }
      60             : 
      61             : 
      62             : /* Return the first keyid from the blob.  Returns true if
      63             :    available.  */
      64             : static int
      65         212 : blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
      66             : {
      67             :   const unsigned char *buffer;
      68             :   size_t length, nkeys, keyinfolen;
      69             : 
      70         212 :   buffer = _keybox_get_blob_image (blob, &length);
      71         212 :   if (length < 48)
      72           0 :     return 0; /* blob too short */
      73             : 
      74         212 :   nkeys = get16 (buffer + 16);
      75         212 :   keyinfolen = get16 (buffer + 18);
      76         212 :   if (!nkeys || keyinfolen < 28)
      77           0 :     return 0; /* invalid blob */
      78             : 
      79         212 :   kid[0] = get32 (buffer + 32);
      80         212 :   kid[1] = get32 (buffer + 36);
      81             : 
      82         212 :   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        3230 : _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        3230 :   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        3230 :       if (length < 20)
     113           0 :         return GPG_ERR_INV_OBJ;
     114             :       /* Key info. */
     115        3230 :       nkeys = get16 (buffer + 16);
     116        3230 :       keyinfolen = get16 (buffer + 18 );
     117        3230 :       if (keyinfolen < 28)
     118           0 :         return GPG_ERR_INV_OBJ;
     119        3230 :       pos = 20 + keyinfolen*nkeys;
     120        3230 :       if (pos+2 > length)
     121           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     122             :       /* Serial number. */
     123        3230 :       nserial = get16 (buffer+pos);
     124        3230 :       pos += 2 + nserial;
     125        3230 :       if (pos+4 > length)
     126           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     127             :       /* User IDs. */
     128        3230 :       nuids = get16 (buffer + pos); pos += 2;
     129        3230 :       uidinfolen = get16 (buffer + pos); pos += 2;
     130        3230 :       if (uidinfolen < 12 )
     131           0 :         return GPG_ERR_INV_OBJ;
     132        3230 :       pos += uidinfolen*nuids;
     133        3230 :       if (pos+4 > length)
     134           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     135             :       /* Signature info. */
     136        3230 :       siginfooff = pos;
     137        3230 :       nsigs = get16 (buffer + pos); pos += 2;
     138        3230 :       siginfolen = get16 (buffer + pos); pos += 2;
     139        3230 :       if (siginfolen < 4 )
     140           0 :         return GPG_ERR_INV_OBJ;
     141        3230 :       pos += siginfolen*nsigs;
     142        3230 :       if (pos+1+1+2+4+4+4+4 > length)
     143           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     144        3230 :       *flag_size = 1;
     145        3230 :       *flag_off = pos;
     146        3230 :       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        3230 :           *flag_size = siginfolen * nsigs;
     157        3230 :           *flag_off = siginfooff;
     158        3230 :           break;
     159             :         default:
     160           0 :           break;
     161             :         }
     162        3230 :       break;
     163             : 
     164             :     default:
     165           0 :       return GPG_ERR_INV_FLAG;
     166             :     }
     167        3230 :   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       15622 : 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       15622 :   buffer = _keybox_get_blob_image (blob, &length);
     241       15622 :   if (length < 40)
     242           0 :     return 0; /* blob too short */
     243             : 
     244             :   /*keys*/
     245       15622 :   nkeys = get16 (buffer + 16);
     246       15622 :   keyinfolen = get16 (buffer + 18 );
     247       15622 :   if (keyinfolen < 28)
     248           0 :     return 0; /* invalid blob */
     249       15622 :   pos = 20;
     250       15622 :   if (pos + keyinfolen*nkeys > length)
     251           0 :     return 0; /* out of bounds */
     252             : 
     253       43766 :   for (idx=0; idx < nkeys; idx++)
     254             :     {
     255       28662 :       off = pos + idx*keyinfolen;
     256       28662 :       if (!memcmp (buffer + off, fpr, 20))
     257         518 :         return idx+1; /* found */
     258             :     }
     259       15104 :   return 0; /* not found */
     260             : }
     261             : 
     262             : static int
     263       73347 : 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       73347 :   buffer = _keybox_get_blob_image (blob, &length);
     273       73347 :   if (length < 40)
     274           0 :     return 0; /* blob too short */
     275             : 
     276             :   /*keys*/
     277       73347 :   nkeys = get16 (buffer + 16);
     278       73347 :   keyinfolen = get16 (buffer + 18 );
     279       73347 :   if (keyinfolen < 28)
     280           0 :     return 0; /* invalid blob */
     281       73347 :   pos = 20;
     282       73347 :   if (pos + keyinfolen*nkeys > length)
     283           0 :     return 0; /* out of bounds */
     284             : 
     285      208630 :   for (idx=0; idx < nkeys; idx++)
     286             :     {
     287      137697 :       off = pos + idx*keyinfolen;
     288      137697 :       if (!memcmp (buffer + off + fproff, fpr, fprlen))
     289        2414 :         return idx+1; /* found */
     290             :     }
     291       70933 :   return 0; /* not found */
     292             : }
     293             : 
     294             : 
     295             : static int
     296        7533 : 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        7533 :   buffer = _keybox_get_blob_image (blob, &length);
     307        7533 :   if (length < 40)
     308           0 :     return 0; /* blob too short */
     309             : 
     310             :   /*keys*/
     311        7533 :   nkeys = get16 (buffer + 16);
     312        7533 :   keyinfolen = get16 (buffer + 18 );
     313        7533 :   if (keyinfolen < 28)
     314           0 :     return 0; /* invalid blob */
     315        7533 :   pos = 20 + keyinfolen*nkeys;
     316        7533 :   if (pos+2 > length)
     317           0 :     return 0; /* out of bounds */
     318             : 
     319             :   /*serial*/
     320        7533 :   nserial = get16 (buffer+pos);
     321        7533 :   pos += 2 + nserial;
     322        7533 :   if (pos+4 > length)
     323           0 :     return 0; /* out of bounds */
     324             : 
     325             :   /* user ids*/
     326        7533 :   nuids = get16 (buffer + pos);  pos += 2;
     327        7533 :   uidinfolen = get16 (buffer + pos);  pos += 2;
     328        7533 :   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
     329           0 :     return 0; /* invalid blob */
     330        7533 :   if (pos + uidinfolen*nuids > length)
     331           0 :     return 0; /* out of bounds */
     332             : 
     333        7533 :   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       15896 :       for (idx = !!x509; idx < nuids; idx++)
     337             :         {
     338        8588 :           size_t mypos = pos;
     339             : 
     340        8588 :           mypos += idx*uidinfolen;
     341        8588 :           off = get32 (buffer+mypos);
     342        8588 :           len = get32 (buffer+mypos+4);
     343        8588 :           if (off+len > length)
     344           0 :             return 0; /* error: better stop here out of bounds */
     345        8588 :           if (len < 1)
     346           0 :             continue; /* empty name */
     347        8588 :           if (substr)
     348             :             {
     349        8577 :               if (ascii_memcasemem (buffer+off, len, name, namelen))
     350         217 :                 return idx+1; /* found */
     351             :             }
     352             :           else
     353             :             {
     354          11 :               if (len == namelen && !memcmp (buffer+off, name, len))
     355           8 :                 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        7308 :   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        8012 : has_short_kid (KEYBOXBLOB blob, u32 lkid)
     576             : {
     577             :   unsigned char buf[4];
     578        8012 :   buf[0] = lkid >> 24;
     579        8012 :   buf[1] = lkid >> 16;
     580        8012 :   buf[2] = lkid >> 8;
     581        8012 :   buf[3] = lkid;
     582        8012 :   return blob_cmp_fpr_part (blob, buf, 16, 4);
     583             : }
     584             : 
     585             : static inline int
     586       65335 : has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
     587             : {
     588             :   unsigned char buf[8];
     589       65335 :   buf[0] = mkid >> 24;
     590       65335 :   buf[1] = mkid >> 16;
     591       65335 :   buf[2] = mkid >> 8;
     592       65335 :   buf[3] = mkid;
     593       65335 :   buf[4] = lkid >> 24;
     594       65335 :   buf[5] = lkid >> 16;
     595       65335 :   buf[6] = lkid >> 8;
     596       65335 :   buf[7] = lkid;
     597       65335 :   return blob_cmp_fpr_part (blob, buf, 12, 8);
     598             : }
     599             : 
     600             : static inline int
     601       15622 : has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
     602             : {
     603       15622 :   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        7533 : has_username (KEYBOXBLOB blob, const char *name, int substr)
     679             : {
     680             :   size_t namelen;
     681             :   int btype;
     682             : 
     683        7533 :   return_val_if_fail (name, 0);
     684             : 
     685        7533 :   btype = blob_get_type (blob);
     686        7533 :   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
     687           0 :     return 0;
     688             : 
     689        7533 :   namelen = strlen (name);
     690        7533 :   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         343 : keybox_search_reset (KEYBOX_HANDLE hd)
     737             : {
     738         343 :   if (!hd)
     739           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     740             : 
     741         343 :   if (hd->found.blob)
     742             :     {
     743          59 :       _keybox_release_blob (hd->found.blob);
     744          59 :       hd->found.blob = NULL;
     745             :     }
     746             : 
     747         343 :   if (hd->fp)
     748             :     {
     749          62 :       fclose (hd->fp);
     750          62 :       hd->fp = NULL;
     751             :     }
     752         343 :   hd->error = 0;
     753         343 :   hd->eof = 0;
     754         343 :   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        3900 : 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        3900 :   KEYBOXBLOB blob = NULL;
     772        3900 :   struct sn_array_s *sn_array = NULL;
     773             :   int pk_no, uid_no;
     774             : 
     775        3900 :   if (!hd)
     776           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     777             : 
     778             :   /* clear last found result */
     779        3900 :   if (hd->found.blob)
     780             :     {
     781         542 :       _keybox_release_blob (hd->found.blob);
     782         542 :       hd->found.blob = NULL;
     783             :     }
     784             : 
     785        3900 :   if (hd->error)
     786           0 :     return hd->error; /* still in error state */
     787        3900 :   if (hd->eof)
     788           0 :     return -1; /* still EOF */
     789             : 
     790             :   /* figure out what information we need */
     791        3900 :   need_words = any_skip = 0;
     792        7820 :   for (n=0; n < ndesc; n++)
     793             :     {
     794        3920 :       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          87 :           keybox_search_reset (hd);
     802          87 :           break;
     803             :         default:
     804        3833 :           break;
     805             :         }
     806        3920 :       if (desc[n].skipfnc)
     807         337 :         any_skip = 1;
     808        3920 :       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        3900 :   if (!hd->fp)
     819             :     {
     820        3356 :       hd->fp = fopen (hd->kb->fname, "rb");
     821        3356 :       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        3900 :   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        3900 :   pk_no = uid_no = 0;
     891             :   for (;;)
     892             :     {
     893             :       unsigned int blobflags;
     894             :       int blobtype;
     895             : 
     896      100336 :       _keybox_release_blob (blob); blob = NULL;
     897      100336 :       rc = _keybox_read_blob (&blob, hd->fp);
     898      100336 :       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      100336 :       if (rc)
     906         658 :         break;
     907             : 
     908       99678 :       blobtype = blob_get_type (blob);
     909       99678 :       if (blobtype == KEYBOX_BLOBTYPE_HEADER)
     910        3356 :         continue;
     911       96322 :       if (want_blobtype && blobtype != want_blobtype)
     912           0 :         continue;
     913             : 
     914       96322 :       blobflags = blob_get_blob_flags (blob);
     915       96322 :       if (!hd->ephemeral && (blobflags & 2))
     916           0 :         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
     917             : 
     918      189667 :       for (n=0; n < ndesc; n++)
     919             :         {
     920       96589 :           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           8 :               uid_no = has_username (blob, desc[n].u.name, 0);
     927           8 :               if (uid_no)
     928           8 :                 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        7525 :               uid_no =  has_username (blob, desc[n].u.name, 1);
     942        7525 :               if (uid_no)
     943         217 :                 goto found;
     944        7308 :               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        8012 :               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
     970        8012 :               if (pk_no)
     971         230 :                 goto found;
     972        7782 :               break;
     973             :             case KEYDB_SEARCH_MODE_LONG_KID:
     974       65335 :               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
     975       65335 :               if (pk_no)
     976        2184 :                 goto found;
     977       63151 :               break;
     978             :             case KEYDB_SEARCH_MODE_FPR:
     979             :             case KEYDB_SEARCH_MODE_FPR20:
     980       15622 :               pk_no = has_fingerprint (blob, desc[n].u.fpr);
     981       15622 :               if (pk_no)
     982         518 :                 goto found;
     983       15104 :               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          87 :               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       93078 :       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        3244 :       if(r_descindex)
    1004           6 :         *r_descindex = n;
    1005        3454 :       for (n=any_skip?0:ndesc; n < ndesc; n++)
    1006             :         {
    1007             :           u32 kid[2];
    1008             : 
    1009         212 :           if (desc[n].skipfnc
    1010         212 :               && blob_get_first_keyid (blob, kid)
    1011         212 :               && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
    1012           2 :                 break;
    1013             :         }
    1014        3244 :       if (n == ndesc)
    1015        3242 :         break; /* got it */
    1016       96436 :     }
    1017             : 
    1018        3900 :   if (!rc)
    1019             :     {
    1020        3242 :       hd->found.blob = blob;
    1021        3242 :       hd->found.pk_no = pk_no;
    1022        3242 :       hd->found.uid_no = uid_no;
    1023             :     }
    1024         658 :   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
    1025             :     {
    1026         658 :       _keybox_release_blob (blob);
    1027         658 :       hd->eof = 1;
    1028             :     }
    1029             :   else
    1030             :     {
    1031           0 :       _keybox_release_blob (blob);
    1032           0 :       hd->error = rc;
    1033             :     }
    1034             : 
    1035        3900 :   if (sn_array)
    1036           0 :     release_sn_array (sn_array, ndesc);
    1037             : 
    1038        3900 :   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        3230 : 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        3230 :   *r_iobuf = NULL;
    1067        3230 :   *r_sigstatus = NULL;
    1068             : 
    1069        3230 :   if (!hd)
    1070           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1071        3230 :   if (!hd->found.blob)
    1072           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1073             : 
    1074        3230 :   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
    1075           0 :     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
    1076             : 
    1077        3230 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1078        3230 :   if (length < 40)
    1079           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1080        3230 :   image_off = get32 (buffer+8);
    1081        3230 :   image_len = get32 (buffer+12);
    1082        3230 :   if (image_off+image_len > length)
    1083           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1084             : 
    1085        3230 :   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
    1086             :                                    &siginfo_off, &siginfo_len);
    1087        3230 :   if (err)
    1088           0 :     return err;
    1089        3230 :   n_sigs  = get16 (buffer + siginfo_off);
    1090        3230 :   sigilen = get16 (buffer + siginfo_off + 2);
    1091        3230 :   p = buffer + siginfo_off + 4;
    1092        3230 :   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
    1093        3230 :   if (!sigstatus)
    1094           0 :     return gpg_error_from_syserror ();
    1095        3230 :   sigstatus[0] = n_sigs;
    1096       11258 :   for (n=1; n <= n_sigs; n++, p += sigilen)
    1097        8028 :     sigstatus[n] = get32 (p);
    1098             : 
    1099        3230 :   *r_pk_no  = hd->found.pk_no;
    1100        3230 :   *r_uid_no = hd->found.uid_no;
    1101        3230 :   *r_sigstatus = sigstatus;
    1102        3230 :   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
    1103        3230 :   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         467 : keybox_offset (KEYBOX_HANDLE hd)
    1194             : {
    1195         467 :   if (!hd->fp)
    1196           0 :     return 0;
    1197         467 :   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