LCOV - code coverage report
Current view: top level - src - keylist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 344 493 69.8 %
Date: 2015-11-05 17:14:26 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /* keylist.c - Listing keys.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007,
       4             :                  2008, 2009  g10 Code GmbH
       5             : 
       6             :    This file is part of GPGME.
       7             : 
       8             :    GPGME is free software; you can redistribute it and/or modify it
       9             :    under the terms of the GNU Lesser General Public License as
      10             :    published by the Free Software Foundation; either version 2.1 of
      11             :    the License, or (at your option) any later version.
      12             : 
      13             :    GPGME is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    Lesser General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU Lesser General Public
      19             :    License along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdio.h>
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #ifdef HAVE_SYS_TYPES_H
      29             :   /* Solaris 8 needs sys/types.h before time.h.  */
      30             : # include <sys/types.h>
      31             : #endif
      32             : #include <time.h>
      33             : #include <assert.h>
      34             : #include <ctype.h>
      35             : #include <errno.h>
      36             : 
      37             : /* Suppress warning for accessing deprecated member "class".  */
      38             : #define _GPGME_IN_GPGME
      39             : #include "gpgme.h"
      40             : #include "util.h"
      41             : #include "context.h"
      42             : #include "ops.h"
      43             : #include "debug.h"
      44             : 
      45             : 
      46             : struct key_queue_item_s
      47             : {
      48             :   struct key_queue_item_s *next;
      49             :   gpgme_key_t key;
      50             : };
      51             : 
      52             : typedef struct
      53             : {
      54             :   struct _gpgme_op_keylist_result result;
      55             : 
      56             :   gpgme_key_t tmp_key;
      57             : 
      58             :   /* This points to the last uid in tmp_key.  */
      59             :   gpgme_user_id_t tmp_uid;
      60             : 
      61             :   /* This points to the last sig in tmp_uid.  */
      62             :   gpgme_key_sig_t tmp_keysig;
      63             : 
      64             :   /* Something new is available.  */
      65             :   int key_cond;
      66             :   struct key_queue_item_s *key_queue;
      67             : } *op_data_t;
      68             : 
      69             : 
      70             : static void
      71          57 : release_op_data (void *hook)
      72             : {
      73          57 :   op_data_t opd = (op_data_t) hook;
      74          57 :   struct key_queue_item_s *key = opd->key_queue;
      75             : 
      76          57 :   if (opd->tmp_key)
      77           0 :     gpgme_key_unref (opd->tmp_key);
      78             : 
      79             :   /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
      80             :      so we do not need to release them here.  */
      81             : 
      82         114 :   while (key)
      83             :     {
      84           0 :       struct key_queue_item_s *next = key->next;
      85             : 
      86           0 :       gpgme_key_unref (key->key);
      87           0 :       key = next;
      88             :     }
      89          57 : }
      90             : 
      91             : 
      92             : gpgme_keylist_result_t
      93           3 : gpgme_op_keylist_result (gpgme_ctx_t ctx)
      94             : {
      95             :   void *hook;
      96             :   op_data_t opd;
      97             :   gpgme_error_t err;
      98             : 
      99           3 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_result", ctx);
     100             : 
     101           3 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
     102           3 :   opd = hook;
     103           3 :   if (err || !opd)
     104             :     {
     105           0 :       TRACE_SUC0 ("result=(null)");
     106           0 :       return NULL;
     107             :     }
     108             : 
     109           3 :   TRACE_LOG1 ("truncated = %i", opd->result.truncated);
     110             : 
     111           3 :   TRACE_SUC1 ("result=%p", &opd->result);
     112           3 :   return &opd->result;
     113             : }
     114             : 
     115             : 
     116             : static gpgme_error_t
     117          58 : keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
     118             : {
     119          58 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     120             :   gpgme_error_t err;
     121             :   void *hook;
     122             :   op_data_t opd;
     123             : 
     124          58 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
     125          58 :   opd = hook;
     126          58 :   if (err)
     127           0 :     return err;
     128             : 
     129          58 :   switch (code)
     130             :     {
     131             :     case GPGME_STATUS_TRUNCATED:
     132           0 :       opd->result.truncated = 1;
     133           0 :       break;
     134             : 
     135             :     default:
     136          58 :       break;
     137             :     }
     138          58 :   return 0;
     139             : }
     140             : 
     141             : 
     142             : static void
     143         172 : set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
     144             : {
     145         515 :   while (*src && !isdigit (*src))
     146             :     {
     147         171 :       switch (*src)
     148             :         {
     149             :         case 'e':
     150           2 :           subkey->expired = 1;
     151           2 :           break;
     152             : 
     153             :         case 'r':
     154           0 :           subkey->revoked = 1;
     155           0 :           break;
     156             : 
     157             :         case 'd':
     158             :           /* Note that gpg 1.3 won't print that anymore but only uses
     159             :              the capabilities field. */
     160           0 :           subkey->disabled = 1;
     161           0 :           break;
     162             : 
     163             :         case 'i':
     164           0 :           subkey->invalid = 1;
     165           0 :           break;
     166             :         }
     167         171 :       src++;
     168             :     }
     169         172 : }
     170             : 
     171             : 
     172             : static void
     173          88 : set_mainkey_trust_info (gpgme_key_t key, const char *src)
     174             : {
     175             :   /* First set the trust info of the main key (the first subkey).  */
     176          88 :   set_subkey_trust_info (key->subkeys, src);
     177             : 
     178             :   /* Now set the summarized trust info.  */
     179         263 :   while (*src && !isdigit (*src))
     180             :     {
     181          87 :       switch (*src)
     182             :         {
     183             :         case 'e':
     184           0 :           key->expired = 1;
     185           0 :           break;
     186             : 
     187             :         case 'r':
     188           0 :           key->revoked = 1;
     189           0 :           break;
     190             : 
     191             :         case 'd':
     192             :           /* Note that gpg 1.3 won't print that anymore but only uses
     193             :              the capabilities field.  However, it is still used for
     194             :              external key listings.  */
     195           0 :           key->disabled = 1;
     196           0 :           break;
     197             : 
     198             :         case 'i':
     199           0 :           key->invalid = 1;
     200           0 :           break;
     201             :         }
     202          87 :       src++;
     203             :     }
     204          88 : }
     205             : 
     206             : 
     207             : static void
     208         180 : set_userid_flags (gpgme_key_t key, const char *src)
     209             : {
     210         180 :   gpgme_user_id_t uid = key->_last_uid;
     211             : 
     212         180 :   assert (uid);
     213             :   /* Look at letters and stop at the first digit.  */
     214         538 :   while (*src && !isdigit (*src))
     215             :     {
     216         178 :       switch (*src)
     217             :         {
     218             :         case 'r':
     219           0 :           uid->revoked = 1;
     220           0 :           break;
     221             : 
     222             :         case 'i':
     223           0 :           uid->invalid = 1;
     224           0 :           break;
     225             : 
     226             :         case 'n':
     227           4 :           uid->validity = GPGME_VALIDITY_NEVER;
     228           4 :           break;
     229             : 
     230             :         case 'm':
     231           0 :           uid->validity = GPGME_VALIDITY_MARGINAL;
     232           0 :           break;
     233             : 
     234             :         case 'f':
     235           0 :           uid->validity = GPGME_VALIDITY_FULL;
     236           0 :           break;
     237             : 
     238             :         case 'u':
     239           2 :           uid->validity = GPGME_VALIDITY_ULTIMATE;
     240           2 :           break;
     241             :         }
     242         178 :       src++;
     243             :     }
     244         180 : }
     245             : 
     246             : 
     247             : static void
     248         172 : set_subkey_capability (gpgme_subkey_t subkey, const char *src)
     249             : {
     250        1026 :   while (*src)
     251             :     {
     252         682 :       switch (*src)
     253             :         {
     254             :         case 'e':
     255          86 :           subkey->can_encrypt = 1;
     256          86 :           break;
     257             : 
     258             :         case 's':
     259          86 :           subkey->can_sign = 1;
     260          86 :           break;
     261             : 
     262             :         case 'c':
     263          88 :           subkey->can_certify = 1;
     264          88 :           break;
     265             : 
     266             :         case 'a':
     267          82 :           subkey->can_authenticate = 1;
     268          82 :           break;
     269             : 
     270             :         case 'q':
     271           0 :           subkey->is_qualified = 1;
     272           0 :           break;
     273             : 
     274             :         case 'd':
     275           0 :           subkey->disabled = 1;
     276           0 :           break;
     277             :         }
     278         682 :       src++;
     279             :     }
     280         172 : }
     281             : 
     282             : 
     283             : static void
     284          88 : set_mainkey_capability (gpgme_key_t key, const char *src)
     285             : {
     286             :   /* First set the capabilities of the main key (the first subkey).  */
     287          88 :   set_subkey_capability (key->subkeys, src);
     288             : 
     289         774 :   while (*src)
     290             :     {
     291         598 :       switch (*src)
     292             :         {
     293             :         case 'd':
     294             :         case 'D':
     295             :           /* Note, that this flag is also set using the key validity
     296             :              field for backward compatibility with gpg 1.2.  We use d
     297             :              and D, so that a future gpg version will be able to
     298             :              disable certain subkeys. Currently it is expected that
     299             :              gpg sets this for the primary key. */
     300           0 :           key->disabled = 1;
     301           0 :           break;
     302             : 
     303             :         case 'e':
     304             :         case 'E':
     305          88 :           key->can_encrypt = 1;
     306          88 :           break;
     307             : 
     308             :         case 's':
     309             :         case 'S':
     310         170 :           key->can_sign = 1;
     311         170 :           break;
     312             : 
     313             :         case 'c':
     314             :         case 'C':
     315         176 :           key->can_certify = 1;
     316         176 :           break;
     317             : 
     318             :         case 'a':
     319             :         case 'A':
     320         164 :           key->can_authenticate = 1;
     321         164 :           break;
     322             : 
     323             :         case 'q':
     324             :         case 'Q':
     325           0 :           key->is_qualified = 1;
     326           0 :           break;
     327             :         }
     328         598 :       src++;
     329             :     }
     330          88 : }
     331             : 
     332             : 
     333             : static void
     334          88 : set_ownertrust (gpgme_key_t key, const char *src)
     335             : {
     336             :   /* Look at letters and stop at the first digit.  */
     337         258 :   while (*src && !isdigit (*src))
     338             :     {
     339          82 :       switch (*src)
     340             :         {
     341             :         case 'n':
     342           0 :           key->owner_trust = GPGME_VALIDITY_NEVER;
     343           0 :           break;
     344             : 
     345             :         case 'm':
     346           0 :           key->owner_trust = GPGME_VALIDITY_MARGINAL;
     347           0 :           break;
     348             : 
     349             :         case 'f':
     350           0 :           key->owner_trust = GPGME_VALIDITY_FULL;
     351           0 :           break;
     352             : 
     353             :         case 'u':
     354           0 :           key->owner_trust = GPGME_VALIDITY_ULTIMATE;
     355           0 :           break;
     356             : 
     357             :         default:
     358          82 :           key->owner_trust = GPGME_VALIDITY_UNKNOWN;
     359          82 :           break;
     360             :         }
     361          82 :       src++;
     362             :     }
     363          88 : }
     364             : 
     365             : 
     366             : /* Parse field 15 of a secret key or subkey.  This fields holds a
     367             :    reference to smartcards.  FIELD is the content of the field and we
     368             :    are allowed to modify it.  */
     369             : static gpg_error_t
     370           4 : parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field)
     371             : {
     372           4 :   if (!*field)
     373             :     ; /* Empty.  */
     374           4 :   else if (*field == '#')
     375             :     {
     376             :       /* This is a stub for an offline key.  We reset the SECRET flag
     377             :          of the subkey here.  Note that the secret flag of the entire
     378             :          key will be true even then.  We even explicitly set
     379             :          key->secret to make it works for GPGME_KEYLIST_MODE_WITH_SECRET. */
     380           0 :       subkey->secret = 0;
     381           0 :       key->secret = 1;
     382             :     }
     383           4 :   else if (strchr ("01234567890ABCDEFabcdef", *field))
     384             :     {
     385             :       /* Fields starts with a hex digit; thus it is a serial number.  */
     386           0 :       key->secret = 1;
     387           0 :       subkey->is_cardkey = 1;
     388           0 :       subkey->card_number = strdup (field);
     389           0 :       if (!subkey->card_number)
     390           0 :         return gpg_error_from_syserror ();
     391             :     }
     392           4 :   else if (*field == '+')
     393             :     {
     394           4 :       key->secret = 1;
     395           4 :       subkey->secret = 1;
     396             :     }
     397             :   else
     398             :     {
     399             :       /* RFU.  */
     400             :     }
     401             : 
     402           4 :   return 0;
     403             : }
     404             : 
     405             : 
     406             : /* We have read an entire key into tmp_key and should now finish it.
     407             :    It is assumed that this releases tmp_key.  */
     408             : static void
     409         145 : finish_key (gpgme_ctx_t ctx, op_data_t opd)
     410             : {
     411         145 :   gpgme_key_t key = opd->tmp_key;
     412             : 
     413         145 :   opd->tmp_key = NULL;
     414         145 :   opd->tmp_uid = NULL;
     415         145 :   opd->tmp_keysig = NULL;
     416             : 
     417         145 :   if (key)
     418          88 :     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
     419         145 : }
     420             : 
     421             : 
     422             : /* Note: We are allowed to modify LINE.  */
     423             : static gpgme_error_t
     424         640 : keylist_colon_handler (void *priv, char *line)
     425             : {
     426         640 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     427             :   enum
     428             :     {
     429             :       RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
     430             :       RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
     431             :     }
     432         640 :   rectype = RT_NONE;
     433             : #define NR_FIELDS 17
     434             :   char *field[NR_FIELDS];
     435         640 :   int fields = 0;
     436             :   void *hook;
     437             :   op_data_t opd;
     438             :   gpgme_error_t err;
     439             :   gpgme_key_t key;
     440         640 :   gpgme_subkey_t subkey = NULL;
     441         640 :   gpgme_key_sig_t keysig = NULL;
     442             : 
     443         640 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
     444         640 :   opd = hook;
     445         640 :   if (err)
     446           0 :     return err;
     447             : 
     448         640 :   key = opd->tmp_key;
     449             : 
     450         640 :   TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx,
     451             :           "key = %p, line = %s", key, line ? line : "(null)");
     452             : 
     453         640 :   if (!line)
     454             :     {
     455             :       /* End Of File.  */
     456          57 :       finish_key (ctx, opd);
     457          57 :       return 0;
     458             :     }
     459             : 
     460        9517 :   while (line && fields < NR_FIELDS)
     461             :     {
     462        8351 :       field[fields++] = line;
     463        8351 :       line = strchr (line, ':');
     464        8351 :       if (line)
     465        8105 :         *(line++) = '\0';
     466             :     }
     467             : 
     468         583 :   if (!strcmp (field[0], "sig"))
     469           5 :     rectype = RT_SIG;
     470         578 :   else if (!strcmp (field[0], "rev"))
     471           0 :     rectype = RT_REV;
     472         578 :   else if (!strcmp (field[0], "pub"))
     473          80 :     rectype = RT_PUB;
     474         498 :   else if (!strcmp (field[0], "sec"))
     475           2 :     rectype = RT_SEC;
     476         496 :   else if (!strcmp (field[0], "crt"))
     477           4 :     rectype = RT_CRT;
     478         492 :   else if (!strcmp (field[0], "crs"))
     479           2 :     rectype = RT_CRS;
     480         490 :   else if (!strcmp (field[0], "fpr") && key)
     481         172 :     rectype = RT_FPR;
     482         318 :   else if (!strcmp (field[0], "uid") && key)
     483         180 :     rectype = RT_UID;
     484         138 :   else if (!strcmp (field[0], "sub") && key)
     485          82 :     rectype = RT_SUB;
     486          56 :   else if (!strcmp (field[0], "ssb") && key)
     487           2 :     rectype = RT_SSB;
     488          54 :   else if (!strcmp (field[0], "spk") && key)
     489           0 :     rectype = RT_SPK;
     490             :   else
     491          54 :     rectype = RT_NONE;
     492             : 
     493             :   /* Only look at signatures immediately following a user ID.  For
     494             :      this, clear the user ID pointer when encountering anything but a
     495             :      signature.  */
     496         583 :   if (rectype != RT_SIG && rectype != RT_REV)
     497         578 :     opd->tmp_uid = NULL;
     498             : 
     499             :   /* Only look at subpackets immediately following a signature.  For
     500             :      this, clear the signature pointer when encountering anything but
     501             :      a subpacket.  */
     502         583 :   if (rectype != RT_SPK)
     503         583 :     opd->tmp_keysig = NULL;
     504             : 
     505         583 :   switch (rectype)
     506             :     {
     507             :     case RT_PUB:
     508             :     case RT_SEC:
     509             :     case RT_CRT:
     510             :     case RT_CRS:
     511             :       /* Start a new keyblock.  */
     512          88 :       err = _gpgme_key_new (&key);
     513          88 :       if (err)
     514           0 :         return err;
     515          88 :       key->keylist_mode = ctx->keylist_mode;
     516          88 :       err = _gpgme_key_add_subkey (key, &subkey);
     517          88 :       if (err)
     518             :         {
     519           0 :           gpgme_key_unref (key);
     520           0 :           return err;
     521             :         }
     522             : 
     523          88 :       if (rectype == RT_SEC || rectype == RT_CRS)
     524           4 :         key->secret = subkey->secret = 1;
     525          88 :       if (rectype == RT_CRT || rectype == RT_CRS)
     526           6 :         key->protocol = GPGME_PROTOCOL_CMS;
     527          88 :       finish_key (ctx, opd);
     528          88 :       opd->tmp_key = key;
     529             : 
     530             :       /* Field 2 has the trust info.  */
     531          88 :       if (fields >= 2)
     532          88 :         set_mainkey_trust_info (key, field[1]);
     533             : 
     534             :       /* Field 3 has the key length.  */
     535          88 :       if (fields >= 3)
     536             :         {
     537          88 :           int i = atoi (field[2]);
     538             :           /* Ignore invalid values.  */
     539          88 :           if (i > 1)
     540          88 :             subkey->length = i;
     541             :         }
     542             : 
     543             :       /* Field 4 has the public key algorithm.  */
     544          88 :       if (fields >= 4)
     545             :         {
     546          88 :           int i = atoi (field[3]);
     547          88 :           if (i >= 1 && i < 128)
     548          88 :             subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
     549             :         }
     550             : 
     551             :       /* Field 5 has the long keyid.  Allow short key IDs for the
     552             :          output of an external keyserver listing.  */
     553          88 :       if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
     554          88 :         strcpy (subkey->_keyid, field[4]);
     555             : 
     556             :       /* Field 6 has the timestamp (seconds).  */
     557          88 :       if (fields >= 6)
     558          88 :         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
     559             : 
     560             :       /* Field 7 has the expiration time (seconds).  */
     561          88 :       if (fields >= 7)
     562          88 :         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
     563             : 
     564             :       /* Field 8 has the X.509 serial number.  */
     565          88 :       if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
     566             :         {
     567           6 :           key->issuer_serial = strdup (field[7]);
     568           6 :           if (!key->issuer_serial)
     569           0 :             return gpg_error_from_syserror ();
     570             :         }
     571             : 
     572             :       /* Field 9 has the ownertrust.  */
     573          88 :       if (fields >= 9)
     574          88 :         set_ownertrust (key, field[8]);
     575             : 
     576             :       /* Field 10 is not used for gpg due to --fixed-list-mode option
     577             :          but GPGSM stores the issuer name.  */
     578          88 :       if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
     579           6 :         if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
     580           0 :           return gpg_error (GPG_ERR_ENOMEM);    /* FIXME */
     581             : 
     582             :       /* Field 11 has the signature class.  */
     583             : 
     584             :       /* Field 12 has the capabilities.  */
     585          88 :       if (fields >= 12)
     586          88 :         set_mainkey_capability (key, field[11]);
     587             : 
     588             :       /* Field 15 carries special flags of a secret key.  */
     589          88 :       if (fields >= 15
     590          85 :           && (key->secret
     591          83 :               || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
     592             :         {
     593           2 :           err = parse_sec_field15 (key, subkey, field[14]);
     594           2 :           if (err)
     595           0 :             return err;
     596             :         }
     597             : 
     598             :       /* Field 17 has the curve name for ECC.  */
     599          88 :       if (fields >= 17 && *field[16])
     600             :         {
     601           0 :           subkey->curve = strdup (field[16]);
     602           0 :           if (!subkey->curve)
     603           0 :             return gpg_error_from_syserror ();
     604             :         }
     605             : 
     606          88 :       break;
     607             : 
     608             :     case RT_SUB:
     609             :     case RT_SSB:
     610             :       /* Start a new subkey.  */
     611          84 :       err = _gpgme_key_add_subkey (key, &subkey);
     612          84 :       if (err)
     613           0 :         return err;
     614             : 
     615          84 :       if (rectype == RT_SSB)
     616           2 :         subkey->secret = 1;
     617             : 
     618             :       /* Field 2 has the trust info.  */
     619          84 :       if (fields >= 2)
     620          84 :         set_subkey_trust_info (subkey, field[1]);
     621             : 
     622             :       /* Field 3 has the key length.  */
     623          84 :       if (fields >= 3)
     624             :         {
     625          84 :           int i = atoi (field[2]);
     626             :           /* Ignore invalid values.  */
     627          84 :           if (i > 1)
     628          84 :             subkey->length = i;
     629             :         }
     630             : 
     631             :       /* Field 4 has the public key algorithm.  */
     632          84 :       if (fields >= 4)
     633             :         {
     634          84 :           int i = atoi (field[3]);
     635          84 :           if (i >= 1 && i < 128)
     636          84 :             subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
     637             :         }
     638             : 
     639             :       /* Field 5 has the long keyid.  */
     640          84 :       if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
     641          84 :         strcpy (subkey->_keyid, field[4]);
     642             : 
     643             :       /* Field 6 has the timestamp (seconds).  */
     644          84 :       if (fields >= 6)
     645          84 :         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
     646             : 
     647             :       /* Field 7 has the expiration time (seconds).  */
     648          84 :       if (fields >= 7)
     649          84 :         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
     650             : 
     651             :       /* Field 8 is reserved (LID).  */
     652             :       /* Field 9 has the ownertrust.  */
     653             :       /* Field 10, the user ID, is n/a for a subkey.  */
     654             : 
     655             :       /* Field 11 has the signature class.  */
     656             : 
     657             :       /* Field 12 has the capabilities.  */
     658          84 :       if (fields >= 12)
     659          84 :         set_subkey_capability (subkey, field[11]);
     660             : 
     661             :       /* Field 15 carries special flags of a secret key. */
     662          84 :       if (fields >= 15
     663          84 :           && (key->secret
     664          82 :               || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
     665             :         {
     666           2 :           err = parse_sec_field15 (key, subkey, field[14]);
     667           2 :           if (err)
     668           0 :             return err;
     669             :         }
     670             : 
     671             :       /* Field 17 has the curve name for ECC.  */
     672          84 :       if (fields >= 17 && *field[16])
     673             :         {
     674           0 :           subkey->curve = strdup (field[16]);
     675           0 :           if (!subkey->curve)
     676           0 :             return gpg_error_from_syserror ();
     677             :         }
     678             : 
     679          84 :       break;
     680             : 
     681             :     case RT_UID:
     682             :       /* Field 2 has the trust info, and field 10 has the user ID.  */
     683         180 :       if (fields >= 10)
     684             :         {
     685         180 :           if (_gpgme_key_append_name (key, field[9], 1))
     686           0 :             return gpg_error (GPG_ERR_ENOMEM);  /* FIXME */
     687             :           else
     688             :             {
     689         180 :               if (field[1])
     690         180 :                 set_userid_flags (key, field[1]);
     691         180 :               opd->tmp_uid = key->_last_uid;
     692             :             }
     693             :         }
     694         180 :       break;
     695             : 
     696             :     case RT_FPR:
     697             :       /* Field 10 has the fingerprint (take only the first one).  */
     698         172 :       if (fields >= 10 && field[9] && *field[9])
     699             :         {
     700             :           /* Need to apply it to the last subkey because all subkeys
     701             :              do have fingerprints. */
     702         172 :           subkey = key->_last_subkey;
     703         172 :           if (!subkey->fpr)
     704             :             {
     705         172 :               subkey->fpr = strdup (field[9]);
     706         172 :               if (!subkey->fpr)
     707           0 :                 return gpg_error_from_syserror ();
     708             :             }
     709             :         }
     710             : 
     711             :       /* Field 13 has the gpgsm chain ID (take only the first one).  */
     712         172 :       if (fields >= 13 && !key->chain_id && *field[12])
     713             :         {
     714           6 :           key->chain_id = strdup (field[12]);
     715           6 :           if (!key->chain_id)
     716           0 :             return gpg_error_from_syserror ();
     717             :         }
     718         172 :       break;
     719             : 
     720             :     case RT_SIG:
     721             :     case RT_REV:
     722           5 :       if (!opd->tmp_uid)
     723           1 :         return 0;
     724             : 
     725             :       /* Start a new (revoked) signature.  */
     726           4 :       assert (opd->tmp_uid == key->_last_uid);
     727           4 :       keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
     728           4 :       if (!keysig)
     729           0 :         return gpg_error (GPG_ERR_ENOMEM);      /* FIXME */
     730             : 
     731             :       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
     732           4 :       if (fields >= 2)
     733           4 :         switch (field[1][0])
     734             :           {
     735             :           case '!':
     736           4 :             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
     737           4 :             break;
     738             : 
     739             :           case '-':
     740           0 :             keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
     741           0 :             break;
     742             : 
     743             :           case '?':
     744           0 :             keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
     745           0 :             break;
     746             : 
     747             :           case '%':
     748           0 :             keysig->status = gpg_error (GPG_ERR_GENERAL);
     749           0 :             break;
     750             : 
     751             :           default:
     752           0 :             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
     753           0 :             break;
     754             :           }
     755             : 
     756             :       /* Field 4 has the public key algorithm.  */
     757           4 :       if (fields >= 4)
     758             :         {
     759           4 :           int i = atoi (field[3]);
     760           4 :           if (i >= 1 && i < 128)
     761           4 :             keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
     762             :         }
     763             : 
     764             :       /* Field 5 has the long keyid.  */
     765           4 :       if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
     766           4 :         strcpy (keysig->_keyid, field[4]);
     767             : 
     768             :       /* Field 6 has the timestamp (seconds).  */
     769           4 :       if (fields >= 6)
     770           4 :         keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
     771             : 
     772             :       /* Field 7 has the expiration time (seconds).  */
     773           4 :       if (fields >= 7)
     774           4 :         keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
     775             : 
     776             :       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
     777           4 :       if (fields >= 11)
     778           4 :         if (field[10][0] && field[10][1])
     779             :           {
     780           4 :             int sig_class = _gpgme_hextobyte (field[10]);
     781           4 :             if (sig_class >= 0)
     782             :               {
     783           4 :                 keysig->sig_class = sig_class;
     784           4 :                 keysig->class = keysig->sig_class;
     785           4 :                 if (sig_class == 0x30)
     786           0 :                   keysig->revoked = 1;
     787             :               }
     788           4 :             if (field[10][2] == 'x')
     789           4 :               keysig->exportable = 1;
     790             :           }
     791             : 
     792           4 :       opd->tmp_keysig = keysig;
     793           4 :       break;
     794             : 
     795             :     case RT_SPK:
     796           0 :       if (!opd->tmp_keysig)
     797           0 :         return 0;
     798           0 :       assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
     799             : 
     800           0 :       if (fields >= 4)
     801             :         {
     802             :           /* Field 2 has the subpacket type.  */
     803           0 :           int type = atoi (field[1]);
     804             : 
     805             :           /* Field 3 has the flags.  */
     806           0 :           int flags = atoi (field[2]);
     807             : 
     808             :           /* Field 4 has the length.  */
     809           0 :           int len = atoi (field[3]);
     810             : 
     811             :           /* Field 5 has the data.  */
     812           0 :           char *data = field[4];
     813             : 
     814             :           /* Type 20: Notation data.  */
     815             :           /* Type 26: Policy URL.  */
     816           0 :           if (type == 20 || type == 26)
     817             :             {
     818             :               gpgme_sig_notation_t notation;
     819             : 
     820           0 :               keysig = opd->tmp_keysig;
     821             : 
     822             :               /* At this time, any error is serious.  */
     823           0 :               err = _gpgme_parse_notation (&notation, type, flags, len, data);
     824           0 :               if (err)
     825           0 :                 return err;
     826             : 
     827             :               /* Add a new notation.  FIXME: Could be factored out.  */
     828           0 :               if (!keysig->notations)
     829           0 :                 keysig->notations = notation;
     830           0 :               if (keysig->_last_notation)
     831           0 :                 keysig->_last_notation->next = notation;
     832           0 :               keysig->_last_notation = notation;
     833             :             }
     834             :         }
     835             : 
     836             :     case RT_NONE:
     837             :       /* Unknown record.  */
     838          54 :       break;
     839             :     }
     840         582 :   return 0;
     841             : }
     842             : 
     843             : 
     844             : void
     845          88 : _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
     846             : {
     847             :   gpgme_error_t err;
     848          88 :   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
     849          88 :   gpgme_key_t key = (gpgme_key_t) type_data;
     850             :   void *hook;
     851             :   op_data_t opd;
     852             :   struct key_queue_item_s *q, *q2;
     853             : 
     854          88 :   assert (type == GPGME_EVENT_NEXT_KEY);
     855             : 
     856          88 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
     857          88 :   opd = hook;
     858          88 :   if (err)
     859           0 :     return;
     860             : 
     861          88 :   q = malloc (sizeof *q);
     862          88 :   if (!q)
     863             :     {
     864           0 :       gpgme_key_unref (key);
     865             :       /* FIXME       return GPGME_Out_Of_Core; */
     866           0 :       return;
     867             :     }
     868          88 :   q->key = key;
     869          88 :   q->next = NULL;
     870             :   /* FIXME: Use a tail pointer?  */
     871          88 :   if (!(q2 = opd->key_queue))
     872          71 :     opd->key_queue = q;
     873             :   else
     874             :     {
     875          17 :       for (; q2->next; q2 = q2->next)
     876             :         ;
     877          17 :       q2->next = q;
     878             :     }
     879          88 :   opd->key_cond = 1;
     880             : }
     881             : 
     882             : 
     883             : /* Start a keylist operation within CTX, searching for keys which
     884             :    match PATTERN.  If SECRET_ONLY is true, only secret keys are
     885             :    returned.  */
     886             : gpgme_error_t
     887          57 : gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
     888             : {
     889             :   gpgme_error_t err;
     890             :   void *hook;
     891             :   op_data_t opd;
     892          57 :   int flags = 0;
     893             : 
     894          57 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
     895             :               "pattern=%s, secret_only=%i", pattern, secret_only);
     896             : 
     897          57 :   if (!ctx)
     898           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     899             : 
     900          57 :   err = _gpgme_op_reset (ctx, 2);
     901          57 :   if (err)
     902           0 :     return TRACE_ERR (err);
     903             : 
     904          57 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
     905             :                                sizeof (*opd), release_op_data);
     906          57 :   opd = hook;
     907          57 :   if (err)
     908           0 :     return TRACE_ERR (err);
     909             : 
     910          57 :   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
     911             : 
     912          57 :   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
     913             :                                               keylist_colon_handler, ctx);
     914          57 :   if (err)
     915           0 :     return TRACE_ERR (err);
     916             : 
     917          57 :   if (ctx->offline)
     918           0 :     flags |= GPGME_ENGINE_FLAG_OFFLINE;
     919             : 
     920          57 :   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
     921             :                                   ctx->keylist_mode, flags);
     922          57 :   return TRACE_ERR (err);
     923             : }
     924             : 
     925             : 
     926             : /* Start a keylist operation within CTX, searching for keys which
     927             :    match PATTERN.  If SECRET_ONLY is true, only secret keys are
     928             :    returned.  */
     929             : gpgme_error_t
     930           0 : gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
     931             :                             int secret_only, int reserved)
     932             : {
     933             :   gpgme_error_t err;
     934             :   void *hook;
     935             :   op_data_t opd;
     936           0 :   int flags = 0;
     937             : 
     938           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
     939             :               "secret_only=%i, reserved=0x%x", secret_only, reserved);
     940             : 
     941           0 :   if (!ctx)
     942           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     943             : 
     944           0 :   err = _gpgme_op_reset (ctx, 2);
     945           0 :   if (err)
     946           0 :     return TRACE_ERR (err);
     947             : 
     948           0 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
     949             :                                sizeof (*opd), release_op_data);
     950           0 :   opd = hook;
     951           0 :   if (err)
     952           0 :     return TRACE_ERR (err);
     953             : 
     954           0 :   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
     955           0 :   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
     956             :                                               keylist_colon_handler, ctx);
     957           0 :   if (err)
     958           0 :     return TRACE_ERR (err);
     959             : 
     960           0 :   if (ctx->offline)
     961           0 :     flags |= GPGME_ENGINE_FLAG_OFFLINE;
     962             : 
     963           0 :   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
     964             :                                       reserved, ctx->keylist_mode,
     965             :                                       flags);
     966           0 :   return TRACE_ERR (err);
     967             : }
     968             : 
     969             : 
     970             : /* Return the next key from the keylist in R_KEY.  */
     971             : gpgme_error_t
     972         143 : gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
     973             : {
     974             :   gpgme_error_t err;
     975             :   struct key_queue_item_s *queue_item;
     976             :   void *hook;
     977             :   op_data_t opd;
     978             : 
     979         143 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
     980             : 
     981         143 :   if (!ctx || !r_key)
     982           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     983         143 :   *r_key = NULL;
     984         143 :   if (!ctx)
     985           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     986             : 
     987         143 :   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
     988         143 :   opd = hook;
     989         143 :   if (err)
     990           0 :     return TRACE_ERR (err);
     991         143 :   if (opd == NULL)
     992           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     993             : 
     994         143 :   if (!opd->key_queue)
     995             :     {
     996         126 :       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
     997         126 :       if (err)
     998           0 :         return TRACE_ERR (err);
     999             : 
    1000         126 :       if (!opd->key_cond)
    1001          55 :         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
    1002             : 
    1003          71 :       opd->key_cond = 0;
    1004          71 :       assert (opd->key_queue);
    1005             :     }
    1006          88 :   queue_item = opd->key_queue;
    1007          88 :   opd->key_queue = queue_item->next;
    1008          88 :   if (!opd->key_queue)
    1009          71 :     opd->key_cond = 0;
    1010             : 
    1011          88 :   *r_key = queue_item->key;
    1012          88 :   free (queue_item);
    1013             : 
    1014          88 :   return TRACE_SUC2 ("key=%p (%s)", *r_key,
    1015             :                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
    1016             :                      (*r_key)->subkeys->fpr : "invalid");
    1017             : }
    1018             : 
    1019             : 
    1020             : /* Terminate a pending keylist operation within CTX.  */
    1021             : gpgme_error_t
    1022           5 : gpgme_op_keylist_end (gpgme_ctx_t ctx)
    1023             : {
    1024           5 :   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
    1025             : 
    1026           5 :   if (!ctx)
    1027           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1028             : 
    1029           5 :   return 0;
    1030             : }
    1031             : 
    1032             : 
    1033             : /* Get the key with the fingerprint FPR from the crypto backend.  If
    1034             :    SECRET is true, get the secret key.  */
    1035             : gpgme_error_t
    1036          52 : gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
    1037             :                int secret)
    1038             : {
    1039             :   gpgme_ctx_t listctx;
    1040             :   gpgme_error_t err;
    1041             :   gpgme_key_t key;
    1042             : 
    1043          52 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
    1044             :               "fpr=%s, secret=%i", fpr, secret);
    1045             : 
    1046          52 :   if (!ctx || !r_key || !fpr)
    1047           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
    1048             : 
    1049          52 :   if (strlen (fpr) < 8)      /* We have at least a key ID.  */
    1050           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
    1051             : 
    1052             :   /* FIXME: We use our own context because we have to avoid the user's
    1053             :      I/O callback handlers.  */
    1054          52 :   err = gpgme_new (&listctx);
    1055          52 :   if (err)
    1056           0 :     return TRACE_ERR (err);
    1057             :   {
    1058             :     gpgme_protocol_t proto;
    1059             :     gpgme_engine_info_t info;
    1060             : 
    1061             :     /* Clone the relevant state.  */
    1062          52 :     proto = gpgme_get_protocol (ctx);
    1063          52 :     gpgme_set_protocol (listctx, proto);
    1064          52 :     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
    1065          52 :     info = gpgme_ctx_get_engine_info (ctx);
    1066         105 :     while (info && info->protocol != proto)
    1067           1 :       info = info->next;
    1068          52 :     if (info)
    1069          52 :       gpgme_ctx_set_engine_info (listctx, proto,
    1070          52 :                                  info->file_name, info->home_dir);
    1071             :   }
    1072             : 
    1073          52 :   err = gpgme_op_keylist_start (listctx, fpr, secret);
    1074          52 :   if (!err)
    1075          52 :     err = gpgme_op_keylist_next (listctx, r_key);
    1076          52 :   if (!err)
    1077             :     {
    1078             :     try_next_key:
    1079          52 :       err = gpgme_op_keylist_next (listctx, &key);
    1080          52 :       if (gpgme_err_code (err) == GPG_ERR_EOF)
    1081          52 :         err = 0;
    1082             :       else
    1083             :         {
    1084           0 :           if (!err
    1085           0 :               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
    1086           0 :               && key && key->subkeys && key->subkeys->fpr
    1087           0 :               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
    1088             :             {
    1089             :               /* The fingerprint is identical.  We assume that this is
    1090             :                  the same key and don't mark it as an ambiguous.  This
    1091             :                  problem may occur with corrupted keyrings and has
    1092             :                  been noticed often with gpgsm.  In fact gpgsm uses a
    1093             :                  similar hack to sort out such duplicates but it can't
    1094             :                  do that while listing keys.  */
    1095           0 :               gpgme_key_unref (key);
    1096           0 :               goto try_next_key;
    1097             :             }
    1098           0 :           if (!err)
    1099             :             {
    1100           0 :               gpgme_key_unref (key);
    1101           0 :               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
    1102             :             }
    1103           0 :           gpgme_key_unref (*r_key);
    1104             :         }
    1105             :     }
    1106          52 :   gpgme_release (listctx);
    1107          52 :   if (! err)
    1108             :     {
    1109          52 :       TRACE_LOG2 ("key=%p (%s)", *r_key,
    1110             :                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
    1111             :                   (*r_key)->subkeys->fpr : "invalid");
    1112             :     }
    1113          52 :   return TRACE_ERR (err);
    1114             : }

Generated by: LCOV version 1.11