gpg: First patches to support a keybox storage backend.
[gnupg.git] / g10 / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2008, 2009, 2011 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
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 "gpg.h"
32 #include "util.h"
33 #include "options.h"
34 #include "main.h" /*try_make_homedir ()*/
35 #include "packet.h"
36 #include "keyring.h"
37 #include "../kbx/keybox.h"
38 #include "keydb.h"
39 #include "i18n.h"
40
41 static int active_handles;
42
43 typedef enum
44   {
45     KEYDB_RESOURCE_TYPE_NONE = 0,
46     KEYDB_RESOURCE_TYPE_KEYRING,
47     KEYDB_RESOURCE_TYPE_KEYBOX
48   } KeydbResourceType;
49 #define MAX_KEYDB_RESOURCES 40
50
51 struct resource_item
52 {
53   KeydbResourceType type;
54   union {
55     KEYRING_HANDLE kr;
56     KEYBOX_HANDLE kb;
57   } u;
58   void *token;
59 };
60
61 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
62 static int used_resources;
63 static void *primary_keyring=NULL;
64
65 struct keydb_handle
66 {
67   int locked;
68   int found;
69   int current;
70   int used;   /* Number of items in ACTIVE. */
71   struct resource_item active[MAX_KEYDB_RESOURCES];
72 };
73
74
75 static int lock_all (KEYDB_HANDLE hd);
76 static void unlock_all (KEYDB_HANDLE hd);
77
78
79 /* Handle the creation of a keyring or a keybox if it does not yet
80    exist.  Take into acount that other processes might have the
81    keyring/keybox already locked.  This lock check does not work if
82    the directory itself is not yet available. */
83 static int
84 maybe_create_keyring_or_box (char *filename, int is_box, int force)
85 {
86   dotlock_t lockhd = NULL;
87   IOBUF iobuf;
88   int rc;
89   mode_t oldmask;
90   char *last_slash_in_filename;
91   int save_slash;
92
93   /* A quick test whether the filename already exists. */
94   if (!access (filename, F_OK))
95     return 0;
96
97   /* If we don't want to create a new file at all, there is no need to
98      go any further - bail out right here.  */
99   if (!force)
100     return gpg_error (GPG_ERR_ENOENT);
101
102   /* First of all we try to create the home directory.  Note, that we
103      don't do any locking here because any sane application of gpg
104      would create the home directory by itself and not rely on gpg's
105      tricky auto-creation which is anyway only done for some home
106      directory name patterns. */
107   last_slash_in_filename = strrchr (filename, DIRSEP_C);
108 #if HAVE_W32_SYSTEM
109   {
110     /* Windows may either have a slash or a backslash.  Take care of it.  */
111     char *p = strrchr (filename, '/');
112     if (!last_slash_in_filename || p > last_slash_in_filename)
113       last_slash_in_filename = p;
114   }
115 #endif /*HAVE_W32_SYSTEM*/
116   if (!last_slash_in_filename)
117     return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
118                                            not happen though.  */
119   save_slash = *last_slash_in_filename;
120   *last_slash_in_filename = 0;
121   if (access(filename, F_OK))
122     {
123       static int tried;
124
125       if (!tried)
126         {
127           tried = 1;
128           try_make_homedir (filename);
129         }
130       if (access (filename, F_OK))
131         {
132           rc = gpg_error_from_syserror ();
133           *last_slash_in_filename = save_slash;
134           goto leave;
135         }
136     }
137   *last_slash_in_filename = save_slash;
138
139   /* To avoid races with other instances of gpg trying to create or
140      update the keyring (it is removed during an update for a short
141      time), we do the next stuff in a locked state. */
142   lockhd = dotlock_create (filename, 0);
143   if (!lockhd)
144     {
145       rc = gpg_error_from_syserror ();
146       /* A reason for this to fail is that the directory is not
147          writable. However, this whole locking stuff does not make
148          sense if this is the case. An empty non-writable directory
149          with no keyring is not really useful at all. */
150       if (opt.verbose)
151         log_info ("can't allocate lock for '%s': %s\n",
152                   filename, gpg_strerror (rc));
153
154       if (!force)
155         return gpg_error (GPG_ERR_ENOENT);
156       else
157         return rc;
158     }
159
160   if ( dotlock_take (lockhd, -1) )
161     {
162       rc = gpg_error_from_syserror ();
163       /* This is something bad.  Probably a stale lockfile.  */
164       log_info ("can't lock '%s': %s\n", filename, gpg_strerror (rc));
165       goto leave;
166     }
167
168   /* Now the real test while we are locked. */
169   if (!access (filename, F_OK))
170     {
171       rc = 0;  /* Okay, we may access the file now.  */
172       goto leave;
173     }
174
175   /* The file does not yet exist, create it now. */
176   oldmask = umask (077);
177   if (is_secured_filename (filename))
178     {
179       iobuf = NULL;
180       gpg_err_set_errno (EPERM);
181     }
182   else
183     iobuf = iobuf_create (filename);
184   umask (oldmask);
185   if (!iobuf)
186     {
187       rc = gpg_error_from_syserror ();
188       if (is_box)
189         log_error (_("error creating keybox '%s': %s\n"),
190                    filename, gpg_strerror (rc));
191       else
192         log_error (_("error creating keyring '%s': %s\n"),
193                    filename, gpg_strerror (rc));
194       goto leave;
195     }
196
197   iobuf_close (iobuf);
198   /* Must invalidate that ugly cache */
199   iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, filename);
200
201   /* Make sure that at least one record is in a new keybox file, so
202      that the detection magic will work the next time it is used.  */
203   if (is_box)
204     {
205       FILE *fp = fopen (filename, "w");
206       if (!fp)
207         rc = gpg_error_from_syserror ();
208       else
209         {
210           rc = _keybox_write_header_blob (fp);
211           fclose (fp);
212         }
213       if (rc)
214         {
215           if (is_box)
216             log_error (_("error creating keybox '%s': %s\n"),
217                        filename, gpg_strerror (rc));
218           else
219             log_error (_("error creating keyring '%s': %s\n"),
220                        filename, gpg_strerror (rc));
221           goto leave;
222         }
223     }
224
225   if (!opt.quiet)
226     {
227       if (is_box)
228         log_info (_("keybox '%s' created\n"), filename);
229       else
230         log_info (_("keyring '%s' created\n"), filename);
231     }
232
233   rc = 0;
234
235  leave:
236   if (lockhd)
237     {
238       dotlock_release (lockhd);
239       dotlock_destroy (lockhd);
240     }
241   return rc;
242 }
243
244
245 /*
246  * Register a resource (keyring or aeybox).  The first keyring or
247  * keybox which is added by this function is created if it does not
248  * exist.  FLAGS are a combination of the KEYDB_RESOURCE_FLAG_
249  * constants as defined in keydb.h.
250  */
251 gpg_error_t
252 keydb_add_resource (const char *url, unsigned int flags)
253 {
254   static int any_registered;
255   const char *resname = url;
256   char *filename = NULL;
257   int create;
258   int read_only = !!(flags&KEYDB_RESOURCE_FLAG_READONLY);
259   int rc = 0;
260   KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
261   void *token;
262
263   /* Create the resource if it is the first registered one.  */
264   create = (!read_only && !any_registered);
265
266   /* Do we have an URL?
267    *    gnupg-ring:filename  := this is a plain keyring.
268    *    gnupg-kbx:filename   := this is a keybox file.
269    *    filename := See what is is, but create as plain keyring.
270    */
271   if (strlen (resname) > 11 && !strncmp( resname, "gnupg-ring:", 11) )
272     {
273       rt = KEYDB_RESOURCE_TYPE_KEYRING;
274       resname += 11;
275     }
276   else if (strlen (resname) > 10 && !strncmp (resname, "gnupg-kbx:", 10) )
277     {
278       rt = KEYDB_RESOURCE_TYPE_KEYBOX;
279       resname += 10;
280     }
281 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
282   else if (strchr (resname, ':'))
283     {
284       log_error ("invalid key resource URL '%s'\n", url );
285       rc = gpg_error (GPG_ERR_GENERAL);
286       goto leave;
287     }
288 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
289
290   if (*resname != DIRSEP_C )
291     {
292       /* Do tilde expansion etc. */
293       if (strchr(resname, DIRSEP_C) )
294         filename = make_filename (resname, NULL);
295       else
296         filename = make_filename (opt.homedir, resname, NULL);
297     }
298   else
299     filename = xstrdup (resname);
300
301   /* See whether we can determine the filetype.  */
302   if (rt == KEYDB_RESOURCE_TYPE_NONE)
303     {
304       FILE *fp = fopen (filename, "rb");
305
306       if (fp)
307         {
308           u32 magic;
309
310           if (fread (&magic, 4, 1, fp) == 1 )
311             {
312               if (magic == 0x13579ace || magic == 0xce9a5713)
313                 ; /* GDBM magic - not anymore supported. */
314               else if (fread (&magic, 4, 1, fp) == 1
315                        && !memcmp (&magic, "\x01", 1)
316                        && fread (&magic, 4, 1, fp) == 1
317                        && !memcmp (&magic, "KBXf", 4))
318                 rt = KEYDB_RESOURCE_TYPE_KEYBOX;
319               else
320                 rt = KEYDB_RESOURCE_TYPE_KEYRING;
321             }
322           else /* Maybe empty: assume keyring. */
323             rt = KEYDB_RESOURCE_TYPE_KEYRING;
324
325           fclose (fp);
326         }
327       else /* No file yet: create keybox. */
328         rt = KEYDB_RESOURCE_TYPE_KEYBOX;
329     }
330
331   switch (rt)
332     {
333     case KEYDB_RESOURCE_TYPE_NONE:
334       log_error ("unknown type of key resource '%s'\n", url );
335       rc = gpg_error (GPG_ERR_GENERAL);
336       goto leave;
337
338     case KEYDB_RESOURCE_TYPE_KEYRING:
339       rc = maybe_create_keyring_or_box (filename, create, 0);
340       if (rc)
341         goto leave;
342
343       if (keyring_register_filename (filename, read_only, &token))
344         {
345           if (used_resources >= MAX_KEYDB_RESOURCES)
346             rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
347           else
348             {
349               if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
350                 primary_keyring = token;
351               all_resources[used_resources].type = rt;
352               all_resources[used_resources].u.kr = NULL; /* Not used here */
353               all_resources[used_resources].token = token;
354               used_resources++;
355             }
356         }
357       else
358         {
359           /* This keyring was already registered, so ignore it.
360              However, we can still mark it as primary even if it was
361              already registered.  */
362           if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
363             primary_keyring = token;
364         }
365       break;
366
367     case KEYDB_RESOURCE_TYPE_KEYBOX:
368       {
369         rc = maybe_create_keyring_or_box (filename, create, 1);
370         if (rc)
371           goto leave;
372
373         /* FIXME: How do we register a read-only keybox?  */
374         token = keybox_register_file (filename, 0);
375         if (token)
376           {
377             if (used_resources >= MAX_KEYDB_RESOURCES)
378               rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
379             else
380               {
381                 /* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
382                 /*   primary_keyring = token; */
383                 all_resources[used_resources].type = rt;
384                 all_resources[used_resources].u.kb = NULL; /* Not used here */
385                 all_resources[used_resources].token = token;
386
387                 /* FIXME: Do a compress run if needed and no other
388                    user is currently using the keybox. */
389
390                 used_resources++;
391               }
392           }
393         else
394           {
395             /* Already registered.  We will mark it as the primary key
396                if requested.  */
397             /* FIXME: How to do that?  Change the keybox interface?  */
398             /* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
399             /*   primary_keyring = token; */
400           }
401       }
402       break;
403
404       default:
405         log_error ("resource type of '%s' not supported\n", url);
406         rc = gpg_error (GPG_ERR_GENERAL);
407         goto leave;
408     }
409
410   /* fixme: check directory permissions and print a warning */
411
412  leave:
413   if (rc)
414     log_error (_("keyblock resource '%s': %s\n"), filename, gpg_strerror (rc));
415   else
416     any_registered = 1;
417   xfree (filename);
418   return rc;
419 }
420
421
422
423
424 KEYDB_HANDLE
425 keydb_new (void)
426 {
427   KEYDB_HANDLE hd;
428   int i, j;
429
430   hd = xmalloc_clear (sizeof *hd);
431   hd->found = -1;
432
433   assert (used_resources <= MAX_KEYDB_RESOURCES);
434   for (i=j=0; i < used_resources; i++)
435     {
436       switch (all_resources[i].type)
437         {
438         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
439           break;
440         case KEYDB_RESOURCE_TYPE_KEYRING:
441           hd->active[j].type   = all_resources[i].type;
442           hd->active[j].token  = all_resources[i].token;
443           hd->active[j].u.kr = keyring_new (all_resources[i].token);
444           if (!hd->active[j].u.kr) {
445             xfree (hd);
446             return NULL; /* fixme: release all previously allocated handles*/
447           }
448           j++;
449           break;
450         case KEYDB_RESOURCE_TYPE_KEYBOX:
451           hd->active[j].type   = all_resources[i].type;
452           hd->active[j].token  = all_resources[i].token;
453           hd->active[j].u.kb   = keybox_new (all_resources[i].token, 0);
454           if (!hd->active[j].u.kb)
455             {
456               xfree (hd);
457               return NULL; /* fixme: release all previously allocated handles*/
458             }
459           j++;
460           break;
461         }
462     }
463   hd->used = j;
464
465   active_handles++;
466   return hd;
467 }
468
469 void
470 keydb_release (KEYDB_HANDLE hd)
471 {
472   int i;
473
474   if (!hd)
475     return;
476   assert (active_handles > 0);
477   active_handles--;
478
479   unlock_all (hd);
480   for (i=0; i < hd->used; i++)
481     {
482       switch (hd->active[i].type)
483         {
484         case KEYDB_RESOURCE_TYPE_NONE:
485           break;
486         case KEYDB_RESOURCE_TYPE_KEYRING:
487           keyring_release (hd->active[i].u.kr);
488           break;
489         case KEYDB_RESOURCE_TYPE_KEYBOX:
490           keybox_release (hd->active[i].u.kb);
491           break;
492         }
493     }
494
495   xfree (hd);
496 }
497
498
499 /*
500  * Return the name of the current resource.  This is function first
501  * looks for the last found found, then for the current search
502  * position, and last returns the first available resource.  The
503  * returned string is only valid as long as the handle exists.  This
504  * function does only return NULL if no handle is specified, in all
505  * other error cases an empty string is returned.
506  */
507 const char *
508 keydb_get_resource_name (KEYDB_HANDLE hd)
509 {
510   int idx;
511   const char *s = NULL;
512
513   if (!hd)
514     return NULL;
515
516   if ( hd->found >= 0 && hd->found < hd->used)
517     idx = hd->found;
518   else if ( hd->current >= 0 && hd->current < hd->used)
519     idx = hd->current;
520   else
521     idx = 0;
522
523   switch (hd->active[idx].type)
524     {
525     case KEYDB_RESOURCE_TYPE_NONE:
526       s = NULL;
527       break;
528     case KEYDB_RESOURCE_TYPE_KEYRING:
529       s = keyring_get_resource_name (hd->active[idx].u.kr);
530       break;
531     case KEYDB_RESOURCE_TYPE_KEYBOX:
532       s = keybox_get_resource_name (hd->active[idx].u.kb);
533       break;
534     }
535
536   return s? s: "";
537 }
538
539
540
541 static int
542 lock_all (KEYDB_HANDLE hd)
543 {
544   int i, rc = 0;
545
546   /* Fixme: This locking scheme may lead to a deadlock if the resources
547      are not added in the same order by all processes.  We are
548      currently only allowing one resource so it is not a problem.
549      [Oops: Who claimed the latter]
550
551      To fix this we need to use a lock file to protect lock_all.  */
552
553   for (i=0; !rc && i < hd->used; i++)
554     {
555       switch (hd->active[i].type)
556         {
557         case KEYDB_RESOURCE_TYPE_NONE:
558           break;
559         case KEYDB_RESOURCE_TYPE_KEYRING:
560           rc = keyring_lock (hd->active[i].u.kr, 1);
561           break;
562         case KEYDB_RESOURCE_TYPE_KEYBOX:
563           rc = keybox_lock (hd->active[i].u.kb, 1);
564           break;
565         }
566     }
567
568   if (rc)
569     {
570       /* Revert the already taken locks.  */
571       for (i--; i >= 0; i--)
572         {
573           switch (hd->active[i].type)
574             {
575             case KEYDB_RESOURCE_TYPE_NONE:
576               break;
577             case KEYDB_RESOURCE_TYPE_KEYRING:
578               keyring_lock (hd->active[i].u.kr, 0);
579               break;
580             case KEYDB_RESOURCE_TYPE_KEYBOX:
581               rc = keybox_lock (hd->active[i].u.kb, 0);
582               break;
583             }
584         }
585     }
586   else
587     hd->locked = 1;
588
589   return rc;
590 }
591
592
593 static void
594 unlock_all (KEYDB_HANDLE hd)
595 {
596   int i;
597
598   if (!hd->locked)
599     return;
600
601   for (i=hd->used-1; i >= 0; i--)
602     {
603       switch (hd->active[i].type)
604         {
605         case KEYDB_RESOURCE_TYPE_NONE:
606           break;
607         case KEYDB_RESOURCE_TYPE_KEYRING:
608           keyring_lock (hd->active[i].u.kr, 0);
609           break;
610         case KEYDB_RESOURCE_TYPE_KEYBOX:
611           keybox_lock (hd->active[i].u.kb, 0);
612           break;
613         }
614     }
615   hd->locked = 0;
616 }
617
618
619 /*
620  * Return the last found keyring.  Caller must free it.
621  * The returned keyblock has the kbode flag bit 0 set for the node with
622  * the public key used to locate the keyblock or flag bit 1 set for
623  * the user ID node.
624  */
625 gpg_error_t
626 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
627 {
628   gpg_error_t err = 0;
629
630   if (!hd)
631     return gpg_error (GPG_ERR_INV_ARG);
632
633   if (hd->found < 0 || hd->found >= hd->used)
634     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
635
636   switch (hd->active[hd->found].type)
637     {
638     case KEYDB_RESOURCE_TYPE_NONE:
639       err = gpg_error (GPG_ERR_GENERAL); /* oops */
640       break;
641     case KEYDB_RESOURCE_TYPE_KEYRING:
642       err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
643       break;
644     /* case KEYDB_RESOURCE_TYPE_KEYBOX: */
645     /*   err = keybox_get_keyblock (hd->active[hd->found].u.kb, ret_kb); */
646     /*   if (!err) */
647     /*     err = parse_keyblock (image, imagelen) */
648     /*   break; */
649     }
650
651   return err;
652 }
653
654 /*
655  * Update the current keyblock with the keyblock KB
656  */
657 gpg_error_t
658 keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
659 {
660   gpg_error_t rc;
661
662   if (!hd)
663     return gpg_error (GPG_ERR_INV_ARG);
664
665   if (hd->found < 0 || hd->found >= hd->used)
666     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
667
668   if (opt.dry_run)
669     return 0;
670
671   rc = lock_all (hd);
672   if (rc)
673     return rc;
674
675   switch (hd->active[hd->found].type)
676     {
677     case KEYDB_RESOURCE_TYPE_NONE:
678       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
679       break;
680     case KEYDB_RESOURCE_TYPE_KEYRING:
681       rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
682       break;
683     /* case KEYDB_RESOURCE_TYPE_KEYRING: */
684     /*   rc = build_keyblock (kb, &image, &imagelen); */
685     /*   if (!rc) */
686     /*     rc = keybox_update_keyblock (hd->active[hd->found].u.kb, */
687     /*                                  image, imagelen); */
688     /*   break; */
689     }
690
691   unlock_all (hd);
692   return rc;
693 }
694
695
696 /*
697  * Insert a new KB into one of the resources.
698  */
699 gpg_error_t
700 keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
701 {
702   int rc;
703   int idx;
704
705   if (!hd)
706     return gpg_error (GPG_ERR_INV_ARG);
707
708   if (opt.dry_run)
709     return 0;
710
711   if (hd->found >= 0 && hd->found < hd->used)
712     idx = hd->found;
713   else if (hd->current >= 0 && hd->current < hd->used)
714     idx = hd->current;
715   else
716     return gpg_error (GPG_ERR_GENERAL);
717
718   rc = lock_all (hd);
719   if (rc)
720     return rc;
721
722   switch (hd->active[idx].type)
723     {
724     case KEYDB_RESOURCE_TYPE_NONE:
725       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
726       break;
727     case KEYDB_RESOURCE_TYPE_KEYRING:
728       rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
729       break;
730     /* case KEYDB_RESOURCE_TYPE_KEYBOX: */
731     /*   rc = build_keyblock (kb, &image, &imagelen); */
732     /*   if (!rc) */
733     /*     rc = keybox_insert_keyblock (hd->active[idx].u.kb, image, imagelen); */
734     /*   break; */
735     }
736
737   unlock_all (hd);
738   return rc;
739 }
740
741
742 /*
743  * Delete the current keyblock.
744  */
745 gpg_error_t
746 keydb_delete_keyblock (KEYDB_HANDLE hd)
747 {
748   gpg_error_t rc;
749
750   if (!hd)
751     return gpg_error (GPG_ERR_INV_ARG);
752
753   if (hd->found < 0 || hd->found >= hd->used)
754     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
755
756   if (opt.dry_run)
757     return 0;
758
759   rc = lock_all (hd);
760   if (rc)
761     return rc;
762
763   switch (hd->active[hd->found].type)
764     {
765     case KEYDB_RESOURCE_TYPE_NONE:
766       rc = gpg_error (GPG_ERR_GENERAL);
767       break;
768     case KEYDB_RESOURCE_TYPE_KEYRING:
769       rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
770       break;
771     case KEYDB_RESOURCE_TYPE_KEYBOX:
772       rc = keybox_delete (hd->active[hd->found].u.kb);
773       break;
774     }
775
776   unlock_all (hd);
777   return rc;
778 }
779
780
781 \f
782 /*
783  * Locate the default writable key resource, so that the next
784  * operation (which is only relevant for inserts) will be done on this
785  * resource.
786  */
787 gpg_error_t
788 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
789 {
790   gpg_error_t rc;
791
792   (void)reserved;
793
794   if (!hd)
795     return G10ERR_INV_ARG;
796
797   rc = keydb_search_reset (hd); /* this does reset hd->current */
798   if (rc)
799     return rc;
800
801   /* If we have a primary set, try that one first */
802   if (primary_keyring)
803     {
804       for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
805         {
806           if(hd->active[hd->current].token==primary_keyring)
807             {
808               if(keyring_is_writable (hd->active[hd->current].token))
809                 return 0;
810               else
811                 break;
812             }
813         }
814
815       rc = keydb_search_reset (hd); /* this does reset hd->current */
816       if (rc)
817         return rc;
818     }
819
820   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
821     {
822       switch (hd->active[hd->current].type)
823         {
824         case KEYDB_RESOURCE_TYPE_NONE:
825           BUG();
826           break;
827         case KEYDB_RESOURCE_TYPE_KEYRING:
828           if (keyring_is_writable (hd->active[hd->current].token))
829             return 0; /* found (hd->current is set to it) */
830           break;
831         case KEYDB_RESOURCE_TYPE_KEYBOX:
832           if (keybox_is_writable (hd->active[hd->current].token))
833             return 0; /* found (hd->current is set to it) */
834           break;
835         }
836     }
837
838   return gpg_error (GPG_ERR_NOT_FOUND);
839 }
840
841 /*
842  * Rebuild the caches of all key resources.
843  */
844 void
845 keydb_rebuild_caches (int noisy)
846 {
847   int i, rc;
848
849   for (i=0; i < used_resources; i++)
850     {
851       if (!keyring_is_writable (all_resources[i].token))
852         continue;
853       switch (all_resources[i].type)
854         {
855         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
856           break;
857         case KEYDB_RESOURCE_TYPE_KEYRING:
858           rc = keyring_rebuild_cache (all_resources[i].token,noisy);
859           if (rc)
860             log_error (_("failed to rebuild keyring cache: %s\n"),
861                        g10_errstr (rc));
862           break;
863         }
864     }
865 }
866
867
868
869 /*
870  * Start the next search on this handle right at the beginning
871  */
872 gpg_error_t
873 keydb_search_reset (KEYDB_HANDLE hd)
874 {
875   gpg_error_t rc = 0;
876   int i;
877
878   if (!hd)
879     return gpg_error (GPG_ERR_INV_ARG);
880
881   hd->current = 0;
882   hd->found = -1;
883   /* Now reset all resources.  */
884   for (i=0; !rc && i < hd->used; i++)
885     {
886       switch (hd->active[i].type)
887         {
888         case KEYDB_RESOURCE_TYPE_NONE:
889           break;
890         case KEYDB_RESOURCE_TYPE_KEYRING:
891           rc = keyring_search_reset (hd->active[i].u.kr);
892           break;
893         case KEYDB_RESOURCE_TYPE_KEYBOX:
894           rc = keybox_search_reset (hd->active[i].u.kb);
895           break;
896         }
897     }
898   return rc;
899 }
900
901
902 /*
903  * Search through all keydb resources, starting at the current
904  * position, for a keyblock which contains one of the keys described
905  * in the DESC array.  Returns GPG_ERR_NOT_FOUND if no matching
906  * keyring was found.
907  */
908 gpg_error_t
909 keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
910                size_t ndesc, size_t *descindex)
911 {
912   gpg_error_t rc;
913
914   if (!hd)
915     return gpg_error (GPG_ERR_INV_ARG);
916
917   rc = -1;
918   while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
919          && hd->current >= 0 && hd->current < hd->used)
920     {
921       switch (hd->active[hd->current].type)
922         {
923         case KEYDB_RESOURCE_TYPE_NONE:
924           BUG(); /* we should never see it here */
925           break;
926         case KEYDB_RESOURCE_TYPE_KEYRING:
927           rc = keyring_search (hd->active[hd->current].u.kr, desc,
928                                ndesc, descindex);
929           break;
930         case KEYDB_RESOURCE_TYPE_KEYBOX:
931           rc = keybox_search (hd->active[hd->current].u.kb, desc, ndesc);
932           break;
933         }
934       if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
935         {
936           /* EOF -> switch to next resource */
937           hd->current++;
938         }
939       else if (!rc)
940         hd->found = hd->current;
941     }
942
943   return ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
944           ? gpg_error (GPG_ERR_NOT_FOUND)
945           : rc);
946 }
947
948
949 gpg_error_t
950 keydb_search_first (KEYDB_HANDLE hd)
951 {
952   KEYDB_SEARCH_DESC desc;
953
954   memset (&desc, 0, sizeof desc);
955   desc.mode = KEYDB_SEARCH_MODE_FIRST;
956   return keydb_search (hd, &desc, 1);
957 }
958
959 gpg_error_t
960 keydb_search_next (KEYDB_HANDLE hd)
961 {
962   KEYDB_SEARCH_DESC desc;
963
964   memset (&desc, 0, sizeof desc);
965   desc.mode = KEYDB_SEARCH_MODE_NEXT;
966   return keydb_search (hd, &desc, 1);
967 }
968
969 gpg_error_t
970 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
971 {
972   KEYDB_SEARCH_DESC desc;
973
974   memset (&desc, 0, sizeof desc);
975   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
976   desc.u.kid[0] = kid[0];
977   desc.u.kid[1] = kid[1];
978   return keydb_search (hd, &desc, 1);
979 }
980
981 gpg_error_t
982 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
983 {
984   KEYDB_SEARCH_DESC desc;
985
986   memset (&desc, 0, sizeof desc);
987   desc.mode = KEYDB_SEARCH_MODE_FPR;
988   memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
989   return keydb_search (hd, &desc, 1);
990 }