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