sm: Avoid double-free on iconv failure
[gnupg.git] / g10 / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2008, 2009, 2012 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 "keydb.h"
38 #include "i18n.h"
39
40 static int active_handles;
41
42 typedef enum {
43     KEYDB_RESOURCE_TYPE_NONE = 0,
44     KEYDB_RESOURCE_TYPE_KEYRING,
45     KEYDB_RESOURCE_TYPE_KEYBOX
46 } KeydbResourceType;
47 #define MAX_KEYDB_RESOURCES 40
48
49 struct resource_item {
50   KeydbResourceType type;
51   union {
52     KEYRING_HANDLE kr;
53   } u;
54   void *token;
55   int secret;
56 };
57
58 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
59 static int used_resources;
60 static void *primary_keyring=NULL;
61
62 struct keydb_handle {
63   int locked;
64   int found;
65   int current;
66   int used; /* items in active */
67   struct resource_item active[MAX_KEYDB_RESOURCES];
68 };
69
70
71 static int lock_all (KEYDB_HANDLE hd);
72 static void unlock_all (KEYDB_HANDLE hd);
73
74
75 /* Handle the creation of a keyring if it does not yet exist.  Take
76    into acount that other processes might have the keyring already
77    locked.  This lock check does not work if the directory itself is
78    not yet available. */
79 static int
80 maybe_create_keyring (char *filename, int force)
81 {
82   DOTLOCK lockhd = NULL;
83   IOBUF iobuf;
84   int rc;
85   mode_t oldmask;
86   char *last_slash_in_filename;
87   int save_slash;
88
89   /* A quick test whether the filename already exists. */
90   if (!access (filename, F_OK))
91     return 0;
92
93   /* If we don't want to create a new file at all, there is no need to
94      go any further - bail out right here.  */
95   if (!force)
96     return gpg_error (GPG_ERR_ENOENT);
97
98   /* First of all we try to create the home directory.  Note, that we
99      don't do any locking here because any sane application of gpg
100      would create the home directory by itself and not rely on gpg's
101      tricky auto-creation which is anyway only done for some home
102      directory name patterns. */
103   last_slash_in_filename = strrchr (filename, DIRSEP_C);
104 #if HAVE_W32_SYSTEM
105   {
106     /* Windows may either have a slash or a backslash.  Take care of it.  */
107     char *p = strrchr (filename, '/');
108     if (!last_slash_in_filename || p > last_slash_in_filename)
109       last_slash_in_filename = p;
110   }
111 #endif /*HAVE_W32_SYSTEM*/
112   if (!last_slash_in_filename)
113     return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
114                                            not happen though.  */
115   save_slash = *last_slash_in_filename;
116   *last_slash_in_filename = 0;
117   if (access(filename, F_OK))
118     {
119       static int tried;
120
121       if (!tried)
122         {
123           tried = 1;
124           try_make_homedir (filename);
125         }
126       if (access (filename, F_OK))
127         {
128           rc = gpg_error_from_syserror ();
129           *last_slash_in_filename = save_slash;
130           goto leave;
131         }
132     }
133   *last_slash_in_filename = save_slash;
134
135   /* To avoid races with other instances of gpg trying to create or
136      update the keyring (it is removed during an update for a short
137      time), we do the next stuff in a locked state. */
138   lockhd = create_dotlock (filename);
139   if (!lockhd)
140     {
141       /* A reason for this to fail is that the directory is not
142          writable. However, this whole locking stuff does not make
143          sense if this is the case. An empty non-writable directory
144          with no keyring is not really useful at all. */
145       if (opt.verbose)
146         log_info ("can't allocate lock for `%s'\n", filename );
147
148       if (!force)
149         return gpg_error (GPG_ERR_ENOENT);
150       else
151         return gpg_error (GPG_ERR_GENERAL);
152     }
153
154   if ( make_dotlock (lockhd, -1) )
155     {
156       /* This is something bad.  Probably a stale lockfile.  */
157       log_info ("can't lock `%s'\n", filename );
158       rc = G10ERR_GENERAL;
159       goto leave;
160     }
161
162   /* Now the real test while we are locked. */
163   if (!access(filename, F_OK))
164     {
165       rc = 0;  /* Okay, we may access the file now.  */
166       goto leave;
167     }
168
169   /* The file does not yet exist, create it now. */
170   oldmask = umask (077);
171   if (is_secured_filename (filename))
172     {
173       iobuf = NULL;
174       errno = EPERM;
175     }
176   else
177     iobuf = iobuf_create (filename);
178   umask (oldmask);
179   if (!iobuf)
180     {
181       rc = gpg_error_from_syserror ();
182       log_error ( _("error creating keyring `%s': %s\n"),
183                   filename, strerror(errno));
184       goto leave;
185     }
186
187   if (!opt.quiet)
188     log_info (_("keyring `%s' created\n"), filename);
189
190   iobuf_close (iobuf);
191   /* Must invalidate that ugly cache */
192   iobuf_ioctl (NULL, 2, 0, filename);
193   rc = 0;
194
195  leave:
196   if (lockhd)
197     {
198       release_dotlock (lockhd);
199       destroy_dotlock (lockhd);
200     }
201   return rc;
202 }
203
204
205 /*
206  * Register a resource (which currently may only be a keyring file).
207  * The first keyring which is added by this function is
208  * created if it does not exist.
209  * Note: this function may be called before secure memory is
210  * available.
211  * Flag 1   - Force.
212  * Flag 2   - Mark resource as primary.
213  * Flag 4   - This is a default resources.
214  * Flag 8   - Open as read-only.
215  */
216 int
217 keydb_add_resource (const char *url, int flags, int secret)
218 {
219     static int any_secret, any_public;
220     const char *resname = url;
221     char *filename = NULL;
222     int force = (flags&1);
223     int readonly = !!(flags&8);
224     int rc = 0;
225     KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
226     void *token;
227
228     if (readonly)
229       force = 0;
230
231     /* Do we have an URL?
232      *  gnupg-ring:filename  := this is a plain keyring
233      *  filename := See what is is, but create as plain keyring.
234      */
235     if (strlen (resname) > 11) {
236         if (!strncmp( resname, "gnupg-ring:", 11) ) {
237             rt = KEYDB_RESOURCE_TYPE_KEYRING;
238             resname += 11;
239         }
240         else if (strlen (resname) > 10 && !strncmp (resname, "gnupg-kbx:", 10) )
241           {
242             rt = KEYDB_RESOURCE_TYPE_KEYBOX;
243             resname += 10;
244           }
245 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
246         else if (strchr (resname, ':')) {
247             log_error ("invalid key resource URL `%s'\n", url );
248             rc = G10ERR_GENERAL;
249             goto leave;
250         }
251 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
252     }
253
254     if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
255         if (strchr(resname, DIRSEP_C) )
256             filename = make_filename (resname, NULL);
257         else
258             filename = make_filename (opt.homedir, resname, NULL);
259     }
260     else
261         filename = xstrdup (resname);
262
263     if (!force && !readonly)
264         force = secret? !any_secret : !any_public;
265
266     /* See whether we can determine the filetype.  */
267     if (rt == KEYDB_RESOURCE_TYPE_NONE) {
268         FILE *fp = fopen( filename, "rb" );
269
270         if (fp) {
271             u32 magic;
272
273             if (fread( &magic, 4, 1, fp) == 1 ) {
274                 if (magic == 0x13579ace || magic == 0xce9a5713)
275                     ; /* GDBM magic - no more support */
276                 else if (fread (&magic, 4, 1, fp) == 1
277                          && !memcmp (&magic, "\x01", 1)
278                          && fread (&magic, 4, 1, fp) == 1
279                          && !memcmp (&magic, "KBXf", 4))
280                     rt = KEYDB_RESOURCE_TYPE_KEYBOX;
281                 else
282                     rt = KEYDB_RESOURCE_TYPE_KEYRING;
283             }
284             else /* maybe empty: assume ring */
285                 rt = KEYDB_RESOURCE_TYPE_KEYRING;
286             fclose( fp );
287         }
288         else /* no file yet: create ring */
289             rt = KEYDB_RESOURCE_TYPE_KEYRING;
290     }
291
292     switch (rt) {
293       case KEYDB_RESOURCE_TYPE_NONE:
294         log_error ("unknown type of key resource `%s'\n", url );
295         rc = G10ERR_GENERAL;
296         goto leave;
297
298       case KEYDB_RESOURCE_TYPE_KEYRING:
299         rc = maybe_create_keyring (filename, force);
300         if (rc)
301           goto leave;
302
303         if(keyring_register_filename (filename, secret, readonly, &token))
304           {
305             if (used_resources >= MAX_KEYDB_RESOURCES)
306               rc = G10ERR_RESOURCE_LIMIT;
307             else
308               {
309                 if(flags&2)
310                   primary_keyring=token;
311                 all_resources[used_resources].type = rt;
312                 all_resources[used_resources].u.kr = NULL; /* Not used here */
313                 all_resources[used_resources].token = token;
314                 all_resources[used_resources].secret = secret;
315                 used_resources++;
316               }
317           }
318         else
319           {
320             /* This keyring was already registered, so ignore it.
321                However, we can still mark it as primary even if it was
322                already registered. */
323             if(flags&2)
324               primary_keyring=token;
325           }
326         break;
327
328       case KEYDB_RESOURCE_TYPE_KEYBOX:
329         rc = G10ERR_UNSUPPORTED;
330         goto leave;
331
332       default:
333         log_error ("resource type of `%s' not supported\n", url);
334         rc = G10ERR_GENERAL;
335         goto leave;
336     }
337
338     /* fixme: check directory permissions and print a warning */
339
340   leave:
341     if (rc)
342       {
343         /* Secret keyrings are not required in all cases.  To avoid
344            having gpg return failure we use log_info here if the
345            rewsource is a secret one and marked as default
346            resource.  */
347         if ((flags&4) && secret)
348           log_info (_("keyblock resource `%s': %s\n"),
349                     filename, g10_errstr(rc));
350         else
351           log_error (_("keyblock resource `%s': %s\n"),
352                      filename, g10_errstr(rc));
353         if (rt == KEYDB_RESOURCE_TYPE_KEYBOX)
354           log_error ("Note: This version of GPG does not support"
355                      " the Keybox format\n");
356       }
357     else if (secret)
358         any_secret = 1;
359     else
360         any_public = 1;
361     xfree (filename);
362     return rc;
363 }
364
365
366
367
368 KEYDB_HANDLE
369 keydb_new (int secret)
370 {
371   KEYDB_HANDLE hd;
372   int i, j;
373
374   hd = xmalloc_clear (sizeof *hd);
375   hd->found = -1;
376
377   assert (used_resources <= MAX_KEYDB_RESOURCES);
378   for (i=j=0; i < used_resources; i++)
379     {
380       if (!all_resources[i].secret != !secret)
381         continue;
382       switch (all_resources[i].type)
383         {
384         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
385         case KEYDB_RESOURCE_TYPE_KEYBOX: /* ignore */
386           break;
387         case KEYDB_RESOURCE_TYPE_KEYRING:
388           hd->active[j].type   = all_resources[i].type;
389           hd->active[j].token  = all_resources[i].token;
390           hd->active[j].secret = all_resources[i].secret;
391           hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
392           if (!hd->active[j].u.kr) {
393             xfree (hd);
394             return NULL; /* fixme: release all previously allocated handles*/
395           }
396           j++;
397           break;
398         }
399     }
400   hd->used = j;
401
402   active_handles++;
403   return hd;
404 }
405
406 void
407 keydb_release (KEYDB_HANDLE hd)
408 {
409     int i;
410
411     if (!hd)
412         return;
413     assert (active_handles > 0);
414     active_handles--;
415
416     unlock_all (hd);
417     for (i=0; i < hd->used; i++) {
418         switch (hd->active[i].type) {
419           case KEYDB_RESOURCE_TYPE_NONE:
420           case KEYDB_RESOURCE_TYPE_KEYBOX:
421             break;
422           case KEYDB_RESOURCE_TYPE_KEYRING:
423             keyring_release (hd->active[i].u.kr);
424             break;
425         }
426     }
427
428     xfree (hd);
429 }
430
431
432 /*
433  * Return the name of the current resource.  This is function first
434  * looks for the last found found, then for the current search
435  * position, and last returns the first available resource.  The
436  * returned string is only valid as long as the handle exists.  This
437  * function does only return NULL if no handle is specified, in all
438  * other error cases an empty string is returned.
439  */
440 const char *
441 keydb_get_resource_name (KEYDB_HANDLE hd)
442 {
443     int idx;
444     const char *s = NULL;
445
446     if (!hd)
447         return NULL;
448
449     if ( hd->found >= 0 && hd->found < hd->used)
450         idx = hd->found;
451     else if ( hd->current >= 0 && hd->current < hd->used)
452         idx = hd->current;
453     else
454         idx = 0;
455
456     switch (hd->active[idx].type) {
457       case KEYDB_RESOURCE_TYPE_NONE:
458       case KEYDB_RESOURCE_TYPE_KEYBOX:
459         s = NULL;
460         break;
461       case KEYDB_RESOURCE_TYPE_KEYRING:
462         s = keyring_get_resource_name (hd->active[idx].u.kr);
463         break;
464     }
465
466     return s? s: "";
467 }
468
469
470
471 static int
472 lock_all (KEYDB_HANDLE hd)
473 {
474     int i, rc = 0;
475
476     for (i=0; !rc && i < hd->used; i++) {
477         switch (hd->active[i].type) {
478           case KEYDB_RESOURCE_TYPE_NONE:
479           case KEYDB_RESOURCE_TYPE_KEYBOX:
480             break;
481           case KEYDB_RESOURCE_TYPE_KEYRING:
482             rc = keyring_lock (hd->active[i].u.kr, 1);
483             break;
484         }
485     }
486
487     if (rc) {
488         /* revert the already set locks */
489         for (i--; i >= 0; i--) {
490             switch (hd->active[i].type) {
491               case KEYDB_RESOURCE_TYPE_NONE:
492               case KEYDB_RESOURCE_TYPE_KEYBOX:
493                 break;
494               case KEYDB_RESOURCE_TYPE_KEYRING:
495                 keyring_lock (hd->active[i].u.kr, 0);
496                 break;
497             }
498         }
499     }
500     else
501         hd->locked = 1;
502
503     return rc;
504 }
505
506 static void
507 unlock_all (KEYDB_HANDLE hd)
508 {
509     int i;
510
511     if (!hd->locked)
512         return;
513
514     for (i=hd->used-1; i >= 0; i--) {
515         switch (hd->active[i].type) {
516           case KEYDB_RESOURCE_TYPE_NONE:
517           case KEYDB_RESOURCE_TYPE_KEYBOX:
518             break;
519           case KEYDB_RESOURCE_TYPE_KEYRING:
520             keyring_lock (hd->active[i].u.kr, 0);
521             break;
522         }
523     }
524     hd->locked = 0;
525 }
526
527
528 /*
529  * Return the last found keyring.  Caller must free it.
530  * The returned keyblock has the kbode flag bit 0 set for the node with
531  * the public key used to locate the keyblock or flag bit 1 set for
532  * the user ID node.
533  */
534 int
535 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
536 {
537     int rc = 0;
538
539     if (!hd)
540         return G10ERR_INV_ARG;
541
542     if ( hd->found < 0 || hd->found >= hd->used)
543         return -1; /* nothing found */
544
545     switch (hd->active[hd->found].type) {
546       case KEYDB_RESOURCE_TYPE_NONE:
547       case KEYDB_RESOURCE_TYPE_KEYBOX:
548         rc = G10ERR_GENERAL; /* oops */
549         break;
550       case KEYDB_RESOURCE_TYPE_KEYRING:
551         rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
552         break;
553     }
554
555     return rc;
556 }
557
558 /*
559  * update the current keyblock with KB
560  */
561 int
562 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
563 {
564     int rc = 0;
565
566     if (!hd)
567         return G10ERR_INV_ARG;
568
569     if ( hd->found < 0 || hd->found >= hd->used)
570         return -1; /* nothing found */
571
572     if( opt.dry_run )
573         return 0;
574
575     rc = lock_all (hd);
576     if (rc)
577         return rc;
578
579     switch (hd->active[hd->found].type) {
580       case KEYDB_RESOURCE_TYPE_NONE:
581       case KEYDB_RESOURCE_TYPE_KEYBOX:
582         rc = G10ERR_GENERAL; /* oops */
583         break;
584       case KEYDB_RESOURCE_TYPE_KEYRING:
585         rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
586         break;
587     }
588
589     unlock_all (hd);
590     return rc;
591 }
592
593
594 /*
595  * Insert a new KB into one of the resources.
596  */
597 int
598 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
599 {
600     int rc = -1;
601     int idx;
602
603     if (!hd)
604         return G10ERR_INV_ARG;
605
606     if( opt.dry_run )
607         return 0;
608
609     if ( hd->found >= 0 && hd->found < hd->used)
610         idx = hd->found;
611     else if ( hd->current >= 0 && hd->current < hd->used)
612         idx = hd->current;
613     else
614         return G10ERR_GENERAL;
615
616     rc = lock_all (hd);
617     if (rc)
618         return rc;
619
620     switch (hd->active[idx].type) {
621       case KEYDB_RESOURCE_TYPE_NONE:
622       case KEYDB_RESOURCE_TYPE_KEYBOX:
623         rc = G10ERR_GENERAL; /* oops */
624         break;
625       case KEYDB_RESOURCE_TYPE_KEYRING:
626         rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
627         break;
628     }
629
630     unlock_all (hd);
631     return rc;
632 }
633
634
635 /*
636  * The current keyblock will be deleted.
637  */
638 int
639 keydb_delete_keyblock (KEYDB_HANDLE hd)
640 {
641     int rc = -1;
642
643     if (!hd)
644         return G10ERR_INV_ARG;
645
646     if ( hd->found < 0 || hd->found >= hd->used)
647         return -1; /* nothing found */
648
649     if( opt.dry_run )
650         return 0;
651
652     rc = lock_all (hd);
653     if (rc)
654         return rc;
655
656     switch (hd->active[hd->found].type) {
657       case KEYDB_RESOURCE_TYPE_NONE:
658       case KEYDB_RESOURCE_TYPE_KEYBOX:
659         rc = G10ERR_GENERAL; /* oops */
660         break;
661       case KEYDB_RESOURCE_TYPE_KEYRING:
662         rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
663         break;
664     }
665
666     unlock_all (hd);
667     return rc;
668 }
669
670 \f
671 /*
672  * Locate the default writable key resource, so that the next
673  * operation (which is only relevant for inserts) will be done on this
674  * resource.
675  */
676 int
677 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
678 {
679   int rc;
680
681   (void)reserved;
682
683   if (!hd)
684     return G10ERR_INV_ARG;
685
686   rc = keydb_search_reset (hd); /* this does reset hd->current */
687   if (rc)
688     return rc;
689
690   /* If we have a primary set, try that one first */
691   if(primary_keyring)
692     {
693       for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
694         {
695           if(hd->active[hd->current].token==primary_keyring)
696             {
697               if(keyring_is_writable (hd->active[hd->current].token))
698                 return 0;
699               else
700                 break;
701             }
702         }
703
704       rc = keydb_search_reset (hd); /* this does reset hd->current */
705       if (rc)
706         return rc;
707     }
708
709   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
710     {
711       switch (hd->active[hd->current].type)
712         {
713         case KEYDB_RESOURCE_TYPE_NONE:
714         case KEYDB_RESOURCE_TYPE_KEYBOX:
715           BUG();
716           break;
717         case KEYDB_RESOURCE_TYPE_KEYRING:
718           if (keyring_is_writable (hd->active[hd->current].token))
719             return 0; /* found (hd->current is set to it) */
720           break;
721         }
722     }
723
724   return -1;
725 }
726
727 /*
728  * Rebuild the caches of all key resources.
729  */
730 void
731 keydb_rebuild_caches (int noisy)
732 {
733   int i, rc;
734
735   for (i=0; i < used_resources; i++)
736     {
737       if (all_resources[i].secret)
738         continue;
739       if (!keyring_is_writable (all_resources[i].token))
740         continue;
741       switch (all_resources[i].type)
742         {
743         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
744         case KEYDB_RESOURCE_TYPE_KEYBOX: /* ignore */
745           break;
746         case KEYDB_RESOURCE_TYPE_KEYRING:
747           rc = keyring_rebuild_cache (all_resources[i].token,noisy);
748           if (rc)
749             log_error (_("failed to rebuild keyring cache: %s\n"),
750                        g10_errstr (rc));
751           break;
752         }
753     }
754 }
755
756
757
758 /*
759  * Start the next search on this handle right at the beginning
760  */
761 int
762 keydb_search_reset (KEYDB_HANDLE hd)
763 {
764     int i, rc = 0;
765
766     if (!hd)
767         return G10ERR_INV_ARG;
768
769     hd->current = 0;
770     hd->found = -1;
771     /* and reset all resources */
772     for (i=0; !rc && i < hd->used; i++) {
773         switch (hd->active[i].type) {
774           case KEYDB_RESOURCE_TYPE_NONE:
775           case KEYDB_RESOURCE_TYPE_KEYBOX:
776             break;
777           case KEYDB_RESOURCE_TYPE_KEYRING:
778             rc = keyring_search_reset (hd->active[i].u.kr);
779             break;
780         }
781     }
782     return rc;
783 }
784
785
786 /*
787  * Search through all keydb resources, starting at the current position,
788  * for a keyblock which contains one of the keys described in the DESC array.
789  */
790 int
791 keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
792                size_t ndesc, size_t *descindex)
793 {
794     int rc = -1;
795
796     if (!hd)
797         return G10ERR_INV_ARG;
798
799     while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
800         switch (hd->active[hd->current].type) {
801           case KEYDB_RESOURCE_TYPE_NONE:
802           case KEYDB_RESOURCE_TYPE_KEYBOX:
803             BUG(); /* we should never see it here */
804             break;
805           case KEYDB_RESOURCE_TYPE_KEYRING:
806             rc = keyring_search (hd->active[hd->current].u.kr, desc,
807                                  ndesc, descindex);
808             break;
809         }
810         if (rc == -1) /* EOF -> switch to next resource */
811             hd->current++;
812         else if (!rc)
813             hd->found = hd->current;
814     }
815
816     return rc;
817 }
818
819 int
820 keydb_search_first (KEYDB_HANDLE hd)
821 {
822     KEYDB_SEARCH_DESC desc;
823
824     memset (&desc, 0, sizeof desc);
825     desc.mode = KEYDB_SEARCH_MODE_FIRST;
826     return keydb_search (hd, &desc, 1);
827 }
828
829 int
830 keydb_search_next (KEYDB_HANDLE hd)
831 {
832     KEYDB_SEARCH_DESC desc;
833
834     memset (&desc, 0, sizeof desc);
835     desc.mode = KEYDB_SEARCH_MODE_NEXT;
836     return keydb_search (hd, &desc, 1);
837 }
838
839 int
840 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
841 {
842     KEYDB_SEARCH_DESC desc;
843
844     memset (&desc, 0, sizeof desc);
845     desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
846     desc.u.kid[0] = kid[0];
847     desc.u.kid[1] = kid[1];
848     return keydb_search (hd, &desc, 1);
849 }
850
851 int
852 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
853 {
854     KEYDB_SEARCH_DESC desc;
855
856     memset (&desc, 0, sizeof desc);
857     desc.mode = KEYDB_SEARCH_MODE_FPR;
858     memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
859     return keydb_search (hd, &desc, 1);
860 }