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