LCOV - code coverage report
Current view: top level - src - key.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 182 336 54.2 %
Date: 2016-09-12 13:07:23 Functions: 9 19 47.4 %

          Line data    Source code
       1             : /* key.c - Key objects.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <assert.h>
      28             : #include <errno.h>
      29             : 
      30             : #include "util.h"
      31             : #include "ops.h"
      32             : #include "sema.h"
      33             : #include "debug.h"
      34             : #include "mbox-util.h"
      35             : 
      36             : 
      37             : 
      38             : /* Protects all reference counters in keys.  All other accesses to a
      39             :    key are read only.  */
      40             : DEFINE_STATIC_LOCK (key_ref_lock);
      41             : 
      42             : 
      43             : /* Create a new key.  */
      44             : gpgme_error_t
      45         198 : _gpgme_key_new (gpgme_key_t *r_key)
      46             : {
      47             :   gpgme_key_t key;
      48             : 
      49         198 :   key = calloc (1, sizeof *key);
      50         198 :   if (!key)
      51           0 :     return gpg_error_from_syserror ();
      52         198 :   key->_refs = 1;
      53             : 
      54         198 :   *r_key = key;
      55         198 :   return 0;
      56             : }
      57             : 
      58             : 
      59             : gpgme_error_t
      60         365 : _gpgme_key_add_subkey (gpgme_key_t key, gpgme_subkey_t *r_subkey)
      61             : {
      62             :   gpgme_subkey_t subkey;
      63             : 
      64         365 :   subkey = calloc (1, sizeof *subkey);
      65         365 :   if (!subkey)
      66           0 :     return gpg_error_from_syserror ();
      67         365 :   subkey->keyid = subkey->_keyid;
      68         365 :   subkey->_keyid[16] = '\0';
      69             : 
      70         365 :   if (!key->subkeys)
      71         189 :     key->subkeys = subkey;
      72         365 :   if (key->_last_subkey)
      73         176 :     key->_last_subkey->next = subkey;
      74         365 :   key->_last_subkey = subkey;
      75             : 
      76         365 :   *r_subkey = subkey;
      77         365 :   return 0;
      78             : }
      79             : 
      80             : 
      81             : static char *
      82         966 : set_user_id_part (char *tail, const char *buf, size_t len)
      83             : {
      84        2283 :   while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
      85         351 :     len--;
      86       11233 :   for (; len; len--)
      87       10267 :     *tail++ = *buf++;
      88         966 :   *tail++ = 0;
      89         966 :   return tail;
      90             : }
      91             : 
      92             : 
      93             : static void
      94         363 : parse_user_id (char *src, char **name, char **email,
      95             :                char **comment, char *tail)
      96             : {
      97         363 :   const char *start = NULL;
      98         363 :   int in_name = 0;
      99         363 :   int in_email = 0;
     100         363 :   int in_comment = 0;
     101             : 
     102       12802 :   while (*src)
     103             :     {
     104       12076 :       if (in_email)
     105             :         {
     106        4441 :           if (*src == '<')
     107             :             /* Not legal but anyway.  */
     108           0 :             in_email++;
     109        4441 :           else if (*src == '>')
     110             :             {
     111         252 :               if (!--in_email && !*email)
     112             :                 {
     113         252 :                   *email = tail;
     114         252 :                   tail = set_user_id_part (tail, start, src - start);
     115             :                 }
     116             :             }
     117             :         }
     118        7635 :       else if (in_comment)
     119             :         {
     120        3313 :           if (*src == '(')
     121           0 :             in_comment++;
     122        3313 :           else if (*src == ')')
     123             :             {
     124         351 :               if (!--in_comment && !*comment)
     125             :                 {
     126         351 :                   *comment = tail;
     127         351 :                   tail = set_user_id_part (tail, start, src - start);
     128             :                 }
     129             :             }
     130             :         }
     131        4322 :       else if (*src == '<')
     132             :         {
     133         252 :           if (in_name)
     134             :             {
     135           0 :               if (!*name)
     136             :                 {
     137           0 :                   *name = tail;
     138           0 :                   tail = set_user_id_part (tail, start, src - start);
     139             :                 }
     140           0 :               in_name = 0;
     141             :             }
     142         252 :           in_email = 1;
     143         252 :           start = src + 1;
     144             :         }
     145        4070 :       else if (*src == '(')
     146             :         {
     147         351 :           if (in_name)
     148             :             {
     149         351 :               if (!*name)
     150             :                 {
     151         351 :                   *name = tail;
     152         351 :                   tail = set_user_id_part (tail, start, src - start);
     153             :                 }
     154         351 :               in_name = 0;
     155             :             }
     156         351 :           in_comment = 1;
     157         351 :           start = src + 1;
     158             :         }
     159        3719 :       else if (!in_name && *src != ' ' && *src != '\t')
     160             :         {
     161         363 :           in_name = 1;
     162         363 :           start = src;
     163             :         }
     164       12076 :       src++;
     165             :     }
     166             : 
     167         363 :   if (in_name)
     168             :     {
     169          12 :       if (!*name)
     170             :         {
     171          12 :           *name = tail;
     172          12 :           tail = set_user_id_part (tail, start, src - start);
     173             :         }
     174             :     }
     175             : 
     176             :   /* Let unused parts point to an EOS.  */
     177         363 :   tail--;
     178         363 :   if (!*name)
     179           0 :     *name = tail;
     180         363 :   if (!*email)
     181         111 :     *email = tail;
     182         363 :   if (!*comment)
     183          12 :     *comment = tail;
     184         363 : }
     185             : 
     186             : 
     187             : static void
     188           9 : parse_x509_user_id (char *src, char **name, char **email,
     189             :                     char **comment, char *tail)
     190             : {
     191           9 :   if (*src == '<' && src[strlen (src) - 1] == '>')
     192           3 :     *email = src;
     193             : 
     194             :   /* Let unused parts point to an EOS.  */
     195           9 :   tail--;
     196           9 :   if (!*name)
     197           9 :     *name = tail;
     198           9 :   if (!*email)
     199           6 :     *email = tail;
     200           9 :   if (!*comment)
     201           9 :     *comment = tail;
     202           9 : }
     203             : 
     204             : 
     205             : /* Take a name from the --with-colon listing, remove certain escape
     206             :    sequences sequences and put it into the list of UIDs.  */
     207             : gpgme_error_t
     208         352 : _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert)
     209             : {
     210             :   gpgme_user_id_t uid;
     211             :   char *dst;
     212         352 :   int src_len = strlen (src);
     213             : 
     214         352 :   assert (key);
     215             :   /* We can malloc a buffer of the same length, because the converted
     216             :      string will never be larger. Actually we allocate it twice the
     217             :      size, so that we are able to store the parsed stuff there too.  */
     218         352 :   uid = malloc (sizeof (*uid) + 2 * src_len + 3);
     219         352 :   if (!uid)
     220           0 :     return gpg_error_from_syserror ();
     221         352 :   memset (uid, 0, sizeof *uid);
     222             : 
     223         352 :   uid->uid = ((char *) uid) + sizeof (*uid);
     224         352 :   dst = uid->uid;
     225         352 :   if (convert)
     226         337 :     _gpgme_decode_c_string (src, &dst, src_len + 1);
     227             :   else
     228          15 :     memcpy (dst, src, src_len + 1);
     229             : 
     230         352 :   dst += strlen (dst) + 1;
     231         352 :   if (key->protocol == GPGME_PROTOCOL_CMS)
     232           9 :     parse_x509_user_id (uid->uid, &uid->name, &uid->email,
     233             :                         &uid->comment, dst);
     234             :   else
     235         343 :     parse_user_id (uid->uid, &uid->name, &uid->email,
     236             :                    &uid->comment, dst);
     237             : 
     238         352 :   uid->address = _gpgme_mailbox_from_userid (uid->uid);
     239         352 :   if (uid->address && uid->email && !strcmp (uid->address, uid->email))
     240             :     {
     241             :       /* The ADDRESS is the same as EMAIL: Save some space.  */
     242         232 :       free (uid->address);
     243         232 :       uid->address = uid->email;
     244             :     }
     245             : 
     246         352 :   if (!key->uids)
     247         196 :     key->uids = uid;
     248         352 :   if (key->_last_uid)
     249         156 :     key->_last_uid->next = uid;
     250         352 :   key->_last_uid = uid;
     251             : 
     252         352 :   return 0;
     253             : }
     254             : 
     255             : 
     256             : gpgme_key_sig_t
     257          20 : _gpgme_key_add_sig (gpgme_key_t key, char *src)
     258             : {
     259          20 :   int src_len = src ? strlen (src) : 0;
     260             :   gpgme_user_id_t uid;
     261             :   gpgme_key_sig_t sig;
     262             : 
     263          20 :   assert (key); /* XXX */
     264             : 
     265          20 :   uid = key->_last_uid;
     266          20 :   assert (uid); /* XXX */
     267             : 
     268             :   /* We can malloc a buffer of the same length, because the converted
     269             :      string will never be larger.  Actually we allocate it twice the
     270             :      size, so that we are able to store the parsed stuff there too.  */
     271          20 :   sig = malloc (sizeof (*sig) + 2 * src_len + 3);
     272          20 :   if (!sig)
     273           0 :     return NULL;
     274          20 :   memset (sig, 0, sizeof *sig);
     275             : 
     276          20 :   sig->keyid = sig->_keyid;
     277          20 :   sig->_keyid[16] = '\0';
     278          20 :   sig->uid = ((char *) sig) + sizeof (*sig);
     279             : 
     280          20 :   if (src)
     281             :     {
     282          20 :       char *dst = sig->uid;
     283          20 :       _gpgme_decode_c_string (src, &dst, src_len + 1);
     284          20 :       dst += strlen (dst) + 1;
     285          20 :       if (key->protocol == GPGME_PROTOCOL_CMS)
     286           0 :         parse_x509_user_id (sig->uid, &sig->name, &sig->email,
     287             :                             &sig->comment, dst);
     288             :       else
     289          20 :         parse_user_id (sig->uid, &sig->name, &sig->email,
     290             :                        &sig->comment, dst);
     291             :     }
     292             :   else
     293           0 :     sig->uid = '\0';
     294             : 
     295          20 :   if (!uid->signatures)
     296          15 :     uid->signatures = sig;
     297          20 :   if (uid->_last_keysig)
     298           5 :     uid->_last_keysig->next = sig;
     299          20 :   uid->_last_keysig = sig;
     300             : 
     301          20 :   return sig;
     302             : }
     303             : 
     304             : 
     305             : /* Acquire a reference to KEY.  */
     306             : void
     307          55 : gpgme_key_ref (gpgme_key_t key)
     308             : {
     309          55 :   LOCK (key_ref_lock);
     310          55 :   key->_refs++;
     311          55 :   UNLOCK (key_ref_lock);
     312          55 : }
     313             : 
     314             : 
     315             : /* gpgme_key_unref releases the key object.  Note, that this function
     316             :    may not do an actual release if there are other shallow copies of
     317             :    the objects.  You have to call this function for every newly
     318             :    created key object as well as for every gpgme_key_ref() done on the
     319             :    key object.  */
     320             : void
     321         172 : gpgme_key_unref (gpgme_key_t key)
     322             : {
     323             :   gpgme_user_id_t uid;
     324             :   gpgme_subkey_t subkey;
     325             : 
     326         172 :   if (!key)
     327           0 :     return;
     328             : 
     329         172 :   LOCK (key_ref_lock);
     330         172 :   assert (key->_refs > 0);
     331         172 :   if (--key->_refs)
     332             :     {
     333          53 :       UNLOCK (key_ref_lock);
     334          53 :       return;
     335             :     }
     336         119 :   UNLOCK (key_ref_lock);
     337             : 
     338         119 :   subkey = key->subkeys;
     339         449 :   while (subkey)
     340             :     {
     341         211 :       gpgme_subkey_t next = subkey->next;
     342         211 :       if (subkey->fpr)
     343         211 :         free (subkey->fpr);
     344         211 :       if (subkey->curve)
     345           0 :         free (subkey->curve);
     346         211 :       if (subkey->keygrip)
     347          21 :         free (subkey->keygrip);
     348         211 :       if (subkey->card_number)
     349           0 :         free (subkey->card_number);
     350         211 :       free (subkey);
     351         211 :       subkey = next;
     352             :     }
     353             : 
     354         119 :   uid = key->uids;
     355         470 :   while (uid)
     356             :     {
     357         232 :       gpgme_user_id_t next_uid = uid->next;
     358         232 :       gpgme_key_sig_t keysig = uid->signatures;
     359         232 :       gpgme_tofu_info_t tofu = uid->tofu;
     360             : 
     361         484 :       while (keysig)
     362             :         {
     363          20 :           gpgme_key_sig_t next_keysig = keysig->next;
     364          20 :           gpgme_sig_notation_t notation = keysig->notations;
     365             : 
     366          40 :           while (notation)
     367             :             {
     368           0 :               gpgme_sig_notation_t next_notation = notation->next;
     369             : 
     370           0 :               _gpgme_sig_notation_free (notation);
     371           0 :               notation = next_notation;
     372             :             }
     373             : 
     374          20 :           free (keysig);
     375          20 :           keysig = next_keysig;
     376             :         }
     377             : 
     378         486 :       while (tofu)
     379             :         {
     380             :           /* NB: The ->next is currently not used but we are prepared
     381             :            * for it.  */
     382          22 :           gpgme_tofu_info_t tofu_next = tofu->next;
     383             : 
     384          22 :           free (tofu->description);
     385          22 :           free (tofu);
     386          22 :           tofu = tofu_next;
     387             :         }
     388             : 
     389         232 :       if (uid->address && uid->address != uid->email)
     390          15 :         free (uid->address);
     391             : 
     392         232 :       free (uid);
     393         232 :       uid = next_uid;
     394             :     }
     395             : 
     396         119 :   if (key->issuer_serial)
     397           6 :     free (key->issuer_serial);
     398         119 :   if (key->issuer_name)
     399           6 :     free (key->issuer_name);
     400             : 
     401         119 :   if (key->chain_id)
     402           6 :     free (key->chain_id);
     403         119 :   if (key->fpr)
     404         119 :     free (key->fpr);
     405             : 
     406         119 :   free (key);
     407             : }
     408             : 
     409             : 
     410             : 
     411             : /* Support functions.  */
     412             : 
     413             : /* Create a dummy key to specify an email address.  */
     414             : gpgme_error_t
     415           0 : gpgme_key_from_uid (gpgme_key_t *r_key, const char *name)
     416             : {
     417             :   gpgme_error_t err;
     418             :   gpgme_key_t key;
     419             : 
     420           0 :   *r_key = NULL;
     421           0 :   err = _gpgme_key_new (&key);
     422           0 :   if (err)
     423           0 :     return err;
     424             : 
     425             :   /* Note: protocol doesn't matter if only email is provided.  */
     426           0 :   err = _gpgme_key_append_name (key, name, 0);
     427           0 :   if (err)
     428           0 :     gpgme_key_unref (key);
     429             :   else
     430           0 :     *r_key = key;
     431             : 
     432           0 :   return err;
     433             : }
     434             : 
     435             : 
     436             : 
     437             : /* Compatibility interfaces.  */
     438             : 
     439             : void
     440           0 : gpgme_key_release (gpgme_key_t key)
     441             : {
     442           0 :   gpgme_key_unref (key);
     443           0 : }
     444             : 
     445             : 
     446             : static const char *
     447           0 : otrust_to_string (int otrust)
     448             : {
     449           0 :   switch (otrust)
     450             :     {
     451             :     case GPGME_VALIDITY_NEVER:
     452           0 :       return "n";
     453             : 
     454             :     case GPGME_VALIDITY_MARGINAL:
     455           0 :       return "m";
     456             : 
     457             :     case GPGME_VALIDITY_FULL:
     458           0 :       return "f";
     459             : 
     460             :     case GPGME_VALIDITY_ULTIMATE:
     461           0 :       return "u";
     462             : 
     463             :     default:
     464           0 :       return "?";
     465             :     }
     466             : }
     467             : 
     468             : 
     469             : static const char *
     470           0 : validity_to_string (int validity)
     471             : {
     472           0 :   switch (validity)
     473             :     {
     474             :     case GPGME_VALIDITY_UNDEFINED:
     475           0 :       return "q";
     476             : 
     477             :     case GPGME_VALIDITY_NEVER:
     478           0 :       return "n";
     479             : 
     480             :     case GPGME_VALIDITY_MARGINAL:
     481           0 :       return "m";
     482             : 
     483             :     case GPGME_VALIDITY_FULL:
     484           0 :       return "f";
     485             : 
     486             :     case GPGME_VALIDITY_ULTIMATE:
     487           0 :       return "u";
     488             : 
     489             :     case GPGME_VALIDITY_UNKNOWN:
     490             :     default:
     491           0 :       return "?";
     492             :     }
     493             : }
     494             : 
     495             : 
     496             : static const char *
     497           0 : capabilities_to_string (gpgme_subkey_t subkey)
     498             : {
     499             :   static const char *const strings[8] =
     500             :     {
     501             :       "",
     502             :       "c",
     503             :       "s",
     504             :       "sc",
     505             :       "e",
     506             :       "ec",
     507             :       "es",
     508             :       "esc"
     509             :     };
     510           0 :   return strings[(!!subkey->can_encrypt << 2)
     511           0 :                  | (!!subkey->can_sign << 1)
     512           0 :                  | (!!subkey->can_certify)];
     513             : }
     514             : 
     515             : 
     516             : /* Return the value of the attribute WHAT of ITEM, which has to be
     517             :    representable by a string.  */
     518             : const char *
     519           0 : gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
     520             :                            const void *reserved, int idx)
     521             : {
     522             :   gpgme_subkey_t subkey;
     523             :   gpgme_user_id_t uid;
     524             :   int i;
     525             : 
     526           0 :   if (!key || reserved || idx < 0)
     527           0 :     return NULL;
     528             : 
     529             :   /* Select IDXth subkey.  */
     530           0 :   subkey = key->subkeys;
     531           0 :   for (i = 0; i < idx; i++)
     532             :     {
     533           0 :       subkey = subkey->next;
     534           0 :       if (!subkey)
     535           0 :         break;
     536             :     }
     537             : 
     538             :   /* Select the IDXth user ID.  */
     539           0 :   uid = key->uids;
     540           0 :   for (i = 0; i < idx; i++)
     541             :     {
     542           0 :       uid = uid->next;
     543           0 :       if (!uid)
     544           0 :         break;
     545             :     }
     546             : 
     547           0 :   switch (what)
     548             :     {
     549             :     case GPGME_ATTR_KEYID:
     550           0 :       return subkey ? subkey->keyid : NULL;
     551             : 
     552             :     case GPGME_ATTR_FPR:
     553           0 :       return subkey ? subkey->fpr : NULL;
     554             : 
     555             :     case GPGME_ATTR_ALGO:
     556           0 :       return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
     557             : 
     558             :     case GPGME_ATTR_TYPE:
     559           0 :       return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
     560             : 
     561             :     case GPGME_ATTR_OTRUST:
     562           0 :       return otrust_to_string (key->owner_trust);
     563             : 
     564             :     case GPGME_ATTR_USERID:
     565           0 :       return uid ? uid->uid : NULL;
     566             : 
     567             :     case GPGME_ATTR_NAME:
     568           0 :       return uid ? uid->name : NULL;
     569             : 
     570             :     case GPGME_ATTR_EMAIL:
     571           0 :       return uid ? uid->email : NULL;
     572             : 
     573             :     case GPGME_ATTR_COMMENT:
     574           0 :       return uid ? uid->comment : NULL;
     575             : 
     576             :     case GPGME_ATTR_VALIDITY:
     577           0 :       return uid ? validity_to_string (uid->validity) : NULL;
     578             : 
     579             :     case GPGME_ATTR_KEY_CAPS:
     580           0 :       return subkey ? capabilities_to_string (subkey) : NULL;
     581             : 
     582             :     case GPGME_ATTR_SERIAL:
     583           0 :       return key->issuer_serial;
     584             : 
     585             :     case GPGME_ATTR_ISSUER:
     586           0 :       return idx ? NULL : key->issuer_name;
     587             : 
     588             :     case GPGME_ATTR_CHAINID:
     589           0 :       return key->chain_id;
     590             : 
     591             :     default:
     592           0 :       return NULL;
     593             :     }
     594             : }
     595             : 
     596             : 
     597             : unsigned long
     598           0 : gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
     599             :                           const void *reserved, int idx)
     600             : {
     601             :   gpgme_subkey_t subkey;
     602             :   gpgme_user_id_t uid;
     603             :   int i;
     604             : 
     605           0 :   if (!key || reserved || idx < 0)
     606           0 :     return 0;
     607             : 
     608             :   /* Select IDXth subkey.  */
     609           0 :   subkey = key->subkeys;
     610           0 :   for (i = 0; i < idx; i++)
     611             :     {
     612           0 :       subkey = subkey->next;
     613           0 :       if (!subkey)
     614           0 :         break;
     615             :     }
     616             : 
     617             :   /* Select the IDXth user ID.  */
     618           0 :   uid = key->uids;
     619           0 :   for (i = 0; i < idx; i++)
     620             :     {
     621           0 :       uid = uid->next;
     622           0 :       if (!uid)
     623           0 :         break;
     624             :     }
     625             : 
     626           0 :   switch (what)
     627             :     {
     628             :     case GPGME_ATTR_ALGO:
     629           0 :       return subkey ? (unsigned long) subkey->pubkey_algo : 0;
     630             : 
     631             :     case GPGME_ATTR_LEN:
     632           0 :       return subkey ? (unsigned long) subkey->length : 0;
     633             : 
     634             :     case GPGME_ATTR_TYPE:
     635           0 :       return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
     636             : 
     637             :     case GPGME_ATTR_CREATED:
     638           0 :       return (subkey && subkey->timestamp >= 0)
     639           0 :         ? (unsigned long) subkey->timestamp : 0;
     640             : 
     641             :     case GPGME_ATTR_EXPIRE:
     642           0 :       return (subkey && subkey->expires >= 0)
     643           0 :         ? (unsigned long) subkey->expires : 0;
     644             : 
     645             :     case GPGME_ATTR_VALIDITY:
     646           0 :       return uid ? uid->validity : 0;
     647             : 
     648             :     case GPGME_ATTR_OTRUST:
     649           0 :       return key->owner_trust;
     650             : 
     651             :     case GPGME_ATTR_IS_SECRET:
     652           0 :       return !!key->secret;
     653             : 
     654             :     case GPGME_ATTR_KEY_REVOKED:
     655           0 :       return subkey ? subkey->revoked : 0;
     656             : 
     657             :     case GPGME_ATTR_KEY_INVALID:
     658           0 :       return subkey ? subkey->invalid : 0;
     659             : 
     660             :     case GPGME_ATTR_KEY_EXPIRED:
     661           0 :       return subkey ? subkey->expired : 0;
     662             : 
     663             :     case GPGME_ATTR_KEY_DISABLED:
     664           0 :       return subkey ? subkey->disabled : 0;
     665             : 
     666             :     case GPGME_ATTR_UID_REVOKED:
     667           0 :       return uid ? uid->revoked : 0;
     668             : 
     669             :     case GPGME_ATTR_UID_INVALID:
     670           0 :       return uid ? uid->invalid : 0;
     671             : 
     672             :     case GPGME_ATTR_CAN_ENCRYPT:
     673           0 :       return key->can_encrypt;
     674             : 
     675             :     case GPGME_ATTR_CAN_SIGN:
     676           0 :       return key->can_sign;
     677             : 
     678             :     case GPGME_ATTR_CAN_CERTIFY:
     679           0 :       return key->can_certify;
     680             : 
     681             :     default:
     682           0 :       return 0;
     683             :     }
     684             : }
     685             : 
     686             : 
     687             : static gpgme_key_sig_t
     688           0 : get_keysig (gpgme_key_t key, int uid_idx, int idx)
     689             : {
     690             :   gpgme_user_id_t uid;
     691             :   gpgme_key_sig_t sig;
     692             : 
     693           0 :   if (!key || uid_idx < 0 || idx < 0)
     694           0 :     return NULL;
     695             : 
     696           0 :   uid = key->uids;
     697           0 :   while (uid && uid_idx > 0)
     698             :     {
     699           0 :       uid = uid->next;
     700           0 :       uid_idx--;
     701             :     }
     702           0 :   if (!uid)
     703           0 :     return NULL;
     704             : 
     705           0 :   sig = uid->signatures;
     706           0 :   while (sig && idx > 0)
     707             :     {
     708           0 :       sig = sig->next;
     709           0 :       idx--;
     710             :     }
     711           0 :   return sig;
     712             : }
     713             : 
     714             : 
     715             : const char *
     716           0 : gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
     717             :                                _gpgme_attr_t what,
     718             :                                const void *reserved, int idx)
     719             : {
     720           0 :   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
     721             : 
     722           0 :   if (!certsig || reserved)
     723           0 :     return NULL;
     724             : 
     725           0 :   switch (what)
     726             :     {
     727             :     case GPGME_ATTR_KEYID:
     728           0 :       return certsig->keyid;
     729             : 
     730             :     case GPGME_ATTR_ALGO:
     731           0 :       return gpgme_pubkey_algo_name (certsig->pubkey_algo);
     732             : 
     733             :     case GPGME_ATTR_USERID:
     734           0 :       return certsig->uid;
     735             : 
     736             :     case GPGME_ATTR_NAME:
     737           0 :       return certsig->name;
     738             : 
     739             :     case GPGME_ATTR_EMAIL:
     740           0 :       return certsig->email;
     741             : 
     742             :     case GPGME_ATTR_COMMENT:
     743           0 :       return certsig->comment;
     744             : 
     745             :     default:
     746           0 :       return NULL;
     747             :     }
     748             : }
     749             : 
     750             : 
     751             : unsigned long
     752           0 : gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what,
     753             :                               const void *reserved, int idx)
     754             : {
     755           0 :   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
     756             : 
     757           0 :   if (!certsig || reserved)
     758           0 :     return 0;
     759             : 
     760           0 :   switch (what)
     761             :     {
     762             :     case GPGME_ATTR_ALGO:
     763           0 :       return (unsigned long) certsig->pubkey_algo;
     764             : 
     765             :     case GPGME_ATTR_CREATED:
     766           0 :       return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
     767             : 
     768             :     case GPGME_ATTR_EXPIRE:
     769           0 :       return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
     770             : 
     771             :     case GPGME_ATTR_KEY_REVOKED:
     772           0 :       return certsig->revoked;
     773             : 
     774             :     case GPGME_ATTR_KEY_INVALID:
     775           0 :       return certsig->invalid;
     776             : 
     777             :     case GPGME_ATTR_KEY_EXPIRED:
     778           0 :       return certsig->expired;
     779             : 
     780             :     case GPGME_ATTR_SIG_CLASS:
     781           0 :       return certsig->sig_class;
     782             : 
     783             :     case GPGME_ATTR_SIG_STATUS:
     784           0 :       return certsig->status;
     785             : 
     786             :     default:
     787           0 :       return 0;
     788             :     }
     789             : }

Generated by: LCOV version 1.11