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