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

Generated by: LCOV version 1.13