2008-03-06 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, 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, char *src)
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   _gpgme_decode_c_string (src, &dst, src_len + 1);
223
224   dst += strlen (dst) + 1;
225   if (key->protocol == GPGME_PROTOCOL_CMS)
226     parse_x509_user_id (uid->uid, &uid->name, &uid->email,
227                         &uid->comment, dst);
228   else
229     parse_user_id (uid->uid, &uid->name, &uid->email,
230                    &uid->comment, dst);
231
232   if (!key->uids)
233     key->uids = uid;
234   if (key->_last_uid)
235     key->_last_uid->next = uid;
236   key->_last_uid = uid;
237
238   return 0;
239 }
240
241
242 gpgme_key_sig_t
243 _gpgme_key_add_sig (gpgme_key_t key, char *src)
244 {
245   int src_len = src ? strlen (src) : 0;
246   gpgme_user_id_t uid;
247   gpgme_key_sig_t sig;
248
249   assert (key); /* XXX */
250
251   uid = key->_last_uid;
252   assert (uid); /* XXX */
253
254   /* We can malloc a buffer of the same length, because the converted
255      string will never be larger.  Actually we allocate it twice the
256      size, so that we are able to store the parsed stuff there too.  */
257   sig = malloc (sizeof (*sig) + 2 * src_len + 3);
258   if (!sig)
259     return NULL;
260   memset (sig, 0, sizeof *sig);
261
262   sig->keyid = sig->_keyid;
263   sig->_keyid[16] = '\0';
264   sig->uid = ((char *) sig) + sizeof (*sig);
265
266   if (src)
267     {
268       char *dst = sig->uid;
269       _gpgme_decode_c_string (src, &dst, src_len + 1);
270       dst += strlen (dst) + 1;
271       if (key->protocol == GPGME_PROTOCOL_CMS)
272         parse_x509_user_id (sig->uid, &sig->name, &sig->email,
273                             &sig->comment, dst);
274       else
275         parse_user_id (sig->uid, &sig->name, &sig->email,
276                        &sig->comment, dst);
277     }
278   else
279     sig->uid = '\0';
280
281   if (!uid->signatures)
282     uid->signatures = sig;
283   if (uid->_last_keysig)
284     uid->_last_keysig->next = sig;
285   uid->_last_keysig = sig;
286
287   return sig;
288 }
289
290 \f
291 /* Acquire a reference to KEY.  */
292 void
293 gpgme_key_ref (gpgme_key_t key)
294 {
295   LOCK (key_ref_lock);
296   key->_refs++;
297   UNLOCK (key_ref_lock);
298 }
299
300
301 /* gpgme_key_unref releases the key object.  Note, that this function
302    may not do an actual release if there are other shallow copies of
303    the objects.  You have to call this function for every newly
304    created key object as well as for every gpgme_key_ref() done on the
305    key object.  */
306 void
307 gpgme_key_unref (gpgme_key_t key)
308 {
309   gpgme_user_id_t uid;
310   gpgme_subkey_t subkey;
311
312   if (!key)
313     return;
314
315   LOCK (key_ref_lock);
316   assert (key->_refs > 0);
317   if (--key->_refs)
318     {
319       UNLOCK (key_ref_lock);
320       return;
321     }
322   UNLOCK (key_ref_lock);
323
324   subkey = key->subkeys;
325   while (subkey)
326     {
327       gpgme_subkey_t next = subkey->next;
328       if (subkey->fpr)
329         free (subkey->fpr);
330       free (subkey);
331       subkey = next;
332     }
333
334   uid = key->uids;
335   while (uid)
336     {
337       gpgme_user_id_t next_uid = uid->next;
338       gpgme_key_sig_t keysig = uid->signatures;
339
340       while (keysig)
341         {
342           gpgme_key_sig_t next_keysig = keysig->next;
343           gpgme_sig_notation_t notation = keysig->notations;
344
345           while (notation)
346             {
347               gpgme_sig_notation_t next_notation = notation->next;
348
349               _gpgme_sig_notation_free (notation);
350               notation = next_notation;
351             }
352
353           free (keysig);
354           keysig = next_keysig;
355         }
356       free (uid);
357       uid = next_uid;
358     }
359   
360   if (key->issuer_serial)
361     free (key->issuer_serial);
362   if (key->issuer_name)
363     free (key->issuer_name);
364
365   if (key->chain_id)
366     free (key->chain_id);
367
368   free (key);
369 }
370
371 \f
372 /* Compatibility interfaces.  */
373
374 void
375 gpgme_key_release (gpgme_key_t key)
376 {
377   gpgme_key_unref (key);
378 }
379
380
381 static const char *
382 otrust_to_string (int otrust)
383 {
384   switch (otrust)
385     {
386     case GPGME_VALIDITY_NEVER:
387       return "n";
388
389     case GPGME_VALIDITY_MARGINAL:
390       return "m";
391
392     case GPGME_VALIDITY_FULL:
393       return "f";
394
395     case GPGME_VALIDITY_ULTIMATE:
396       return "u";
397
398     default:
399       return "?";
400     }
401 }
402
403
404 static const char *
405 validity_to_string (int validity)
406 {
407   switch (validity)
408     {
409     case GPGME_VALIDITY_UNDEFINED:
410       return "q";
411
412     case GPGME_VALIDITY_NEVER:
413       return "n";
414
415     case GPGME_VALIDITY_MARGINAL:
416       return "m";
417
418     case GPGME_VALIDITY_FULL:
419       return "f";
420
421     case GPGME_VALIDITY_ULTIMATE:
422       return "u";
423
424     case GPGME_VALIDITY_UNKNOWN:
425     default:
426       return "?";
427     }
428 }
429
430
431 static const char *
432 capabilities_to_string (gpgme_subkey_t subkey)
433 {
434   static const char *const strings[8] =
435     {
436       "",
437       "c",
438       "s",
439       "sc",
440       "e",
441       "ec",
442       "es",
443       "esc"
444     };
445   return strings[(!!subkey->can_encrypt << 2)
446                  | (!!subkey->can_sign << 1)
447                  | (!!subkey->can_certify)];
448 }
449
450
451 /* Return the value of the attribute WHAT of ITEM, which has to be
452    representable by a string.  */
453 const char *
454 gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
455                            const void *reserved, int idx)
456 {
457   gpgme_subkey_t subkey;
458   gpgme_user_id_t uid;
459   int i;
460
461   if (!key || reserved || idx < 0)
462     return NULL;
463
464   /* Select IDXth subkey.  */
465   subkey = key->subkeys;
466   for (i = 0; i < idx; i++)
467     {
468       subkey = subkey->next;
469       if (!subkey)
470         break;
471     }
472
473   /* Select the IDXth user ID.  */
474   uid = key->uids;
475   for (i = 0; i < idx; i++)
476     {
477       uid = uid->next;
478       if (!uid)
479         break;
480     }
481
482   switch (what)
483     {
484     case GPGME_ATTR_KEYID:
485       return subkey ? subkey->keyid : NULL;
486
487     case GPGME_ATTR_FPR:
488       return subkey ? subkey->fpr : NULL;
489
490     case GPGME_ATTR_ALGO:    
491       return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
492
493     case GPGME_ATTR_TYPE:
494       return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
495
496     case GPGME_ATTR_OTRUST:
497       return otrust_to_string (key->owner_trust);
498
499     case GPGME_ATTR_USERID:  
500       return uid ? uid->uid : NULL;
501
502     case GPGME_ATTR_NAME:   
503       return uid ? uid->name : NULL;
504
505     case GPGME_ATTR_EMAIL:
506       return uid ? uid->email : NULL;
507
508     case GPGME_ATTR_COMMENT:
509       return uid ? uid->comment : NULL;
510
511     case GPGME_ATTR_VALIDITY:
512       return uid ? validity_to_string (uid->validity) : NULL;
513
514     case GPGME_ATTR_KEY_CAPS:    
515       return subkey ? capabilities_to_string (subkey) : NULL;
516
517     case GPGME_ATTR_SERIAL:
518       return key->issuer_serial;
519
520     case GPGME_ATTR_ISSUER:
521       return idx ? NULL : key->issuer_name;
522
523     case GPGME_ATTR_CHAINID:
524       return key->chain_id;
525
526     default:
527       return NULL;
528     }
529 }
530
531
532 unsigned long
533 gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
534                           const void *reserved, int idx)
535 {
536   gpgme_subkey_t subkey;
537   gpgme_user_id_t uid;
538   int i;
539
540   if (!key || reserved || idx < 0)
541     return 0;
542
543   /* Select IDXth subkey.  */
544   subkey = key->subkeys;
545   for (i = 0; i < idx; i++)
546     {
547       subkey = subkey->next;
548       if (!subkey)
549         break;
550     }
551
552   /* Select the IDXth user ID.  */
553   uid = key->uids;
554   for (i = 0; i < idx; i++)
555     {
556       uid = uid->next;
557       if (!uid)
558         break;
559     }
560
561   switch (what)
562     {
563     case GPGME_ATTR_ALGO:
564       return subkey ? (unsigned long) subkey->pubkey_algo : 0;
565
566     case GPGME_ATTR_LEN:
567       return subkey ? (unsigned long) subkey->length : 0;
568
569     case GPGME_ATTR_TYPE:
570       return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
571
572     case GPGME_ATTR_CREATED:
573       return (subkey && subkey->timestamp >= 0)
574         ? (unsigned long) subkey->timestamp : 0;
575
576     case GPGME_ATTR_EXPIRE: 
577       return (subkey && subkey->expires >= 0)
578         ? (unsigned long) subkey->expires : 0;
579
580     case GPGME_ATTR_VALIDITY:
581       return uid ? uid->validity : 0;
582
583     case GPGME_ATTR_OTRUST:
584       return key->owner_trust;
585
586     case GPGME_ATTR_IS_SECRET:
587       return !!key->secret;
588
589     case GPGME_ATTR_KEY_REVOKED:
590       return subkey ? subkey->revoked : 0;
591
592     case GPGME_ATTR_KEY_INVALID:
593       return subkey ? subkey->invalid : 0;
594
595     case GPGME_ATTR_KEY_EXPIRED:
596       return subkey ? subkey->expired : 0;
597
598     case GPGME_ATTR_KEY_DISABLED:
599       return subkey ? subkey->disabled : 0;
600
601     case GPGME_ATTR_UID_REVOKED:
602       return uid ? uid->revoked : 0;
603
604     case GPGME_ATTR_UID_INVALID:
605       return uid ? uid->invalid : 0;
606
607     case GPGME_ATTR_CAN_ENCRYPT:
608       return key->can_encrypt;
609
610     case GPGME_ATTR_CAN_SIGN:
611       return key->can_sign;
612
613     case GPGME_ATTR_CAN_CERTIFY:
614       return key->can_certify;
615
616     default:
617       return 0;
618     }
619 }
620
621
622 static gpgme_key_sig_t
623 get_keysig (gpgme_key_t key, int uid_idx, int idx)
624 {
625   gpgme_user_id_t uid;
626   gpgme_key_sig_t sig;
627
628   if (!key || uid_idx < 0 || idx < 0)
629     return NULL;
630
631   uid = key->uids;
632   while (uid && uid_idx > 0)
633     {
634       uid = uid->next;
635       uid_idx--;
636     }
637   if (!uid)
638     return NULL;
639
640   sig = uid->signatures;
641   while (sig && idx > 0)
642     {
643       sig = sig->next;
644       idx--;
645     }
646   return sig;
647 }
648
649
650 const char *
651 gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
652                                _gpgme_attr_t what,
653                                const void *reserved, int idx)
654 {
655   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
656
657   if (!certsig || reserved)
658     return NULL;
659
660   switch (what)
661     {
662     case GPGME_ATTR_KEYID:
663       return certsig->keyid;
664
665     case GPGME_ATTR_ALGO:    
666       return gpgme_pubkey_algo_name (certsig->pubkey_algo);
667
668     case GPGME_ATTR_USERID:
669       return certsig->uid;
670
671     case GPGME_ATTR_NAME:   
672       return certsig->name;
673
674     case GPGME_ATTR_EMAIL:
675       return certsig->email;
676
677     case GPGME_ATTR_COMMENT:
678       return certsig->comment;
679    
680     default:
681       return NULL;
682     }
683 }
684
685
686 unsigned long
687 gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what,
688                               const void *reserved, int idx)
689 {
690   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
691
692   if (!certsig || reserved)
693     return 0;
694
695   switch (what)
696     {
697     case GPGME_ATTR_ALGO:    
698       return (unsigned long) certsig->pubkey_algo;
699
700     case GPGME_ATTR_CREATED: 
701       return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
702
703     case GPGME_ATTR_EXPIRE: 
704       return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
705
706     case GPGME_ATTR_KEY_REVOKED:
707       return certsig->revoked;
708
709     case GPGME_ATTR_KEY_INVALID:
710       return certsig->invalid;
711
712     case GPGME_ATTR_KEY_EXPIRED:
713       return certsig->expired;
714
715     case GPGME_ATTR_SIG_CLASS:
716       return certsig->sig_class;
717
718     case GPGME_ATTR_SIG_STATUS:
719       return certsig->status;
720
721     default:
722       return 0;
723     }
724 }