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