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

Generated by: LCOV version 1.11