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