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