Really add file.
[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, 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       if (subkey->card_number)
331         free (subkey->card_number);
332       free (subkey);
333       subkey = next;
334     }
335
336   uid = key->uids;
337   while (uid)
338     {
339       gpgme_user_id_t next_uid = uid->next;
340       gpgme_key_sig_t keysig = uid->signatures;
341
342       while (keysig)
343         {
344           gpgme_key_sig_t next_keysig = keysig->next;
345           gpgme_sig_notation_t notation = keysig->notations;
346
347           while (notation)
348             {
349               gpgme_sig_notation_t next_notation = notation->next;
350
351               _gpgme_sig_notation_free (notation);
352               notation = next_notation;
353             }
354
355           free (keysig);
356           keysig = next_keysig;
357         }
358       free (uid);
359       uid = next_uid;
360     }
361   
362   if (key->issuer_serial)
363     free (key->issuer_serial);
364   if (key->issuer_name)
365     free (key->issuer_name);
366
367   if (key->chain_id)
368     free (key->chain_id);
369
370   free (key);
371 }
372
373 \f
374 /* Compatibility interfaces.  */
375
376 void
377 gpgme_key_release (gpgme_key_t key)
378 {
379   gpgme_key_unref (key);
380 }
381
382
383 static const char *
384 otrust_to_string (int otrust)
385 {
386   switch (otrust)
387     {
388     case GPGME_VALIDITY_NEVER:
389       return "n";
390
391     case GPGME_VALIDITY_MARGINAL:
392       return "m";
393
394     case GPGME_VALIDITY_FULL:
395       return "f";
396
397     case GPGME_VALIDITY_ULTIMATE:
398       return "u";
399
400     default:
401       return "?";
402     }
403 }
404
405
406 static const char *
407 validity_to_string (int validity)
408 {
409   switch (validity)
410     {
411     case GPGME_VALIDITY_UNDEFINED:
412       return "q";
413
414     case GPGME_VALIDITY_NEVER:
415       return "n";
416
417     case GPGME_VALIDITY_MARGINAL:
418       return "m";
419
420     case GPGME_VALIDITY_FULL:
421       return "f";
422
423     case GPGME_VALIDITY_ULTIMATE:
424       return "u";
425
426     case GPGME_VALIDITY_UNKNOWN:
427     default:
428       return "?";
429     }
430 }
431
432
433 static const char *
434 capabilities_to_string (gpgme_subkey_t subkey)
435 {
436   static const char *const strings[8] =
437     {
438       "",
439       "c",
440       "s",
441       "sc",
442       "e",
443       "ec",
444       "es",
445       "esc"
446     };
447   return strings[(!!subkey->can_encrypt << 2)
448                  | (!!subkey->can_sign << 1)
449                  | (!!subkey->can_certify)];
450 }
451
452
453 /* Return the value of the attribute WHAT of ITEM, which has to be
454    representable by a string.  */
455 const char *
456 gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
457                            const void *reserved, int idx)
458 {
459   gpgme_subkey_t subkey;
460   gpgme_user_id_t uid;
461   int i;
462
463   if (!key || reserved || idx < 0)
464     return NULL;
465
466   /* Select IDXth subkey.  */
467   subkey = key->subkeys;
468   for (i = 0; i < idx; i++)
469     {
470       subkey = subkey->next;
471       if (!subkey)
472         break;
473     }
474
475   /* Select the IDXth user ID.  */
476   uid = key->uids;
477   for (i = 0; i < idx; i++)
478     {
479       uid = uid->next;
480       if (!uid)
481         break;
482     }
483
484   switch (what)
485     {
486     case GPGME_ATTR_KEYID:
487       return subkey ? subkey->keyid : NULL;
488
489     case GPGME_ATTR_FPR:
490       return subkey ? subkey->fpr : NULL;
491
492     case GPGME_ATTR_ALGO:    
493       return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
494
495     case GPGME_ATTR_TYPE:
496       return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
497
498     case GPGME_ATTR_OTRUST:
499       return otrust_to_string (key->owner_trust);
500
501     case GPGME_ATTR_USERID:  
502       return uid ? uid->uid : NULL;
503
504     case GPGME_ATTR_NAME:   
505       return uid ? uid->name : NULL;
506
507     case GPGME_ATTR_EMAIL:
508       return uid ? uid->email : NULL;
509
510     case GPGME_ATTR_COMMENT:
511       return uid ? uid->comment : NULL;
512
513     case GPGME_ATTR_VALIDITY:
514       return uid ? validity_to_string (uid->validity) : NULL;
515
516     case GPGME_ATTR_KEY_CAPS:    
517       return subkey ? capabilities_to_string (subkey) : NULL;
518
519     case GPGME_ATTR_SERIAL:
520       return key->issuer_serial;
521
522     case GPGME_ATTR_ISSUER:
523       return idx ? NULL : key->issuer_name;
524
525     case GPGME_ATTR_CHAINID:
526       return key->chain_id;
527
528     default:
529       return NULL;
530     }
531 }
532
533
534 unsigned long
535 gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
536                           const void *reserved, int idx)
537 {
538   gpgme_subkey_t subkey;
539   gpgme_user_id_t uid;
540   int i;
541
542   if (!key || reserved || idx < 0)
543     return 0;
544
545   /* Select IDXth subkey.  */
546   subkey = key->subkeys;
547   for (i = 0; i < idx; i++)
548     {
549       subkey = subkey->next;
550       if (!subkey)
551         break;
552     }
553
554   /* Select the IDXth user ID.  */
555   uid = key->uids;
556   for (i = 0; i < idx; i++)
557     {
558       uid = uid->next;
559       if (!uid)
560         break;
561     }
562
563   switch (what)
564     {
565     case GPGME_ATTR_ALGO:
566       return subkey ? (unsigned long) subkey->pubkey_algo : 0;
567
568     case GPGME_ATTR_LEN:
569       return subkey ? (unsigned long) subkey->length : 0;
570
571     case GPGME_ATTR_TYPE:
572       return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
573
574     case GPGME_ATTR_CREATED:
575       return (subkey && subkey->timestamp >= 0)
576         ? (unsigned long) subkey->timestamp : 0;
577
578     case GPGME_ATTR_EXPIRE: 
579       return (subkey && subkey->expires >= 0)
580         ? (unsigned long) subkey->expires : 0;
581
582     case GPGME_ATTR_VALIDITY:
583       return uid ? uid->validity : 0;
584
585     case GPGME_ATTR_OTRUST:
586       return key->owner_trust;
587
588     case GPGME_ATTR_IS_SECRET:
589       return !!key->secret;
590
591     case GPGME_ATTR_KEY_REVOKED:
592       return subkey ? subkey->revoked : 0;
593
594     case GPGME_ATTR_KEY_INVALID:
595       return subkey ? subkey->invalid : 0;
596
597     case GPGME_ATTR_KEY_EXPIRED:
598       return subkey ? subkey->expired : 0;
599
600     case GPGME_ATTR_KEY_DISABLED:
601       return subkey ? subkey->disabled : 0;
602
603     case GPGME_ATTR_UID_REVOKED:
604       return uid ? uid->revoked : 0;
605
606     case GPGME_ATTR_UID_INVALID:
607       return uid ? uid->invalid : 0;
608
609     case GPGME_ATTR_CAN_ENCRYPT:
610       return key->can_encrypt;
611
612     case GPGME_ATTR_CAN_SIGN:
613       return key->can_sign;
614
615     case GPGME_ATTR_CAN_CERTIFY:
616       return key->can_certify;
617
618     default:
619       return 0;
620     }
621 }
622
623
624 static gpgme_key_sig_t
625 get_keysig (gpgme_key_t key, int uid_idx, int idx)
626 {
627   gpgme_user_id_t uid;
628   gpgme_key_sig_t sig;
629
630   if (!key || uid_idx < 0 || idx < 0)
631     return NULL;
632
633   uid = key->uids;
634   while (uid && uid_idx > 0)
635     {
636       uid = uid->next;
637       uid_idx--;
638     }
639   if (!uid)
640     return NULL;
641
642   sig = uid->signatures;
643   while (sig && idx > 0)
644     {
645       sig = sig->next;
646       idx--;
647     }
648   return sig;
649 }
650
651
652 const char *
653 gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
654                                _gpgme_attr_t what,
655                                const void *reserved, int idx)
656 {
657   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
658
659   if (!certsig || reserved)
660     return NULL;
661
662   switch (what)
663     {
664     case GPGME_ATTR_KEYID:
665       return certsig->keyid;
666
667     case GPGME_ATTR_ALGO:    
668       return gpgme_pubkey_algo_name (certsig->pubkey_algo);
669
670     case GPGME_ATTR_USERID:
671       return certsig->uid;
672
673     case GPGME_ATTR_NAME:   
674       return certsig->name;
675
676     case GPGME_ATTR_EMAIL:
677       return certsig->email;
678
679     case GPGME_ATTR_COMMENT:
680       return certsig->comment;
681    
682     default:
683       return NULL;
684     }
685 }
686
687
688 unsigned long
689 gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what,
690                               const void *reserved, int idx)
691 {
692   gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
693
694   if (!certsig || reserved)
695     return 0;
696
697   switch (what)
698     {
699     case GPGME_ATTR_ALGO:    
700       return (unsigned long) certsig->pubkey_algo;
701
702     case GPGME_ATTR_CREATED: 
703       return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
704
705     case GPGME_ATTR_EXPIRE: 
706       return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
707
708     case GPGME_ATTR_KEY_REVOKED:
709       return certsig->revoked;
710
711     case GPGME_ATTR_KEY_INVALID:
712       return certsig->invalid;
713
714     case GPGME_ATTR_KEY_EXPIRED:
715       return certsig->expired;
716
717     case GPGME_ATTR_SIG_CLASS:
718       return certsig->sig_class;
719
720     case GPGME_ATTR_SIG_STATUS:
721       return certsig->status;
722
723     default:
724       return 0;
725     }
726 }