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