ab0c1463ee0e2e5762a09912e7aec916429bca00
[gnupg.git] / g10 / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include "util.h"
32 #include "options.h"
33 #include "main.h" /*try_make_homedir ()*/
34 #include "packet.h"
35 #include "keyring.h"
36 #include "keydb.h" 
37 #include "i18n.h"
38
39 static int active_handles;
40
41 typedef enum {
42     KEYDB_RESOURCE_TYPE_NONE = 0,
43     KEYDB_RESOURCE_TYPE_KEYRING
44 } KeydbResourceType;
45 #define MAX_KEYDB_RESOURCES 40
46
47 struct resource_item {
48   KeydbResourceType type;
49   union {
50     KEYRING_HANDLE kr;
51   } u;
52   void *token;
53   int secret;
54 };
55
56 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
57 static int used_resources;
58 static void *primary_keyring=NULL;
59
60 struct keydb_handle {
61   int locked;
62   int found;
63   int current;
64   int used; /* items in active */
65   struct resource_item active[MAX_KEYDB_RESOURCES];
66 };
67
68
69 static int lock_all (KEYDB_HANDLE hd);
70 static void unlock_all (KEYDB_HANDLE hd);
71
72
73 /*
74  * Register a resource (which currently may only be a keyring file).
75  * The first keyring which is added by this function is
76  * created if it does not exist.
77  * Note: this function may be called before secure memory is
78  * available.
79  * Flag 1 == force
80  * Flag 2 == default
81  */
82 int
83 keydb_add_resource (const char *url, int flags, int secret)
84 {
85     static int any_secret, any_public;
86     const char *resname = url;
87     IOBUF iobuf = NULL;
88     char *filename = NULL;
89     int force=(flags&1);
90     int rc = 0;
91     KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
92     void *token;
93
94     /* Do we have an URL?
95      *  gnupg-ring:filename  := this is a plain keyring
96      *  filename := See what is is, but create as plain keyring.
97      */
98     if (strlen (resname) > 11) {
99         if (!strncmp( resname, "gnupg-ring:", 11) ) {
100             rt = KEYDB_RESOURCE_TYPE_KEYRING;
101             resname += 11;
102         }
103 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
104         else if (strchr (resname, ':')) {
105             log_error ("invalid key resource URL `%s'\n", url );
106             rc = G10ERR_GENERAL;
107             goto leave;
108         }
109 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
110     }
111
112     if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
113         if (strchr(resname, DIRSEP_C) )
114             filename = make_filename (resname, NULL);
115         else
116             filename = make_filename (opt.homedir, resname, NULL);
117     }
118     else
119         filename = m_strdup (resname);
120
121     if (!force)
122         force = secret? !any_secret : !any_public;
123
124     /* see whether we can determine the filetype */
125     if (rt == KEYDB_RESOURCE_TYPE_NONE) {
126         FILE *fp = fopen( filename, "rb" );
127
128         if (fp) {
129             u32 magic;
130
131             if (fread( &magic, 4, 1, fp) == 1 ) {
132                 if (magic == 0x13579ace || magic == 0xce9a5713)
133                     ; /* GDBM magic - no more support */
134                 else
135                     rt = KEYDB_RESOURCE_TYPE_KEYRING;
136             }
137             else /* maybe empty: assume ring */
138                 rt = KEYDB_RESOURCE_TYPE_KEYRING;
139             fclose( fp );
140         }
141         else /* no file yet: create ring */
142             rt = KEYDB_RESOURCE_TYPE_KEYRING;
143     }
144
145     switch (rt) {
146       case KEYDB_RESOURCE_TYPE_NONE:
147         log_error ("unknown type of key resource `%s'\n", url );
148         rc = G10ERR_GENERAL;
149         goto leave;
150
151       case KEYDB_RESOURCE_TYPE_KEYRING:
152         if (access(filename, F_OK))
153           { /* file does not exist */
154             mode_t oldmask;
155             char *last_slash_in_filename;
156
157             if (!force) 
158               {
159                 rc = G10ERR_OPEN_FILE;
160                 goto leave;
161               }
162
163             last_slash_in_filename = strrchr (filename, DIRSEP_C);
164             *last_slash_in_filename = 0;
165             if (access(filename, F_OK))
166               { /* On the first time we try to create the default
167                    homedir and check again. */
168                 static int tried;
169                 
170                 if (!tried)
171                   {
172                     tried = 1;
173                     try_make_homedir (filename);
174                   }
175                 if (access (filename, F_OK))
176                   {
177                     rc = G10ERR_OPEN_FILE;
178                     *last_slash_in_filename = DIRSEP_C;
179                     goto leave;
180                   }
181               }
182             *last_slash_in_filename = DIRSEP_C;
183
184             oldmask=umask(077);
185             iobuf = iobuf_create (filename);
186             umask(oldmask);
187             if (!iobuf) 
188               {
189                 log_error ( _("error creating keyring `%s': %s\n"),
190                             filename, strerror(errno));
191                 rc = G10ERR_OPEN_FILE;
192                 goto leave;
193               }
194
195             if (!opt.quiet)
196               log_info (_("keyring `%s' created\n"), filename);
197             iobuf_close (iobuf);
198             iobuf = NULL;
199             /* must invalidate that ugly cache */
200             iobuf_ioctl (NULL, 2, 0, (char*)filename);
201           } /* end file creation */
202
203         if(keyring_register_filename (filename, secret, &token))
204           {
205             if (used_resources >= MAX_KEYDB_RESOURCES)
206               rc = G10ERR_RESOURCE_LIMIT;
207             else 
208               {
209                 if(flags&2)
210                   primary_keyring=token;
211                 all_resources[used_resources].type = rt;
212                 all_resources[used_resources].u.kr = NULL; /* Not used here */
213                 all_resources[used_resources].token = token;
214                 all_resources[used_resources].secret = secret;
215                 used_resources++;
216               }
217           }
218         else
219           {
220             /* This keyring was already registered, so ignore it.
221                However, we can still mark it as primary even if it was
222                already registered. */
223             if(flags&2)
224               primary_keyring=token;
225           }
226         break;
227
228       default:
229         log_error ("resource type of `%s' not supported\n", url);
230         rc = G10ERR_GENERAL;
231         goto leave;
232     }
233
234     /* fixme: check directory permissions and print a warning */
235
236   leave:
237     if (rc)
238         log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
239     else if (secret)
240         any_secret = 1;
241     else
242         any_public = 1;
243     m_free (filename);
244     return rc;
245 }
246
247
248
249
250 KEYDB_HANDLE
251 keydb_new (int secret)
252 {
253   KEYDB_HANDLE hd;
254   int i, j;
255   
256   hd = m_alloc_clear (sizeof *hd);
257   hd->found = -1;
258   
259   assert (used_resources <= MAX_KEYDB_RESOURCES);
260   for (i=j=0; i < used_resources; i++)
261     {
262       if (!all_resources[i].secret != !secret)
263         continue;
264       switch (all_resources[i].type)
265         {
266         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
267           break;
268         case KEYDB_RESOURCE_TYPE_KEYRING:
269           hd->active[j].type   = all_resources[i].type;
270           hd->active[j].token  = all_resources[i].token;
271           hd->active[j].secret = all_resources[i].secret;
272           hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
273           if (!hd->active[j].u.kr) {
274             m_free (hd);
275             return NULL; /* fixme: release all previously allocated handles*/
276           }
277           j++;
278           break;
279         }
280     }
281   hd->used = j;
282   
283   active_handles++;
284   return hd;
285 }
286
287 void 
288 keydb_release (KEYDB_HANDLE hd)
289 {
290     int i;
291
292     if (!hd)
293         return;
294     assert (active_handles > 0);
295     active_handles--;
296
297     unlock_all (hd);
298     for (i=0; i < hd->used; i++) {
299         switch (hd->active[i].type) {
300           case KEYDB_RESOURCE_TYPE_NONE:
301             break;
302           case KEYDB_RESOURCE_TYPE_KEYRING:
303             keyring_release (hd->active[i].u.kr);
304             break;
305         }
306     }
307
308     m_free (hd);
309 }
310
311
312 /*
313  * Return the name of the current resource.  This is function first
314  * looks for the last found found, then for the current search
315  * position, and last returns the first available resource.  The
316  * returned string is only valid as long as the handle exists.  This
317  * function does only return NULL if no handle is specified, in all
318  * other error cases an empty string is returned.
319  */
320 const char *
321 keydb_get_resource_name (KEYDB_HANDLE hd)
322 {
323     int idx;
324     const char *s = NULL;
325
326     if (!hd) 
327         return NULL;
328
329     if ( hd->found >= 0 && hd->found < hd->used) 
330         idx = hd->found;
331     else if ( hd->current >= 0 && hd->current < hd->used) 
332         idx = hd->current;
333     else
334         idx = 0;
335
336     switch (hd->active[idx].type) {
337       case KEYDB_RESOURCE_TYPE_NONE:
338         s = NULL; 
339         break;
340       case KEYDB_RESOURCE_TYPE_KEYRING:
341         s = keyring_get_resource_name (hd->active[idx].u.kr);
342         break;
343     }
344
345     return s? s: "";
346 }
347
348
349
350 static int 
351 lock_all (KEYDB_HANDLE hd)
352 {
353     int i, rc = 0;
354
355     for (i=0; !rc && i < hd->used; i++) {
356         switch (hd->active[i].type) {
357           case KEYDB_RESOURCE_TYPE_NONE:
358             break;
359           case KEYDB_RESOURCE_TYPE_KEYRING:
360             rc = keyring_lock (hd->active[i].u.kr, 1);
361             break;
362         }
363     }
364
365     if (rc) {
366         /* revert the already set locks */
367         for (i--; i >= 0; i--) {
368             switch (hd->active[i].type) {
369               case KEYDB_RESOURCE_TYPE_NONE:
370                 break;
371               case KEYDB_RESOURCE_TYPE_KEYRING:
372                 keyring_lock (hd->active[i].u.kr, 0);
373                 break;
374             }
375         }
376     }
377     else
378         hd->locked = 1;
379
380     return rc;
381 }
382
383 static void
384 unlock_all (KEYDB_HANDLE hd)
385 {
386     int i;
387
388     if (!hd->locked)
389         return;
390
391     for (i=hd->used-1; i >= 0; i--) {
392         switch (hd->active[i].type) {
393           case KEYDB_RESOURCE_TYPE_NONE:
394             break;
395           case KEYDB_RESOURCE_TYPE_KEYRING:
396             keyring_lock (hd->active[i].u.kr, 0);
397             break;
398         }
399     }
400     hd->locked = 0;
401 }
402
403
404 /*
405  * Return the last found keyring.  Caller must free it.
406  * The returned keyblock has the kbode flag bit 0 set for the node with
407  * the public key used to locate the keyblock or flag bit 1 set for 
408  * the user ID node.
409  */
410 int
411 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
412 {
413     int rc = 0;
414
415     if (!hd)
416         return G10ERR_INV_ARG;
417
418     if ( hd->found < 0 || hd->found >= hd->used) 
419         return -1; /* nothing found */
420
421     switch (hd->active[hd->found].type) {
422       case KEYDB_RESOURCE_TYPE_NONE:
423         rc = G10ERR_GENERAL; /* oops */
424         break;
425       case KEYDB_RESOURCE_TYPE_KEYRING:
426         rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
427         break;
428     }
429
430     return rc;
431 }
432
433 /* 
434  * update the current keyblock with KB
435  */
436 int
437 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
438 {
439     int rc = 0;
440
441     if (!hd)
442         return G10ERR_INV_ARG;
443
444     if ( hd->found < 0 || hd->found >= hd->used) 
445         return -1; /* nothing found */
446
447     if( opt.dry_run )
448         return 0;
449
450     rc = lock_all (hd);
451     if (rc)
452         return rc;
453
454     switch (hd->active[hd->found].type) {
455       case KEYDB_RESOURCE_TYPE_NONE:
456         rc = G10ERR_GENERAL; /* oops */
457         break;
458       case KEYDB_RESOURCE_TYPE_KEYRING:
459         rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
460         break;
461     }
462
463     unlock_all (hd);
464     return rc;
465 }
466
467
468 /* 
469  * Insert a new KB into one of the resources. 
470  */
471 int
472 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
473 {
474     int rc = -1;
475     int idx;
476
477     if (!hd) 
478         return G10ERR_INV_ARG;
479
480     if( opt.dry_run )
481         return 0;
482
483     if ( hd->found >= 0 && hd->found < hd->used) 
484         idx = hd->found;
485     else if ( hd->current >= 0 && hd->current < hd->used) 
486         idx = hd->current;
487     else
488         return G10ERR_GENERAL;
489
490     rc = lock_all (hd);
491     if (rc)
492         return rc;
493
494     switch (hd->active[idx].type) {
495       case KEYDB_RESOURCE_TYPE_NONE:
496         rc = G10ERR_GENERAL; /* oops */
497         break;
498       case KEYDB_RESOURCE_TYPE_KEYRING:
499         rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
500         break;
501     }
502
503     unlock_all (hd);
504     return rc;
505 }
506
507
508 /* 
509  * The current keyblock will be deleted.
510  */
511 int
512 keydb_delete_keyblock (KEYDB_HANDLE hd)
513 {
514     int rc = -1;
515
516     if (!hd)
517         return G10ERR_INV_ARG;
518
519     if ( hd->found < 0 || hd->found >= hd->used) 
520         return -1; /* nothing found */
521
522     if( opt.dry_run )
523         return 0;
524
525     rc = lock_all (hd);
526     if (rc)
527         return rc;
528
529     switch (hd->active[hd->found].type) {
530       case KEYDB_RESOURCE_TYPE_NONE:
531         rc = G10ERR_GENERAL; /* oops */
532         break;
533       case KEYDB_RESOURCE_TYPE_KEYRING:
534         rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
535         break;
536     }
537
538     unlock_all (hd);
539     return rc;
540 }
541
542 \f
543 /*
544  * Locate the default writable key resource, so that the next
545  * operation (which is only relevant for inserts) will be done on this
546  * resource.  
547  */
548 int
549 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
550 {
551   int rc;
552   
553   if (!hd)
554     return G10ERR_INV_ARG;
555   
556   rc = keydb_search_reset (hd); /* this does reset hd->current */
557   if (rc)
558     return rc;
559
560   /* If we have a primary set, try that one first */
561   if(primary_keyring)
562     {
563       for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
564         {
565           if(hd->active[hd->current].token==primary_keyring)
566             {
567               if(keyring_is_writable (hd->active[hd->current].token))
568                 return 0;
569               else
570                 break;
571             }
572         }
573
574       rc = keydb_search_reset (hd); /* this does reset hd->current */
575       if (rc)
576         return rc;
577     }
578
579   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) 
580     {
581       switch (hd->active[hd->current].type) 
582         {
583         case KEYDB_RESOURCE_TYPE_NONE:
584           BUG();
585           break;
586         case KEYDB_RESOURCE_TYPE_KEYRING:
587           if (keyring_is_writable (hd->active[hd->current].token))
588             return 0; /* found (hd->current is set to it) */
589           break;
590         }
591     }
592   
593   return -1;
594 }
595
596 /*
597  * Rebuild the caches of all key resources.
598  */
599 void
600 keydb_rebuild_caches (int noisy)
601 {
602   int i, rc;
603   
604   for (i=0; i < used_resources; i++)
605     {
606       if (all_resources[i].secret)
607         continue;
608       switch (all_resources[i].type)
609         {
610         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
611           break;
612         case KEYDB_RESOURCE_TYPE_KEYRING:
613           rc = keyring_rebuild_cache (all_resources[i].token,noisy);
614           if (rc)
615             log_error (_("failed to rebuild keyring cache: %s\n"),
616                        g10_errstr (rc));
617           break;
618         }
619     }
620 }
621
622
623
624 /* 
625  * Start the next search on this handle right at the beginning
626  */
627 int 
628 keydb_search_reset (KEYDB_HANDLE hd)
629 {
630     int i, rc = 0;
631
632     if (!hd)
633         return G10ERR_INV_ARG;
634
635     hd->current = 0; 
636     hd->found = -1;
637     /* and reset all resources */
638     for (i=0; !rc && i < hd->used; i++) {
639         switch (hd->active[i].type) {
640           case KEYDB_RESOURCE_TYPE_NONE:
641             break;
642           case KEYDB_RESOURCE_TYPE_KEYRING:
643             rc = keyring_search_reset (hd->active[i].u.kr);
644             break;
645         }
646     }
647     return rc; 
648 }
649
650
651 /* 
652  * Search through all keydb resources, starting at the current position,
653  * for a keyblock which contains one of the keys described in the DESC array.
654  */
655 int 
656 keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
657                size_t ndesc, size_t *descindex)
658 {
659     int rc = -1;
660
661     if (!hd)
662         return G10ERR_INV_ARG;
663
664     while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
665         switch (hd->active[hd->current].type) {
666           case KEYDB_RESOURCE_TYPE_NONE:
667             BUG(); /* we should never see it here */
668             break;
669           case KEYDB_RESOURCE_TYPE_KEYRING:
670             rc = keyring_search (hd->active[hd->current].u.kr, desc,
671                                  ndesc, descindex);
672             break;
673         }
674         if (rc == -1) /* EOF -> switch to next resource */
675             hd->current++; 
676         else if (!rc)
677             hd->found = hd->current;
678     }
679
680     return rc; 
681 }
682
683 int
684 keydb_search_first (KEYDB_HANDLE hd)
685 {
686     KEYDB_SEARCH_DESC desc;
687
688     memset (&desc, 0, sizeof desc);
689     desc.mode = KEYDB_SEARCH_MODE_FIRST;
690     return keydb_search (hd, &desc, 1);
691 }
692
693 int
694 keydb_search_next (KEYDB_HANDLE hd)
695 {
696     KEYDB_SEARCH_DESC desc;
697
698     memset (&desc, 0, sizeof desc);
699     desc.mode = KEYDB_SEARCH_MODE_NEXT;
700     return keydb_search (hd, &desc, 1);
701 }
702
703 int
704 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
705 {
706     KEYDB_SEARCH_DESC desc;
707
708     memset (&desc, 0, sizeof desc);
709     desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
710     desc.u.kid[0] = kid[0];
711     desc.u.kid[1] = kid[1];
712     return keydb_search (hd, &desc, 1);
713 }
714
715 int
716 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
717 {
718     KEYDB_SEARCH_DESC desc;
719
720     memset (&desc, 0, sizeof desc);
721     desc.mode = KEYDB_SEARCH_MODE_FPR;
722     memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
723     return keydb_search (hd, &desc, 1);
724 }