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