9d1a6ef0159141522097f1d449abc4feaf3917e5
[gnupg.git] / sm / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001, 2003, 2004 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "gpgsm.h"
31 #include "../kbx/keybox.h"
32 #include "keydb.h"
33 #include "i18n.h"
34
35 static int active_handles;
36
37 typedef enum {
38     KEYDB_RESOURCE_TYPE_NONE = 0,
39     KEYDB_RESOURCE_TYPE_KEYBOX
40 } KeydbResourceType;
41 #define MAX_KEYDB_RESOURCES 20
42
43 struct resource_item {
44   KeydbResourceType type;
45   union {
46     KEYBOX_HANDLE kr;
47   } u;
48   void *token;
49   int secret;
50   dotlock_t lockhandle;
51 };
52
53 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
54 static int used_resources;
55
56 struct keydb_handle {
57   int locked;
58   int found;
59   int current;
60   int is_ephemeral;
61   int used; /* items in active */
62   struct resource_item active[MAX_KEYDB_RESOURCES];
63 };
64
65
66 static int lock_all (KEYDB_HANDLE hd);
67 static void unlock_all (KEYDB_HANDLE hd);
68
69
70 /*
71  * Register a resource (which currently may only be a keybox file).
72  * The first keybox which is added by this function is created if it
73  * does not exist.  If AUTO_CREATED is not NULL it will be set to true
74  * if the function has created a a new keybox.
75  */
76 int
77 keydb_add_resource (const char *url, int force, int secret, int *auto_created)
78 {
79   static int any_secret, any_public;
80   const char *resname = url;
81   char *filename = NULL;
82   int rc = 0;
83   FILE *fp;
84   KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
85
86   if (auto_created)
87     *auto_created = 0;
88
89   /* Do we have an URL?
90      gnupg-kbx:filename := this is a plain keybox
91      filename := See what is is, but create as plain keybox.
92   */
93   if (strlen (resname) > 10)
94     {
95       if (!strncmp (resname, "gnupg-kbx:", 10) )
96         {
97           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
98           resname += 10;
99         }
100 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
101       else if (strchr (resname, ':'))
102         {
103           log_error ("invalid key resource URL `%s'\n", url );
104           rc = gpg_error (GPG_ERR_GENERAL);
105           goto leave;
106         }
107 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
108     }
109
110   if (*resname != DIRSEP_C )
111     { /* do tilde expansion etc */
112       if (strchr(resname, DIRSEP_C) )
113         filename = make_filename (resname, NULL);
114       else
115         filename = make_filename (opt.homedir, resname, NULL);
116     }
117   else
118     filename = xstrdup (resname);
119
120   if (!force)
121     force = secret? !any_secret : !any_public;
122
123   /* see whether we can determine the filetype */
124   if (rt == KEYDB_RESOURCE_TYPE_NONE)
125     {
126       FILE *fp2 = fopen( filename, "rb" );
127
128       if (fp2) {
129         u32 magic;
130
131         /* FIXME: check for the keybox magic */
132         if (fread( &magic, 4, 1, fp2) == 1 )
133           {
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 (fp2);
142       }
143       else /* no file yet: create ring */
144         rt = KEYDB_RESOURCE_TYPE_KEYBOX;
145     }
146
147   switch (rt)
148     {
149     case KEYDB_RESOURCE_TYPE_NONE:
150       log_error ("unknown type of key resource `%s'\n", url );
151       rc = gpg_error (GPG_ERR_GENERAL);
152       goto leave;
153
154     case KEYDB_RESOURCE_TYPE_KEYBOX:
155       fp = fopen (filename, "rb");
156       if (!fp && !force)
157         {
158           rc = gpg_error (gpg_err_code_from_errno (errno));
159           goto leave;
160         }
161
162       if (!fp)
163         { /* no file */
164 #if 0 /* no autocreate of the homedirectory yet */
165           {
166             char *last_slash_in_filename;
167
168             last_slash_in_filename = strrchr (filename, DIRSEP_C);
169             *last_slash_in_filename = 0;
170             if (access (filename, F_OK))
171               { /* on the first time we try to create the default
172                    homedir and in this case the process will be
173                    terminated, so that on the next invocation can
174                    read the options file in on startup */
175                 try_make_homedir (filename);
176                 rc = gpg_error (GPG_ERR_FILE_OPEN_ERROR);
177                 *last_slash_in_filename = DIRSEP_C;
178                 goto leave;
179               }
180             *last_slash_in_filename = DIRSEP_C;
181           }
182 #endif
183           fp = fopen (filename, "w");
184           if (!fp)
185             {
186               rc = gpg_error (gpg_err_code_from_errno (errno));
187               log_error (_("error creating keybox `%s': %s\n"),
188                          filename, strerror(errno));
189               if (errno == ENOENT)
190                 log_info (_("you may want to start the gpg-agent first\n"));
191               goto leave;
192             }
193
194           if (!opt.quiet)
195             log_info (_("keybox `%s' created\n"), filename);
196           if (auto_created)
197             *auto_created = 1;
198         }
199         fclose (fp);
200         fp = NULL;
201         /* now register the file */
202         {
203
204           void *token = keybox_register_file (filename, secret);
205           if (!token)
206             ; /* already registered - ignore it */
207           else if (used_resources >= MAX_KEYDB_RESOURCES)
208             rc = gpg_error (GPG_ERR_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
216               all_resources[used_resources].lockhandle
217                 = dotlock_create (filename);
218               if (!all_resources[used_resources].lockhandle)
219                 log_fatal ( _("can't create lock for `%s'\n"), filename);
220
221               /* Do a compress run if needed and the file is not locked. */
222               if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
223                 {
224                   KEYBOX_HANDLE kbxhd = keybox_new (token, secret);
225
226                   if (kbxhd)
227                     {
228                       keybox_compress (kbxhd);
229                       keybox_release (kbxhd);
230                     }
231                   dotlock_release (all_resources[used_resources].lockhandle);
232                 }
233
234               used_resources++;
235             }
236         }
237
238
239         break;
240     default:
241       log_error ("resource type of `%s' not supported\n", url);
242       rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
243       goto leave;
244     }
245
246   /* fixme: check directory permissions and print a warning */
247
248  leave:
249   if (rc)
250     log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror(rc));
251   else if (secret)
252     any_secret = 1;
253   else
254     any_public = 1;
255   xfree (filename);
256   return rc;
257 }
258
259
260 KEYDB_HANDLE
261 keydb_new (int secret)
262 {
263   KEYDB_HANDLE hd;
264   int i, j;
265
266   hd = xcalloc (1, sizeof *hd);
267   hd->found = -1;
268
269   assert (used_resources <= MAX_KEYDB_RESOURCES);
270   for (i=j=0; i < used_resources; i++)
271     {
272       if (!all_resources[i].secret != !secret)
273         continue;
274       switch (all_resources[i].type)
275         {
276         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
277           break;
278         case KEYDB_RESOURCE_TYPE_KEYBOX:
279           hd->active[j].type   = all_resources[i].type;
280           hd->active[j].token  = all_resources[i].token;
281           hd->active[j].secret = all_resources[i].secret;
282           hd->active[j].lockhandle = all_resources[i].lockhandle;
283           hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
284           if (!hd->active[j].u.kr)
285             {
286               xfree (hd);
287               return NULL; /* fixme: release all previously allocated handles*/
288             }
289           j++;
290           break;
291         }
292     }
293   hd->used = j;
294
295   active_handles++;
296   return hd;
297 }
298
299 void
300 keydb_release (KEYDB_HANDLE hd)
301 {
302   int i;
303
304   if (!hd)
305     return;
306   assert (active_handles > 0);
307   active_handles--;
308
309   unlock_all (hd);
310   for (i=0; i < hd->used; i++)
311     {
312       switch (hd->active[i].type)
313         {
314         case KEYDB_RESOURCE_TYPE_NONE:
315           break;
316         case KEYDB_RESOURCE_TYPE_KEYBOX:
317           keybox_release (hd->active[i].u.kr);
318           break;
319         }
320     }
321
322     xfree (hd);
323 }
324
325
326 /* Return the name of the current resource.  This is function first
327    looks for the last found found, then for the current search
328    position, and last returns the first available resource.  The
329    returned string is only valid as long as the handle exists.  This
330    function does only return NULL if no handle is specified, in all
331    other error cases an empty string is returned.  */
332 const char *
333 keydb_get_resource_name (KEYDB_HANDLE hd)
334 {
335   int idx;
336   const char *s = NULL;
337
338   if (!hd)
339     return NULL;
340
341   if ( hd->found >= 0 && hd->found < hd->used)
342     idx = hd->found;
343   else if ( hd->current >= 0 && hd->current < hd->used)
344     idx = hd->current;
345   else
346     idx = 0;
347
348   switch (hd->active[idx].type)
349     {
350     case KEYDB_RESOURCE_TYPE_NONE:
351       s = NULL;
352       break;
353     case KEYDB_RESOURCE_TYPE_KEYBOX:
354       s = keybox_get_resource_name (hd->active[idx].u.kr);
355       break;
356     }
357
358   return s? s: "";
359 }
360
361 /* Switch the handle into ephemeral mode and return the orginal value. */
362 int
363 keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
364 {
365   int i;
366
367   if (!hd)
368     return 0;
369
370   yes = !!yes;
371   if (hd->is_ephemeral != yes)
372     {
373       for (i=0; i < hd->used; i++)
374         {
375           switch (hd->active[i].type)
376             {
377             case KEYDB_RESOURCE_TYPE_NONE:
378               break;
379             case KEYDB_RESOURCE_TYPE_KEYBOX:
380               keybox_set_ephemeral (hd->active[i].u.kr, yes);
381               break;
382             }
383         }
384     }
385
386   i = hd->is_ephemeral;
387   hd->is_ephemeral = yes;
388   return i;
389 }
390
391
392 /* If the keyring has not yet been locked, lock it now.  This
393    operation is required before any update operation; it is optional
394    for an insert operation.  The lock is released with
395    keydb_released. */
396 gpg_error_t
397 keydb_lock (KEYDB_HANDLE hd)
398 {
399   if (!hd)
400     return gpg_error (GPG_ERR_INV_HANDLE);
401   if (hd->locked)
402     return 0; /* Already locked. */
403   return lock_all (hd);
404 }
405
406
407 \f
408 static int
409 lock_all (KEYDB_HANDLE hd)
410 {
411   int i, rc = 0;
412
413   /* Fixme: This locking scheme may lead to deadlock if the resources
414      are not added in the same order by all processes.  We are
415      currently only allowing one resource so it is not a problem. */
416   for (i=0; i < hd->used; i++)
417     {
418       switch (hd->active[i].type)
419         {
420         case KEYDB_RESOURCE_TYPE_NONE:
421           break;
422         case KEYDB_RESOURCE_TYPE_KEYBOX:
423           if (hd->active[i].lockhandle)
424             rc = dotlock_take (hd->active[i].lockhandle, -1);
425           break;
426         }
427       if (rc)
428         break;
429     }
430
431     if (rc)
432       {
433         /* revert the already set locks */
434         for (i--; i >= 0; i--)
435           {
436             switch (hd->active[i].type)
437               {
438               case KEYDB_RESOURCE_TYPE_NONE:
439                 break;
440               case KEYDB_RESOURCE_TYPE_KEYBOX:
441                 if (hd->active[i].lockhandle)
442                   dotlock_release (hd->active[i].lockhandle);
443                 break;
444               }
445           }
446       }
447     else
448       hd->locked = 1;
449
450     /* make_dotlock () does not yet guarantee that errno is set, thus
451        we can't rely on the error reason and will simply use
452        EACCES. */
453     return rc? gpg_error (GPG_ERR_EACCES) : 0;
454 }
455
456 static void
457 unlock_all (KEYDB_HANDLE hd)
458 {
459   int i;
460
461   if (!hd->locked)
462     return;
463
464   for (i=hd->used-1; i >= 0; i--)
465     {
466       switch (hd->active[i].type)
467         {
468         case KEYDB_RESOURCE_TYPE_NONE:
469           break;
470         case KEYDB_RESOURCE_TYPE_KEYBOX:
471           if (hd->active[i].lockhandle)
472             dotlock_release (hd->active[i].lockhandle);
473           break;
474         }
475     }
476   hd->locked = 0;
477 }
478
479 \f
480 #if 0
481 /*
482  * Return the last found keybox.  Caller must free it.
483  * The returned keyblock has the kbode flag bit 0 set for the node with
484  * the public key used to locate the keyblock or flag bit 1 set for
485  * the user ID node.
486  */
487 int
488 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
489 {
490     int rc = 0;
491
492     if (!hd)
493         return G10ERR_INV_ARG;
494
495     if ( hd->found < 0 || hd->found >= hd->used)
496         return -1; /* nothing found */
497
498     switch (hd->active[hd->found].type) {
499       case KEYDB_RESOURCE_TYPE_NONE:
500         rc = G10ERR_GENERAL; /* oops */
501         break;
502       case KEYDB_RESOURCE_TYPE_KEYBOX:
503         rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
504         break;
505     }
506
507     return rc;
508 }
509
510 /*
511  * update the current keyblock with KB
512  */
513 int
514 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
515 {
516     int rc = 0;
517
518     if (!hd)
519         return G10ERR_INV_ARG;
520
521     if ( hd->found < 0 || hd->found >= hd->used)
522         return -1; /* nothing found */
523
524     if( opt.dry_run )
525         return 0;
526
527     if (!hd->locked)
528       return gpg_error (GPG_ERR_NOT_LOCKED);
529
530     switch (hd->active[hd->found].type) {
531       case KEYDB_RESOURCE_TYPE_NONE:
532         rc = G10ERR_GENERAL; /* oops */
533         break;
534       case KEYDB_RESOURCE_TYPE_KEYBOX:
535         rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
536         break;
537     }
538
539     unlock_all (hd);
540     return rc;
541 }
542
543
544 /*
545  * Insert a new KB into one of the resources.
546  */
547 int
548 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
549 {
550     int rc = -1;
551     int idx;
552
553     if (!hd)
554         return G10ERR_INV_ARG;
555
556     if( opt.dry_run )
557         return 0;
558
559     if ( hd->found >= 0 && hd->found < hd->used)
560         idx = hd->found;
561     else if ( hd->current >= 0 && hd->current < hd->used)
562         idx = hd->current;
563     else
564         return G10ERR_GENERAL;
565
566     rc = lock_all (hd);
567     if (rc)
568         return rc;
569
570     switch (hd->active[idx].type) {
571       case KEYDB_RESOURCE_TYPE_NONE:
572         rc = G10ERR_GENERAL; /* oops */
573         break;
574       case KEYDB_RESOURCE_TYPE_KEYBOX:
575         rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
576         break;
577     }
578
579     unlock_all (hd);
580     return rc;
581 }
582
583 #endif /*disabled code*/
584
585
586 \f
587 /*
588   Return the last found object.  Caller must free it.  The returned
589   keyblock has the kbode flag bit 0 set for the node with the public
590   key used to locate the keyblock or flag bit 1 set for the user ID
591   node.  */
592 int
593 keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
594 {
595   int rc = 0;
596
597   if (!hd)
598     return gpg_error (GPG_ERR_INV_VALUE);
599
600   if ( hd->found < 0 || hd->found >= hd->used)
601     return -1; /* nothing found */
602
603   switch (hd->active[hd->found].type)
604     {
605     case KEYDB_RESOURCE_TYPE_NONE:
606       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
607       break;
608     case KEYDB_RESOURCE_TYPE_KEYBOX:
609       rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
610       break;
611     }
612
613   return rc;
614 }
615
616 /* Return a flag of the last found object. WHICH is the flag requested;
617    it should be one of the KEYBOX_FLAG_ values.  If the operation is
618    successful, the flag value will be stored at the address given by
619    VALUE.  Return 0 on success or an error code. */
620 gpg_error_t
621 keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
622 {
623   int err = 0;
624
625   if (!hd)
626     return gpg_error (GPG_ERR_INV_VALUE);
627
628   if ( hd->found < 0 || hd->found >= hd->used)
629     return gpg_error (GPG_ERR_NOTHING_FOUND);
630
631   switch (hd->active[hd->found].type)
632     {
633     case KEYDB_RESOURCE_TYPE_NONE:
634       err = gpg_error (GPG_ERR_GENERAL); /* oops */
635       break;
636     case KEYDB_RESOURCE_TYPE_KEYBOX:
637       err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value);
638       break;
639     }
640
641   return err;
642 }
643
644 /* Set a flag of the last found object. WHICH is the flag to be set; it
645    should be one of the KEYBOX_FLAG_ values.  If the operation is
646    successful, the flag value will be stored in the keybox.  Note,
647    that some flag values can't be updated and thus may return an
648    error, some other flag values may be masked out before an update.
649    Returns 0 on success or an error code. */
650 gpg_error_t
651 keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
652 {
653   int err = 0;
654
655   if (!hd)
656     return gpg_error (GPG_ERR_INV_VALUE);
657
658   if ( hd->found < 0 || hd->found >= hd->used)
659     return gpg_error (GPG_ERR_NOTHING_FOUND);
660
661   if (!hd->locked)
662     return gpg_error (GPG_ERR_NOT_LOCKED);
663
664   switch (hd->active[hd->found].type)
665     {
666     case KEYDB_RESOURCE_TYPE_NONE:
667       err = gpg_error (GPG_ERR_GENERAL); /* oops */
668       break;
669     case KEYDB_RESOURCE_TYPE_KEYBOX:
670       err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value);
671       break;
672     }
673
674   return err;
675 }
676
677 /*
678  * Insert a new Certificate into one of the resources.
679  */
680 int
681 keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
682 {
683   int rc = -1;
684   int idx;
685   unsigned char digest[20];
686
687   if (!hd)
688     return gpg_error (GPG_ERR_INV_VALUE);
689
690   if (opt.dry_run)
691     return 0;
692
693   if ( hd->found >= 0 && hd->found < hd->used)
694     idx = hd->found;
695   else if ( hd->current >= 0 && hd->current < hd->used)
696     idx = hd->current;
697   else
698     return gpg_error (GPG_ERR_GENERAL);
699
700   if (!hd->locked)
701     return gpg_error (GPG_ERR_NOT_LOCKED);
702
703   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
704
705   switch (hd->active[idx].type)
706     {
707     case KEYDB_RESOURCE_TYPE_NONE:
708       rc = gpg_error (GPG_ERR_GENERAL);
709       break;
710     case KEYDB_RESOURCE_TYPE_KEYBOX:
711       rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
712       break;
713     }
714
715   unlock_all (hd);
716   return rc;
717 }
718
719
720
721 /* Update the current keyblock with KB.  */
722 int
723 keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
724 {
725   int rc = 0;
726   unsigned char digest[20];
727
728   if (!hd)
729     return gpg_error (GPG_ERR_INV_VALUE);
730
731   if ( hd->found < 0 || hd->found >= hd->used)
732     return -1; /* nothing found */
733
734   if (opt.dry_run)
735     return 0;
736
737   rc = lock_all (hd);
738   if (rc)
739     return rc;
740
741   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
742
743   switch (hd->active[hd->found].type)
744     {
745     case KEYDB_RESOURCE_TYPE_NONE:
746       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
747       break;
748     case KEYDB_RESOURCE_TYPE_KEYBOX:
749       rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
750       break;
751     }
752
753   unlock_all (hd);
754   return rc;
755 }
756
757
758 /*
759  * The current keyblock or cert will be deleted.
760  */
761 int
762 keydb_delete (KEYDB_HANDLE hd, int unlock)
763 {
764   int rc = -1;
765
766   if (!hd)
767     return gpg_error (GPG_ERR_INV_VALUE);
768
769   if ( hd->found < 0 || hd->found >= hd->used)
770     return -1; /* nothing found */
771
772   if( opt.dry_run )
773     return 0;
774
775   if (!hd->locked)
776     return gpg_error (GPG_ERR_NOT_LOCKED);
777
778   switch (hd->active[hd->found].type)
779     {
780     case KEYDB_RESOURCE_TYPE_NONE:
781       rc = gpg_error (GPG_ERR_GENERAL);
782       break;
783     case KEYDB_RESOURCE_TYPE_KEYBOX:
784       rc = keybox_delete (hd->active[hd->found].u.kr);
785       break;
786     }
787
788   if (unlock)
789     unlock_all (hd);
790   return rc;
791 }
792
793
794 \f
795 /*
796  * Locate the default writable key resource, so that the next
797  * operation (which is only relevant for inserts) will be done on this
798  * resource.
799  */
800 int
801 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
802 {
803   int rc;
804
805   (void)reserved;
806
807   if (!hd)
808     return gpg_error (GPG_ERR_INV_VALUE);
809
810   rc = keydb_search_reset (hd); /* this does reset hd->current */
811   if (rc)
812     return rc;
813
814   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
815     {
816       switch (hd->active[hd->current].type)
817         {
818         case KEYDB_RESOURCE_TYPE_NONE:
819           BUG();
820           break;
821         case KEYDB_RESOURCE_TYPE_KEYBOX:
822           if (keybox_is_writable (hd->active[hd->current].token))
823             return 0; /* found (hd->current is set to it) */
824           break;
825         }
826     }
827
828   return -1;
829 }
830
831 /*
832  * Rebuild the caches of all key resources.
833  */
834 void
835 keydb_rebuild_caches (void)
836 {
837   int i;
838
839   for (i=0; i < used_resources; i++)
840     {
841       if (all_resources[i].secret)
842         continue;
843       switch (all_resources[i].type)
844         {
845         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
846           break;
847         case KEYDB_RESOURCE_TYPE_KEYBOX:
848 /*            rc = keybox_rebuild_cache (all_resources[i].token); */
849 /*            if (rc) */
850 /*              log_error (_("failed to rebuild keybox cache: %s\n"), */
851 /*                         g10_errstr (rc)); */
852           break;
853         }
854     }
855 }
856
857
858
859 /*
860  * Start the next search on this handle right at the beginning
861  */
862 int
863 keydb_search_reset (KEYDB_HANDLE hd)
864 {
865   int i, rc = 0;
866
867   if (!hd)
868     return gpg_error (GPG_ERR_INV_VALUE);
869
870   hd->current = 0;
871   hd->found = -1;
872   /* and reset all resources */
873   for (i=0; !rc && i < hd->used; i++)
874     {
875       switch (hd->active[i].type)
876         {
877         case KEYDB_RESOURCE_TYPE_NONE:
878           break;
879         case KEYDB_RESOURCE_TYPE_KEYBOX:
880           rc = keybox_search_reset (hd->active[i].u.kr);
881           break;
882         }
883     }
884   return rc; /* fixme: we need to map error codes or share them with
885                 all modules*/
886 }
887
888 /*
889  * Search through all keydb resources, starting at the current position,
890  * for a keyblock which contains one of the keys described in the DESC array.
891  */
892 int
893 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
894 {
895   int rc = -1;
896
897   if (!hd)
898     return gpg_error (GPG_ERR_INV_VALUE);
899
900   while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
901     {
902       switch (hd->active[hd->current].type)
903         {
904         case KEYDB_RESOURCE_TYPE_NONE:
905           BUG(); /* we should never see it here */
906           break;
907         case KEYDB_RESOURCE_TYPE_KEYBOX:
908           rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
909           break;
910         }
911       if (rc == -1) /* EOF -> switch to next resource */
912         hd->current++;
913       else if (!rc)
914         hd->found = hd->current;
915     }
916
917   return rc;
918 }
919
920
921 int
922 keydb_search_first (KEYDB_HANDLE hd)
923 {
924   KEYDB_SEARCH_DESC desc;
925
926   memset (&desc, 0, sizeof desc);
927   desc.mode = KEYDB_SEARCH_MODE_FIRST;
928   return keydb_search (hd, &desc, 1);
929 }
930
931 int
932 keydb_search_next (KEYDB_HANDLE hd)
933 {
934   KEYDB_SEARCH_DESC desc;
935
936   memset (&desc, 0, sizeof desc);
937   desc.mode = KEYDB_SEARCH_MODE_NEXT;
938   return keydb_search (hd, &desc, 1);
939 }
940
941 int
942 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
943 {
944   KEYDB_SEARCH_DESC desc;
945
946   (void)kid;
947
948   memset (&desc, 0, sizeof desc);
949   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
950   desc.u.kid[0] = kid[0];
951   desc.u.kid[1] = kid[1];
952   return keydb_search (hd, &desc, 1);
953 }
954
955 int
956 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
957 {
958   KEYDB_SEARCH_DESC desc;
959
960   memset (&desc, 0, sizeof desc);
961   desc.mode = KEYDB_SEARCH_MODE_FPR;
962   memcpy (desc.u.fpr, fpr, 20);
963   return keydb_search (hd, &desc, 1);
964 }
965
966 int
967 keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
968 {
969   KEYDB_SEARCH_DESC desc;
970   int rc;
971
972   memset (&desc, 0, sizeof desc);
973   desc.mode = KEYDB_SEARCH_MODE_ISSUER;
974   desc.u.name = issuer;
975   rc = keydb_search (hd, &desc, 1);
976   return rc;
977 }
978
979 int
980 keydb_search_issuer_sn (KEYDB_HANDLE hd,
981                         const char *issuer, ksba_const_sexp_t serial)
982 {
983   KEYDB_SEARCH_DESC desc;
984   int rc;
985   const unsigned char *s;
986
987   memset (&desc, 0, sizeof desc);
988   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
989   s = serial;
990   if (*s !='(')
991     return gpg_error (GPG_ERR_INV_VALUE);
992   s++;
993   for (desc.snlen = 0; digitp (s); s++)
994     desc.snlen = 10*desc.snlen + atoi_1 (s);
995   if (*s !=':')
996     return gpg_error (GPG_ERR_INV_VALUE);
997   desc.sn = s+1;
998   desc.u.name = issuer;
999   rc = keydb_search (hd, &desc, 1);
1000   return rc;
1001 }
1002
1003 int
1004 keydb_search_subject (KEYDB_HANDLE hd, const char *name)
1005 {
1006   KEYDB_SEARCH_DESC desc;
1007   int rc;
1008
1009   memset (&desc, 0, sizeof desc);
1010   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
1011   desc.u.name = name;
1012   rc = keydb_search (hd, &desc, 1);
1013   return rc;
1014 }
1015
1016
1017 \f
1018 /* Store the certificate in the key DB but make sure that it does not
1019    already exists.  We do this simply by comparing the fingerprint.
1020    If EXISTED is not NULL it will be set to true if the certificate
1021    was already in the DB. */
1022 int
1023 keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed)
1024 {
1025   KEYDB_HANDLE kh;
1026   int rc;
1027   unsigned char fpr[20];
1028
1029   if (existed)
1030     *existed = 0;
1031
1032   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1033     {
1034       log_error (_("failed to get the fingerprint\n"));
1035       return gpg_error (GPG_ERR_GENERAL);
1036     }
1037
1038   kh = keydb_new (0);
1039   if (!kh)
1040     {
1041       log_error (_("failed to allocate keyDB handle\n"));
1042       return gpg_error (GPG_ERR_ENOMEM);;
1043     }
1044
1045   if (ephemeral)
1046     keydb_set_ephemeral (kh, 1);
1047
1048   rc = lock_all (kh);
1049   if (rc)
1050     return rc;
1051
1052   rc = keydb_search_fpr (kh, fpr);
1053   if (rc != -1)
1054     {
1055       keydb_release (kh);
1056       if (!rc)
1057         {
1058           if (existed)
1059             *existed = 1;
1060           return 0; /* okay */
1061         }
1062       log_error (_("problem looking for existing certificate: %s\n"),
1063                  gpg_strerror (rc));
1064       return rc;
1065     }
1066
1067   rc = keydb_locate_writable (kh, 0);
1068   if (rc)
1069     {
1070       log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
1071       keydb_release (kh);
1072       return rc;
1073     }
1074
1075   rc = keydb_insert_cert (kh, cert);
1076   if (rc)
1077     {
1078       log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
1079       keydb_release (kh);
1080       return rc;
1081     }
1082   keydb_release (kh);
1083   return 0;
1084 }
1085
1086
1087 /* This is basically keydb_set_flags but it implements a complete
1088    transaction by locating the certificate in the DB and updating the
1089    flags. */
1090 gpg_error_t
1091 keydb_set_cert_flags (ksba_cert_t cert, int ephemeral,
1092                       int which, int idx,
1093                       unsigned int mask, unsigned int value)
1094 {
1095   KEYDB_HANDLE kh;
1096   gpg_error_t err;
1097   unsigned char fpr[20];
1098   unsigned int old_value;
1099
1100   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1101     {
1102       log_error (_("failed to get the fingerprint\n"));
1103       return gpg_error (GPG_ERR_GENERAL);
1104     }
1105
1106   kh = keydb_new (0);
1107   if (!kh)
1108     {
1109       log_error (_("failed to allocate keyDB handle\n"));
1110       return gpg_error (GPG_ERR_ENOMEM);;
1111     }
1112
1113   if (ephemeral)
1114     keydb_set_ephemeral (kh, 1);
1115
1116   err = keydb_lock (kh);
1117   if (err)
1118     {
1119       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1120       keydb_release (kh);
1121       return err;
1122     }
1123
1124   err = keydb_search_fpr (kh, fpr);
1125   if (err)
1126     {
1127       if (err == -1)
1128         err = gpg_error (GPG_ERR_NOT_FOUND);
1129       else
1130         log_error (_("problem re-searching certificate: %s\n"),
1131                    gpg_strerror (err));
1132       keydb_release (kh);
1133       return err;
1134     }
1135
1136   err = keydb_get_flags (kh, which, idx, &old_value);
1137   if (err)
1138     {
1139       log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
1140       keydb_release (kh);
1141       return err;
1142     }
1143
1144   value = ((old_value & ~mask) | (value & mask));
1145
1146   if (value != old_value)
1147     {
1148       err = keydb_set_flags (kh, which, idx, value);
1149       if (err)
1150         {
1151           log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1152           keydb_release (kh);
1153           return err;
1154         }
1155     }
1156
1157   keydb_release (kh);
1158   return 0;
1159 }
1160
1161
1162 /* Reset all the certificate flags we have stored with the certificates
1163    for performance reasons. */
1164 void
1165 keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
1166 {
1167   gpg_error_t err;
1168   KEYDB_HANDLE hd = NULL;
1169   KEYDB_SEARCH_DESC *desc = NULL;
1170   int ndesc;
1171   strlist_t sl;
1172   int rc=0;
1173   unsigned int old_value, value;
1174
1175   (void)ctrl;
1176
1177   hd = keydb_new (0);
1178   if (!hd)
1179     {
1180       log_error ("keydb_new failed\n");
1181       goto leave;
1182     }
1183
1184   if (!names)
1185     ndesc = 1;
1186   else
1187     {
1188       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
1189         ;
1190     }
1191
1192   desc = xtrycalloc (ndesc, sizeof *desc);
1193   if (!ndesc)
1194     {
1195       log_error ("allocating memory failed: %s\n",
1196                  gpg_strerror (out_of_core ()));
1197       goto leave;
1198     }
1199
1200   if (!names)
1201     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1202   else
1203     {
1204       for (ndesc=0, sl=names; sl; sl = sl->next)
1205         {
1206           rc = classify_user_id (sl->d, desc+ndesc, 0);
1207           if (rc)
1208             {
1209               log_error ("key `%s' not found: %s\n",
1210                          sl->d, gpg_strerror (rc));
1211               rc = 0;
1212             }
1213           else
1214             ndesc++;
1215         }
1216     }
1217
1218   err = keydb_lock (hd);
1219   if (err)
1220     {
1221       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1222       goto leave;
1223     }
1224
1225   while (!(rc = keydb_search (hd, desc, ndesc)))
1226     {
1227       if (!names)
1228         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1229
1230       err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
1231       if (err)
1232         {
1233           log_error (_("error getting stored flags: %s\n"),
1234                      gpg_strerror (err));
1235           goto leave;
1236         }
1237
1238       value = (old_value & ~VALIDITY_REVOKED);
1239       if (value != old_value)
1240         {
1241           err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
1242           if (err)
1243             {
1244               log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1245               goto leave;
1246             }
1247         }
1248     }
1249   if (rc && rc != -1)
1250     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1251
1252  leave:
1253   xfree (desc);
1254   keydb_release (hd);
1255 }