sm: Create homedir and lock empty keybox creation.
[gnupg.git] / sm / keydb.c
1 /* keydb.c - key database dispatcher
2  * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
3  * Copyright (C) 2014 g10 Code GmbH
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 <fcntl.h>
30 #include <unistd.h>
31
32 #include "gpgsm.h"
33 #include "../kbx/keybox.h"
34 #include "keydb.h"
35 #include "i18n.h"
36
37 static int active_handles;
38
39 typedef enum {
40     KEYDB_RESOURCE_TYPE_NONE = 0,
41     KEYDB_RESOURCE_TYPE_KEYBOX
42 } KeydbResourceType;
43 #define MAX_KEYDB_RESOURCES 20
44
45 struct resource_item {
46   KeydbResourceType type;
47   union {
48     KEYBOX_HANDLE kr;
49   } u;
50   void *token;
51   int secret;
52   DOTLOCK lockhandle;
53 };
54
55 static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
56 static int used_resources;
57
58 struct keydb_handle {
59   int locked;
60   int found;
61   int saved_found;
62   int current;
63   int is_ephemeral;
64   int used; /* items in active */
65   struct resource_item active[MAX_KEYDB_RESOURCES];
66 };
67
68
69 static int lock_all (KEYDB_HANDLE hd);
70 static void unlock_all (KEYDB_HANDLE hd);
71
72
73 static void
74 try_make_homedir (const char *fname)
75 {
76   const char *defhome = standard_homedir ();
77
78   /* Create the directory only if the supplied directory name is the
79      same as the default one.  This way we avoid to create arbitrary
80      directories when a non-default home directory is used.  To cope
81      with HOME, we do compare only the suffix if we see that the
82      default homedir does start with a tilde.  */
83   if ( opt.dry_run || opt.no_homedir_creation )
84     return;
85
86   if (
87 #ifdef HAVE_W32_SYSTEM
88       ( !compare_filenames (fname, defhome) )
89 #else
90       ( *defhome == '~'
91         && (strlen(fname) >= strlen (defhome+1)
92             && !strcmp(fname+strlen(fname)-strlen(defhome+1), defhome+1 ) ))
93       || (*defhome != '~'  && !compare_filenames( fname, defhome ) )
94 #endif
95       )
96     {
97       if ( mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR) )
98         log_info (_("can't create directory `%s': %s\n"),
99                   fname, strerror(errno) );
100       else if (!opt.quiet )
101         log_info (_("directory `%s' created\n"), fname);
102     }
103 }
104
105
106 /* Handle the creation of a keybox if it does not yet exist.  Take
107    into acount that other processes might have the keybox already
108    locked.  This lock check does not work if the directory itself is
109    not yet available.  If R_CREATED is not NULL it will be set to true
110    if the function created a new keybox.  */
111 static int
112 maybe_create_keybox (char *filename, int force, int *r_created)
113 {
114   DOTLOCK lockhd = NULL;
115   FILE *fp;
116   int rc;
117   mode_t oldmask;
118   char *last_slash_in_filename;
119   int save_slash;
120
121   if (r_created)
122     *r_created = 0;
123
124   /* A quick test whether the filename already exists. */
125   if (!access (filename, F_OK))
126     return 0;
127
128   /* If we don't want to create a new file at all, there is no need to
129      go any further - bail out right here.  */
130   if (!force)
131     return gpg_error (GPG_ERR_ENOENT);
132
133   /* First of all we try to create the home directory.  Note, that we
134      don't do any locking here because any sane application of gpg
135      would create the home directory by itself and not rely on gpg's
136      tricky auto-creation which is anyway only done for some home
137      directory name patterns. */
138   last_slash_in_filename = strrchr (filename, DIRSEP_C);
139 #if HAVE_W32_SYSTEM
140   {
141     /* Windows may either have a slash or a backslash.  Take care of it.  */
142     char *p = strrchr (filename, '/');
143     if (!last_slash_in_filename || p > last_slash_in_filename)
144       last_slash_in_filename = p;
145   }
146 #endif /*HAVE_W32_SYSTEM*/
147   if (!last_slash_in_filename)
148     return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
149                                            not happen though.  */
150   save_slash = *last_slash_in_filename;
151   *last_slash_in_filename = 0;
152   if (access(filename, F_OK))
153     {
154       static int tried;
155
156       if (!tried)
157         {
158           tried = 1;
159           try_make_homedir (filename);
160         }
161       if (access (filename, F_OK))
162         {
163           rc = gpg_error_from_syserror ();
164           *last_slash_in_filename = save_slash;
165           goto leave;
166         }
167     }
168   *last_slash_in_filename = save_slash;
169
170   /* To avoid races with other instances of gpg trying to create or
171      update the keybox (it is removed during an update for a short
172      time), we do the next stuff in a locked state. */
173   lockhd = create_dotlock (filename);
174   if (!lockhd)
175     {
176       /* A reason for this to fail is that the directory is not
177          writable. However, this whole locking stuff does not make
178          sense if this is the case. An empty non-writable directory
179          with no keyring is not really useful at all. */
180       if (opt.verbose)
181         log_info ("can't allocate lock for `%s'\n", filename );
182
183       if (!force)
184         return gpg_error (GPG_ERR_ENOENT);
185       else
186         return gpg_error (GPG_ERR_GENERAL);
187     }
188
189   if ( make_dotlock (lockhd, -1) )
190     {
191       /* This is something bad.  Probably a stale lockfile.  */
192       log_info ("can't lock `%s'\n", filename);
193       rc = gpg_error (GPG_ERR_GENERAL);
194       goto leave;
195     }
196
197   /* Now the real test while we are locked. */
198   if (!access(filename, F_OK))
199     {
200       rc = 0;  /* Okay, we may access the file now.  */
201       goto leave;
202     }
203
204   /* The file does not yet exist, create it now. */
205   oldmask = umask (077);
206   fp = fopen (filename, "w");
207   if (!fp)
208     {
209       rc = gpg_error_from_syserror ();
210       umask (oldmask);
211       log_error (_("error creating keybox `%s': %s\n"),
212                  filename, gpg_strerror (rc));
213       goto leave;
214     }
215   umask (oldmask);
216
217   if (!opt.quiet)
218     log_info (_("keybox `%s' created\n"), filename);
219   if (r_created)
220     *r_created = 1;
221
222   fclose (fp);
223   rc = 0;
224
225  leave:
226   if (lockhd)
227     {
228       release_dotlock (lockhd);
229       destroy_dotlock (lockhd);
230     }
231   return rc;
232 }
233
234
235 /*
236  * Register a resource (which currently may only be a keybox file).
237  * The first keybox which is added by this function is created if it
238  * does not exist.  If AUTO_CREATED is not NULL it will be set to true
239  * if the function has created a new keybox.
240  */
241 int
242 keydb_add_resource (const char *url, int force, int secret, int *auto_created)
243 {
244   static int any_secret, any_public;
245   const char *resname = url;
246   char *filename = NULL;
247   int rc = 0;
248   FILE *fp;
249   KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
250
251   if (auto_created)
252     *auto_created = 0;
253
254   /* Do we have an URL?
255      gnupg-kbx:filename := this is a plain keybox
256      filename := See what is is, but create as plain keybox.
257   */
258   if (strlen (resname) > 10)
259     {
260       if (!strncmp (resname, "gnupg-kbx:", 10) )
261         {
262           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
263           resname += 10;
264         }
265 #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
266       else if (strchr (resname, ':'))
267         {
268           log_error ("invalid key resource URL `%s'\n", url );
269           rc = gpg_error (GPG_ERR_GENERAL);
270           goto leave;
271         }
272 #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
273     }
274
275   if (*resname != DIRSEP_C )
276     { /* do tilde expansion etc */
277       if (strchr(resname, DIRSEP_C) )
278         filename = make_filename (resname, NULL);
279       else
280         filename = make_filename (opt.homedir, resname, NULL);
281     }
282   else
283     filename = xstrdup (resname);
284
285   if (!force)
286     force = secret? !any_secret : !any_public;
287
288   /* see whether we can determine the filetype */
289   if (rt == KEYDB_RESOURCE_TYPE_NONE)
290     {
291       FILE *fp2 = fopen( filename, "rb" );
292
293       if (fp2) {
294         u32 magic;
295
296         /* FIXME: check for the keybox magic */
297         if (fread( &magic, 4, 1, fp2) == 1 )
298           {
299             if (magic == 0x13579ace || magic == 0xce9a5713)
300               ; /* GDBM magic - no more support */
301             else
302               rt = KEYDB_RESOURCE_TYPE_KEYBOX;
303           }
304         else /* maybe empty: assume keybox */
305           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
306         fclose (fp2);
307       }
308       else /* no file yet: create keybox */
309         rt = KEYDB_RESOURCE_TYPE_KEYBOX;
310     }
311
312   switch (rt)
313     {
314     case KEYDB_RESOURCE_TYPE_NONE:
315       log_error ("unknown type of key resource `%s'\n", url );
316       rc = gpg_error (GPG_ERR_GENERAL);
317       goto leave;
318
319     case KEYDB_RESOURCE_TYPE_KEYBOX:
320       rc = maybe_create_keybox (filename, force, auto_created);
321       if (rc)
322         goto leave;
323       /* Now register the file */
324       {
325         void *token = keybox_register_file (filename, secret);
326         if (!token)
327           ; /* already registered - ignore it */
328         else if (used_resources >= MAX_KEYDB_RESOURCES)
329           rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
330         else
331           {
332             all_resources[used_resources].type = rt;
333             all_resources[used_resources].u.kr = NULL; /* Not used here */
334             all_resources[used_resources].token = token;
335             all_resources[used_resources].secret = secret;
336
337             all_resources[used_resources].lockhandle
338               = create_dotlock (filename);
339             if (!all_resources[used_resources].lockhandle)
340               log_fatal ( _("can't create lock for `%s'\n"), filename);
341
342             /* Do a compress run if needed and the file is not locked. */
343             if (!make_dotlock (all_resources[used_resources].lockhandle, 0))
344               {
345                 KEYBOX_HANDLE kbxhd = keybox_new (token, secret);
346
347                 if (kbxhd)
348                   {
349                     keybox_compress (kbxhd);
350                     keybox_release (kbxhd);
351                   }
352                 release_dotlock (all_resources[used_resources].lockhandle);
353               }
354
355             used_resources++;
356           }
357       }
358       break;
359
360     default:
361       log_error ("resource type of `%s' not supported\n", url);
362       rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
363       goto leave;
364     }
365
366   /* fixme: check directory permissions and print a warning */
367
368  leave:
369   if (rc)
370     log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror(rc));
371   else if (secret)
372     any_secret = 1;
373   else
374     any_public = 1;
375   xfree (filename);
376   return rc;
377 }
378
379
380 KEYDB_HANDLE
381 keydb_new (int secret)
382 {
383   KEYDB_HANDLE hd;
384   int i, j;
385
386   hd = xcalloc (1, sizeof *hd);
387   hd->found = -1;
388   hd->saved_found = -1;
389
390   assert (used_resources <= MAX_KEYDB_RESOURCES);
391   for (i=j=0; i < used_resources; i++)
392     {
393       if (!all_resources[i].secret != !secret)
394         continue;
395       switch (all_resources[i].type)
396         {
397         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
398           break;
399         case KEYDB_RESOURCE_TYPE_KEYBOX:
400           hd->active[j].type   = all_resources[i].type;
401           hd->active[j].token  = all_resources[i].token;
402           hd->active[j].secret = all_resources[i].secret;
403           hd->active[j].lockhandle = all_resources[i].lockhandle;
404           hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
405           if (!hd->active[j].u.kr)
406             {
407               xfree (hd);
408               return NULL; /* fixme: release all previously allocated handles*/
409             }
410           j++;
411           break;
412         }
413     }
414   hd->used = j;
415
416   active_handles++;
417   return hd;
418 }
419
420 void
421 keydb_release (KEYDB_HANDLE hd)
422 {
423   int i;
424
425   if (!hd)
426     return;
427   assert (active_handles > 0);
428   active_handles--;
429
430   unlock_all (hd);
431   for (i=0; i < hd->used; i++)
432     {
433       switch (hd->active[i].type)
434         {
435         case KEYDB_RESOURCE_TYPE_NONE:
436           break;
437         case KEYDB_RESOURCE_TYPE_KEYBOX:
438           keybox_release (hd->active[i].u.kr);
439           break;
440         }
441     }
442
443     xfree (hd);
444 }
445
446
447 /* Return the name of the current resource.  This is function first
448    looks for the last found found, then for the current search
449    position, and last returns the first available resource.  The
450    returned string is only valid as long as the handle exists.  This
451    function does only return NULL if no handle is specified, in all
452    other error cases an empty string is returned.  */
453 const char *
454 keydb_get_resource_name (KEYDB_HANDLE hd)
455 {
456   int idx;
457   const char *s = NULL;
458
459   if (!hd)
460     return NULL;
461
462   if ( hd->found >= 0 && hd->found < hd->used)
463     idx = hd->found;
464   else if ( hd->current >= 0 && hd->current < hd->used)
465     idx = hd->current;
466   else
467     idx = 0;
468
469   switch (hd->active[idx].type)
470     {
471     case KEYDB_RESOURCE_TYPE_NONE:
472       s = NULL;
473       break;
474     case KEYDB_RESOURCE_TYPE_KEYBOX:
475       s = keybox_get_resource_name (hd->active[idx].u.kr);
476       break;
477     }
478
479   return s? s: "";
480 }
481
482 /* Switch the handle into ephemeral mode and return the orginal value. */
483 int
484 keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
485 {
486   int i;
487
488   if (!hd)
489     return 0;
490
491   yes = !!yes;
492   if (hd->is_ephemeral != yes)
493     {
494       for (i=0; i < hd->used; i++)
495         {
496           switch (hd->active[i].type)
497             {
498             case KEYDB_RESOURCE_TYPE_NONE:
499               break;
500             case KEYDB_RESOURCE_TYPE_KEYBOX:
501               keybox_set_ephemeral (hd->active[i].u.kr, yes);
502               break;
503             }
504         }
505     }
506
507   i = hd->is_ephemeral;
508   hd->is_ephemeral = yes;
509   return i;
510 }
511
512
513 /* If the keyring has not yet been locked, lock it now.  This
514    operation is required before any update operation; it is optional
515    for an insert operation.  The lock is released with
516    keydb_released. */
517 gpg_error_t
518 keydb_lock (KEYDB_HANDLE hd)
519 {
520   if (!hd)
521     return gpg_error (GPG_ERR_INV_HANDLE);
522   if (hd->locked)
523     return 0; /* Already locked. */
524   return lock_all (hd);
525 }
526
527
528 \f
529 static int
530 lock_all (KEYDB_HANDLE hd)
531 {
532   int i, rc = 0;
533
534   /* Fixme: This locking scheme may lead to deadlock if the resources
535      are not added in the same order by all processes.  We are
536      currently only allowing one resource so it is not a problem. */
537   for (i=0; i < hd->used; i++)
538     {
539       switch (hd->active[i].type)
540         {
541         case KEYDB_RESOURCE_TYPE_NONE:
542           break;
543         case KEYDB_RESOURCE_TYPE_KEYBOX:
544           if (hd->active[i].lockhandle)
545             rc = make_dotlock (hd->active[i].lockhandle, -1);
546           break;
547         }
548       if (rc)
549         break;
550     }
551
552     if (rc)
553       {
554         /* revert the already set locks */
555         for (i--; i >= 0; i--)
556           {
557             switch (hd->active[i].type)
558               {
559               case KEYDB_RESOURCE_TYPE_NONE:
560                 break;
561               case KEYDB_RESOURCE_TYPE_KEYBOX:
562                 if (hd->active[i].lockhandle)
563                   release_dotlock (hd->active[i].lockhandle);
564                 break;
565               }
566           }
567       }
568     else
569       hd->locked = 1;
570
571     /* make_dotlock () does not yet guarantee that errno is set, thus
572        we can't rely on the error reason and will simply use
573        EACCES. */
574     return rc? gpg_error (GPG_ERR_EACCES) : 0;
575 }
576
577 static void
578 unlock_all (KEYDB_HANDLE hd)
579 {
580   int i;
581
582   if (!hd->locked)
583     return;
584
585   for (i=hd->used-1; i >= 0; i--)
586     {
587       switch (hd->active[i].type)
588         {
589         case KEYDB_RESOURCE_TYPE_NONE:
590           break;
591         case KEYDB_RESOURCE_TYPE_KEYBOX:
592           if (hd->active[i].lockhandle)
593             release_dotlock (hd->active[i].lockhandle);
594           break;
595         }
596     }
597   hd->locked = 0;
598 }
599
600
601 \f
602 /* Push the last found state if any.  */
603 void
604 keydb_push_found_state (KEYDB_HANDLE hd)
605 {
606   if (!hd)
607     return;
608
609   if (hd->found < 0 || hd->found >= hd->used)
610     {
611       hd->saved_found = -1;
612       return;
613     }
614
615   switch (hd->active[hd->found].type)
616     {
617     case KEYDB_RESOURCE_TYPE_NONE:
618       break;
619     case KEYDB_RESOURCE_TYPE_KEYBOX:
620       keybox_push_found_state (hd->active[hd->found].u.kr);
621       break;
622     }
623
624   hd->saved_found = hd->found;
625   hd->found = -1;
626 }
627
628
629 /* Pop the last found state.  */
630 void
631 keydb_pop_found_state (KEYDB_HANDLE hd)
632 {
633   if (!hd)
634     return;
635
636   hd->found = hd->saved_found;
637   hd->saved_found = -1;
638   if (hd->found < 0 || hd->found >= hd->used)
639     return;
640
641   switch (hd->active[hd->found].type)
642     {
643     case KEYDB_RESOURCE_TYPE_NONE:
644       break;
645     case KEYDB_RESOURCE_TYPE_KEYBOX:
646       keybox_pop_found_state (hd->active[hd->found].u.kr);
647       break;
648     }
649 }
650
651
652 \f
653 #if 0
654 /*
655  * Return the last found keybox.  Caller must free it.
656  * The returned keyblock has the kbode flag bit 0 set for the node with
657  * the public key used to locate the keyblock or flag bit 1 set for
658  * the user ID node.
659  */
660 int
661 keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
662 {
663     int rc = 0;
664
665     if (!hd)
666         return G10ERR_INV_ARG;
667
668     if ( hd->found < 0 || hd->found >= hd->used)
669         return -1; /* nothing found */
670
671     switch (hd->active[hd->found].type) {
672       case KEYDB_RESOURCE_TYPE_NONE:
673         rc = G10ERR_GENERAL; /* oops */
674         break;
675       case KEYDB_RESOURCE_TYPE_KEYBOX:
676         rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
677         break;
678     }
679
680     return rc;
681 }
682
683 /*
684  * update the current keyblock with KB
685  */
686 int
687 keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
688 {
689     int rc = 0;
690
691     if (!hd)
692         return G10ERR_INV_ARG;
693
694     if ( hd->found < 0 || hd->found >= hd->used)
695         return -1; /* nothing found */
696
697     if( opt.dry_run )
698         return 0;
699
700     if (!hd->locked)
701       return gpg_error (GPG_ERR_NOT_LOCKED);
702
703     switch (hd->active[hd->found].type) {
704       case KEYDB_RESOURCE_TYPE_NONE:
705         rc = G10ERR_GENERAL; /* oops */
706         break;
707       case KEYDB_RESOURCE_TYPE_KEYBOX:
708         rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
709         break;
710     }
711
712     unlock_all (hd);
713     return rc;
714 }
715
716
717 /*
718  * Insert a new KB into one of the resources.
719  */
720 int
721 keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
722 {
723     int rc = -1;
724     int idx;
725
726     if (!hd)
727         return G10ERR_INV_ARG;
728
729     if( opt.dry_run )
730         return 0;
731
732     if ( hd->found >= 0 && hd->found < hd->used)
733         idx = hd->found;
734     else if ( hd->current >= 0 && hd->current < hd->used)
735         idx = hd->current;
736     else
737         return G10ERR_GENERAL;
738
739     rc = lock_all (hd);
740     if (rc)
741         return rc;
742
743     switch (hd->active[idx].type) {
744       case KEYDB_RESOURCE_TYPE_NONE:
745         rc = G10ERR_GENERAL; /* oops */
746         break;
747       case KEYDB_RESOURCE_TYPE_KEYBOX:
748         rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
749         break;
750     }
751
752     unlock_all (hd);
753     return rc;
754 }
755
756 #endif /*disabled code*/
757
758
759 \f
760 /*
761   Return the last found object.  Caller must free it.  The returned
762   keyblock has the kbode flag bit 0 set for the node with the public
763   key used to locate the keyblock or flag bit 1 set for the user ID
764   node.  */
765 int
766 keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
767 {
768   int rc = 0;
769
770   if (!hd)
771     return gpg_error (GPG_ERR_INV_VALUE);
772
773   if ( hd->found < 0 || hd->found >= hd->used)
774     return -1; /* nothing found */
775
776   switch (hd->active[hd->found].type)
777     {
778     case KEYDB_RESOURCE_TYPE_NONE:
779       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
780       break;
781     case KEYDB_RESOURCE_TYPE_KEYBOX:
782       rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
783       break;
784     }
785
786   return rc;
787 }
788
789 /* Return a flag of the last found object. WHICH is the flag requested;
790    it should be one of the KEYBOX_FLAG_ values.  If the operation is
791    successful, the flag value will be stored at the address given by
792    VALUE.  Return 0 on success or an error code. */
793 gpg_error_t
794 keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
795 {
796   int err = 0;
797
798   if (!hd)
799     return gpg_error (GPG_ERR_INV_VALUE);
800
801   if ( hd->found < 0 || hd->found >= hd->used)
802     return gpg_error (GPG_ERR_NOTHING_FOUND);
803
804   switch (hd->active[hd->found].type)
805     {
806     case KEYDB_RESOURCE_TYPE_NONE:
807       err = gpg_error (GPG_ERR_GENERAL); /* oops */
808       break;
809     case KEYDB_RESOURCE_TYPE_KEYBOX:
810       err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value);
811       break;
812     }
813
814   return err;
815 }
816
817 /* Set a flag of the last found object. WHICH is the flag to be set; it
818    should be one of the KEYBOX_FLAG_ values.  If the operation is
819    successful, the flag value will be stored in the keybox.  Note,
820    that some flag values can't be updated and thus may return an
821    error, some other flag values may be masked out before an update.
822    Returns 0 on success or an error code. */
823 gpg_error_t
824 keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
825 {
826   int err = 0;
827
828   if (!hd)
829     return gpg_error (GPG_ERR_INV_VALUE);
830
831   if ( hd->found < 0 || hd->found >= hd->used)
832     return gpg_error (GPG_ERR_NOTHING_FOUND);
833
834   if (!hd->locked)
835     return gpg_error (GPG_ERR_NOT_LOCKED);
836
837   switch (hd->active[hd->found].type)
838     {
839     case KEYDB_RESOURCE_TYPE_NONE:
840       err = gpg_error (GPG_ERR_GENERAL); /* oops */
841       break;
842     case KEYDB_RESOURCE_TYPE_KEYBOX:
843       err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value);
844       break;
845     }
846
847   return err;
848 }
849
850 /*
851  * Insert a new Certificate into one of the resources.
852  */
853 int
854 keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
855 {
856   int rc = -1;
857   int idx;
858   unsigned char digest[20];
859
860   if (!hd)
861     return gpg_error (GPG_ERR_INV_VALUE);
862
863   if (opt.dry_run)
864     return 0;
865
866   if ( hd->found >= 0 && hd->found < hd->used)
867     idx = hd->found;
868   else if ( hd->current >= 0 && hd->current < hd->used)
869     idx = hd->current;
870   else
871     return gpg_error (GPG_ERR_GENERAL);
872
873   if (!hd->locked)
874     return gpg_error (GPG_ERR_NOT_LOCKED);
875
876   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
877
878   switch (hd->active[idx].type)
879     {
880     case KEYDB_RESOURCE_TYPE_NONE:
881       rc = gpg_error (GPG_ERR_GENERAL);
882       break;
883     case KEYDB_RESOURCE_TYPE_KEYBOX:
884       rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
885       break;
886     }
887
888   unlock_all (hd);
889   return rc;
890 }
891
892
893
894 /* Update the current keyblock with KB.  */
895 int
896 keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
897 {
898   int rc = 0;
899   unsigned char digest[20];
900
901   if (!hd)
902     return gpg_error (GPG_ERR_INV_VALUE);
903
904   if ( hd->found < 0 || hd->found >= hd->used)
905     return -1; /* nothing found */
906
907   if (opt.dry_run)
908     return 0;
909
910   rc = lock_all (hd);
911   if (rc)
912     return rc;
913
914   gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
915
916   switch (hd->active[hd->found].type)
917     {
918     case KEYDB_RESOURCE_TYPE_NONE:
919       rc = gpg_error (GPG_ERR_GENERAL); /* oops */
920       break;
921     case KEYDB_RESOURCE_TYPE_KEYBOX:
922       rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
923       break;
924     }
925
926   unlock_all (hd);
927   return rc;
928 }
929
930
931 /*
932  * The current keyblock or cert will be deleted.
933  */
934 int
935 keydb_delete (KEYDB_HANDLE hd, int unlock)
936 {
937   int rc = -1;
938
939   if (!hd)
940     return gpg_error (GPG_ERR_INV_VALUE);
941
942   if ( hd->found < 0 || hd->found >= hd->used)
943     return -1; /* nothing found */
944
945   if( opt.dry_run )
946     return 0;
947
948   if (!hd->locked)
949     return gpg_error (GPG_ERR_NOT_LOCKED);
950
951   switch (hd->active[hd->found].type)
952     {
953     case KEYDB_RESOURCE_TYPE_NONE:
954       rc = gpg_error (GPG_ERR_GENERAL);
955       break;
956     case KEYDB_RESOURCE_TYPE_KEYBOX:
957       rc = keybox_delete (hd->active[hd->found].u.kr);
958       break;
959     }
960
961   if (unlock)
962     unlock_all (hd);
963   return rc;
964 }
965
966
967 \f
968 /*
969  * Locate the default writable key resource, so that the next
970  * operation (which is only relevant for inserts) will be done on this
971  * resource.
972  */
973 int
974 keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
975 {
976   int rc;
977
978   (void)reserved;
979
980   if (!hd)
981     return gpg_error (GPG_ERR_INV_VALUE);
982
983   rc = keydb_search_reset (hd); /* this does reset hd->current */
984   if (rc)
985     return rc;
986
987   for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
988     {
989       switch (hd->active[hd->current].type)
990         {
991         case KEYDB_RESOURCE_TYPE_NONE:
992           BUG();
993           break;
994         case KEYDB_RESOURCE_TYPE_KEYBOX:
995           if (keybox_is_writable (hd->active[hd->current].token))
996             return 0; /* found (hd->current is set to it) */
997           break;
998         }
999     }
1000
1001   return -1;
1002 }
1003
1004 /*
1005  * Rebuild the caches of all key resources.
1006  */
1007 void
1008 keydb_rebuild_caches (void)
1009 {
1010   int i;
1011
1012   for (i=0; i < used_resources; i++)
1013     {
1014       if (all_resources[i].secret)
1015         continue;
1016       switch (all_resources[i].type)
1017         {
1018         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
1019           break;
1020         case KEYDB_RESOURCE_TYPE_KEYBOX:
1021 /*            rc = keybox_rebuild_cache (all_resources[i].token); */
1022 /*            if (rc) */
1023 /*              log_error (_("failed to rebuild keybox cache: %s\n"), */
1024 /*                         g10_errstr (rc)); */
1025           break;
1026         }
1027     }
1028 }
1029
1030
1031
1032 /*
1033  * Start the next search on this handle right at the beginning
1034  */
1035 int
1036 keydb_search_reset (KEYDB_HANDLE hd)
1037 {
1038   int i, rc = 0;
1039
1040   if (!hd)
1041     return gpg_error (GPG_ERR_INV_VALUE);
1042
1043   hd->current = 0;
1044   hd->found = -1;
1045   /* and reset all resources */
1046   for (i=0; !rc && i < hd->used; i++)
1047     {
1048       switch (hd->active[i].type)
1049         {
1050         case KEYDB_RESOURCE_TYPE_NONE:
1051           break;
1052         case KEYDB_RESOURCE_TYPE_KEYBOX:
1053           rc = keybox_search_reset (hd->active[i].u.kr);
1054           break;
1055         }
1056     }
1057   return rc; /* fixme: we need to map error codes or share them with
1058                 all modules*/
1059 }
1060
1061 /*
1062  * Search through all keydb resources, starting at the current position,
1063  * for a keyblock which contains one of the keys described in the DESC array.
1064  */
1065 int
1066 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
1067 {
1068   int rc = -1;
1069
1070   if (!hd)
1071     return gpg_error (GPG_ERR_INV_VALUE);
1072
1073   while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
1074     {
1075       switch (hd->active[hd->current].type)
1076         {
1077         case KEYDB_RESOURCE_TYPE_NONE:
1078           BUG(); /* we should never see it here */
1079           break;
1080         case KEYDB_RESOURCE_TYPE_KEYBOX:
1081           rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
1082           break;
1083         }
1084       if (rc == -1) /* EOF -> switch to next resource */
1085         hd->current++;
1086       else if (!rc)
1087         hd->found = hd->current;
1088     }
1089
1090   return rc;
1091 }
1092
1093
1094 int
1095 keydb_search_first (KEYDB_HANDLE hd)
1096 {
1097   KEYDB_SEARCH_DESC desc;
1098
1099   memset (&desc, 0, sizeof desc);
1100   desc.mode = KEYDB_SEARCH_MODE_FIRST;
1101   return keydb_search (hd, &desc, 1);
1102 }
1103
1104 int
1105 keydb_search_next (KEYDB_HANDLE hd)
1106 {
1107   KEYDB_SEARCH_DESC desc;
1108
1109   memset (&desc, 0, sizeof desc);
1110   desc.mode = KEYDB_SEARCH_MODE_NEXT;
1111   return keydb_search (hd, &desc, 1);
1112 }
1113
1114 int
1115 keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
1116 {
1117   KEYDB_SEARCH_DESC desc;
1118
1119   (void)kid;
1120
1121   memset (&desc, 0, sizeof desc);
1122   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
1123 /*    desc.u.kid[0] = kid[0]; */
1124 /*    desc.u.kid[1] = kid[1]; */
1125   return keydb_search (hd, &desc, 1);
1126 }
1127
1128 int
1129 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
1130 {
1131   KEYDB_SEARCH_DESC desc;
1132
1133   memset (&desc, 0, sizeof desc);
1134   desc.mode = KEYDB_SEARCH_MODE_FPR;
1135   memcpy (desc.u.fpr, fpr, 20);
1136   return keydb_search (hd, &desc, 1);
1137 }
1138
1139 int
1140 keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
1141 {
1142   KEYDB_SEARCH_DESC desc;
1143   int rc;
1144
1145   memset (&desc, 0, sizeof desc);
1146   desc.mode = KEYDB_SEARCH_MODE_ISSUER;
1147   desc.u.name = issuer;
1148   rc = keydb_search (hd, &desc, 1);
1149   return rc;
1150 }
1151
1152 int
1153 keydb_search_issuer_sn (KEYDB_HANDLE hd,
1154                         const char *issuer, ksba_const_sexp_t serial)
1155 {
1156   KEYDB_SEARCH_DESC desc;
1157   int rc;
1158   const unsigned char *s;
1159
1160   memset (&desc, 0, sizeof desc);
1161   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
1162   s = serial;
1163   if (*s !='(')
1164     return gpg_error (GPG_ERR_INV_VALUE);
1165   s++;
1166   for (desc.snlen = 0; digitp (s); s++)
1167     desc.snlen = 10*desc.snlen + atoi_1 (s);
1168   if (*s !=':')
1169     return gpg_error (GPG_ERR_INV_VALUE);
1170   desc.sn = s+1;
1171   desc.u.name = issuer;
1172   rc = keydb_search (hd, &desc, 1);
1173   return rc;
1174 }
1175
1176 int
1177 keydb_search_subject (KEYDB_HANDLE hd, const char *name)
1178 {
1179   KEYDB_SEARCH_DESC desc;
1180   int rc;
1181
1182   memset (&desc, 0, sizeof desc);
1183   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
1184   desc.u.name = name;
1185   rc = keydb_search (hd, &desc, 1);
1186   return rc;
1187 }
1188
1189
1190 static int
1191 classify_user_id (const char *name,
1192                   KEYDB_SEARCH_DESC *desc,
1193                   int *force_exact )
1194 {
1195   const char *s;
1196   int hexprefix = 0;
1197   int hexlength;
1198   int mode = 0;
1199
1200   /* clear the structure so that the mode field is set to zero unless
1201    * we set it to the correct value right at the end of this function */
1202   memset (desc, 0, sizeof *desc);
1203   *force_exact = 0;
1204   /* Skip leading spaces.  Fixme: what about trailing white space? */
1205   for(s = name; *s && spacep (s); s++ )
1206     ;
1207
1208   switch (*s)
1209     {
1210     case 0:  /* empty string is an error */
1211       return 0;
1212
1213     case '.': /* an email address, compare from end */
1214       mode = KEYDB_SEARCH_MODE_MAILEND;
1215       s++;
1216       desc->u.name = s;
1217       break;
1218
1219     case '<': /* an email address */
1220       mode = KEYDB_SEARCH_MODE_MAIL;
1221       s++;
1222       desc->u.name = s;
1223       break;
1224
1225     case '@':  /* part of an email address */
1226       mode = KEYDB_SEARCH_MODE_MAILSUB;
1227       s++;
1228       desc->u.name = s;
1229       break;
1230
1231     case '=':  /* exact compare */
1232       mode = KEYDB_SEARCH_MODE_EXACT;
1233       s++;
1234       desc->u.name = s;
1235       break;
1236
1237     case '*':  /* case insensitive substring search */
1238       mode = KEYDB_SEARCH_MODE_SUBSTR;
1239       s++;
1240       desc->u.name = s;
1241       break;
1242
1243     case '+':  /* compare individual words */
1244       mode = KEYDB_SEARCH_MODE_WORDS;
1245       s++;
1246       desc->u.name = s;
1247       break;
1248
1249     case '/': /* subject's DN */
1250       s++;
1251       if (!*s || spacep (s))
1252         return 0; /* no DN or prefixed with a space */
1253       desc->u.name = s;
1254       mode = KEYDB_SEARCH_MODE_SUBJECT;
1255       break;
1256
1257     case '#':
1258       {
1259         const char *si;
1260
1261         s++;
1262         if ( *s == '/')
1263           { /* "#/" indicates an issuer's DN */
1264             s++;
1265             if (!*s || spacep (s))
1266               return 0; /* no DN or prefixed with a space */
1267             desc->u.name = s;
1268             mode = KEYDB_SEARCH_MODE_ISSUER;
1269           }
1270         else
1271           { /* serialnumber + optional issuer ID */
1272             for (si=s; *si && *si != '/'; si++)
1273               {
1274                 if (!strchr("01234567890abcdefABCDEF", *si))
1275                   return 0; /* invalid digit in serial number*/
1276               }
1277             desc->sn = (const unsigned char*)s;
1278             desc->snlen = -1;
1279             if (!*si)
1280               mode = KEYDB_SEARCH_MODE_SN;
1281             else
1282               {
1283                 s = si+1;
1284                 if (!*s || spacep (s))
1285                   return 0; /* no DN or prefixed with a space */
1286                 desc->u.name = s;
1287                 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
1288               }
1289           }
1290       }
1291       break;
1292
1293     case ':': /*Unified fingerprint */
1294       {
1295         const char *se, *si;
1296         int i;
1297
1298         se = strchr (++s,':');
1299         if (!se)
1300           return 0;
1301         for (i=0,si=s; si < se; si++, i++ )
1302           {
1303             if (!strchr("01234567890abcdefABCDEF", *si))
1304               return 0; /* invalid digit */
1305           }
1306         if (i != 32 && i != 40)
1307           return 0; /* invalid length of fpr*/
1308         for (i=0,si=s; si < se; i++, si +=2)
1309           desc->u.fpr[i] = hextobyte(si);
1310         for (; i < 20; i++)
1311           desc->u.fpr[i]= 0;
1312         s = se + 1;
1313         mode = KEYDB_SEARCH_MODE_FPR;
1314       }
1315       break;
1316
1317     case '&': /* Keygrip*/
1318       {
1319         if (hex2bin (s+1, desc->u.grip, 20) < 0)
1320           return 0; /* Invalid. */
1321         mode = KEYDB_SEARCH_MODE_KEYGRIP;
1322       }
1323       break;
1324
1325     default:
1326       if (s[0] == '0' && s[1] == 'x')
1327         {
1328           hexprefix = 1;
1329           s += 2;
1330         }
1331
1332       hexlength = strspn(s, "0123456789abcdefABCDEF");
1333       if (hexlength >= 8 && s[hexlength] =='!')
1334         {
1335           *force_exact = 1;
1336           hexlength++; /* just for the following check */
1337         }
1338
1339       /* check if a hexadecimal number is terminated by EOS or blank */
1340       if (hexlength && s[hexlength] && !spacep (s+hexlength))
1341         {
1342           if (hexprefix) /* a "0x" prefix without correct */
1343             return 0;    /* termination is an error */
1344           /* The first chars looked like a hex number, but really is
1345              not */
1346           hexlength = 0;
1347         }
1348
1349       if (*force_exact)
1350         hexlength--; /* remove the bang */
1351
1352       if (hexlength == 8
1353           || (!hexprefix && hexlength == 9 && *s == '0'))
1354         { /* short keyid */
1355           unsigned long kid;
1356           if (hexlength == 9)
1357             s++;
1358           kid = strtoul( s, NULL, 16 );
1359           desc->u.kid[4] = kid >> 24;
1360           desc->u.kid[5] = kid >> 16;
1361           desc->u.kid[6] = kid >>  8;
1362           desc->u.kid[7] = kid;
1363           mode = KEYDB_SEARCH_MODE_SHORT_KID;
1364         }
1365       else if (hexlength == 16
1366                || (!hexprefix && hexlength == 17 && *s == '0'))
1367         { /* complete keyid */
1368           unsigned long kid0, kid1;
1369           char buf[9];
1370           if (hexlength == 17)
1371             s++;
1372           mem2str(buf, s, 9 );
1373           kid0 = strtoul (buf, NULL, 16);
1374           kid1 = strtoul (s+8, NULL, 16);
1375           desc->u.kid[0] = kid0 >> 24;
1376           desc->u.kid[1] = kid0 >> 16;
1377           desc->u.kid[2] = kid0 >>  8;
1378           desc->u.kid[3] = kid0;
1379           desc->u.kid[4] = kid1 >> 24;
1380           desc->u.kid[5] = kid1 >> 16;
1381           desc->u.kid[6] = kid1 >>  8;
1382           desc->u.kid[7] = kid1;
1383           mode = KEYDB_SEARCH_MODE_LONG_KID;
1384         }
1385       else if (hexlength == 32
1386                || (!hexprefix && hexlength == 33 && *s == '0'))
1387         { /* md5 fingerprint */
1388           int i;
1389           if (hexlength == 33)
1390             s++;
1391           memset(desc->u.fpr+16, 0, 4);
1392           for (i=0; i < 16; i++, s+=2)
1393             {
1394               int c = hextobyte(s);
1395               if (c == -1)
1396                 return 0;
1397               desc->u.fpr[i] = c;
1398             }
1399           mode = KEYDB_SEARCH_MODE_FPR16;
1400         }
1401       else if (hexlength == 40
1402                || (!hexprefix && hexlength == 41 && *s == '0'))
1403         { /* sha1/rmd160 fingerprint */
1404           int i;
1405           if (hexlength == 41)
1406             s++;
1407           for (i=0; i < 20; i++, s+=2)
1408             {
1409               int c = hextobyte(s);
1410               if (c == -1)
1411                 return 0;
1412               desc->u.fpr[i] = c;
1413             }
1414           mode = KEYDB_SEARCH_MODE_FPR20;
1415         }
1416       else if (!hexprefix)
1417         {
1418           /* The fingerprint in an X.509 listing is often delimited by
1419              colons, so we try to single this case out. */
1420           mode = 0;
1421           hexlength = strspn (s, ":0123456789abcdefABCDEF");
1422           if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
1423             {
1424               int i;
1425
1426               for (i=0; i < 20; i++, s += 3)
1427                 {
1428                   int c = hextobyte(s);
1429                   if (c == -1 || (i < 19 && s[2] != ':'))
1430                     break;
1431                   desc->u.fpr[i] = c;
1432                 }
1433               if (i == 20)
1434                 mode = KEYDB_SEARCH_MODE_FPR20;
1435             }
1436           if (!mode) /* default is substring search */
1437             {
1438               *force_exact = 0;
1439               desc->u.name = s;
1440               mode = KEYDB_SEARCH_MODE_SUBSTR;
1441             }
1442         }
1443       else
1444         { /* hex number with a prefix but a wrong length */
1445           return 0;
1446         }
1447     }
1448
1449   desc->mode = mode;
1450   return mode;
1451 }
1452
1453
1454 int
1455 keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
1456 {
1457   int dummy;
1458   KEYDB_SEARCH_DESC dummy_desc;
1459
1460   if (!desc)
1461     desc = &dummy_desc;
1462
1463   if (!classify_user_id (name, desc, &dummy))
1464     return gpg_error (GPG_ERR_INV_NAME);
1465   return 0;
1466 }
1467
1468 \f
1469 /* Store the certificate in the key DB but make sure that it does not
1470    already exists.  We do this simply by comparing the fingerprint.
1471    If EXISTED is not NULL it will be set to true if the certificate
1472    was already in the DB. */
1473 int
1474 keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed)
1475 {
1476   KEYDB_HANDLE kh;
1477   int rc;
1478   unsigned char fpr[20];
1479
1480   if (existed)
1481     *existed = 0;
1482
1483   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1484     {
1485       log_error (_("failed to get the fingerprint\n"));
1486       return gpg_error (GPG_ERR_GENERAL);
1487     }
1488
1489   kh = keydb_new (0);
1490   if (!kh)
1491     {
1492       log_error (_("failed to allocate keyDB handle\n"));
1493       return gpg_error (GPG_ERR_ENOMEM);;
1494     }
1495
1496   if (ephemeral)
1497     keydb_set_ephemeral (kh, 1);
1498
1499   rc = lock_all (kh);
1500   if (rc)
1501     return rc;
1502
1503   rc = keydb_search_fpr (kh, fpr);
1504   if (rc != -1)
1505     {
1506       keydb_release (kh);
1507       if (!rc)
1508         {
1509           if (existed)
1510             *existed = 1;
1511           return 0; /* okay */
1512         }
1513       log_error (_("problem looking for existing certificate: %s\n"),
1514                  gpg_strerror (rc));
1515       return rc;
1516     }
1517
1518   rc = keydb_locate_writable (kh, 0);
1519   if (rc)
1520     {
1521       log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
1522       keydb_release (kh);
1523       return rc;
1524     }
1525
1526   rc = keydb_insert_cert (kh, cert);
1527   if (rc)
1528     {
1529       log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
1530       keydb_release (kh);
1531       return rc;
1532     }
1533   keydb_release (kh);
1534   return 0;
1535 }
1536
1537
1538 /* This is basically keydb_set_flags but it implements a complete
1539    transaction by locating the certificate in the DB and updating the
1540    flags. */
1541 gpg_error_t
1542 keydb_set_cert_flags (ksba_cert_t cert, int ephemeral,
1543                       int which, int idx,
1544                       unsigned int mask, unsigned int value)
1545 {
1546   KEYDB_HANDLE kh;
1547   gpg_error_t err;
1548   unsigned char fpr[20];
1549   unsigned int old_value;
1550
1551   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
1552     {
1553       log_error (_("failed to get the fingerprint\n"));
1554       return gpg_error (GPG_ERR_GENERAL);
1555     }
1556
1557   kh = keydb_new (0);
1558   if (!kh)
1559     {
1560       log_error (_("failed to allocate keyDB handle\n"));
1561       return gpg_error (GPG_ERR_ENOMEM);;
1562     }
1563
1564   if (ephemeral)
1565     keydb_set_ephemeral (kh, 1);
1566
1567   err = keydb_lock (kh);
1568   if (err)
1569     {
1570       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1571       keydb_release (kh);
1572       return err;
1573     }
1574
1575   err = keydb_search_fpr (kh, fpr);
1576   if (err)
1577     {
1578       if (err == -1)
1579         err = gpg_error (GPG_ERR_NOT_FOUND);
1580       else
1581         log_error (_("problem re-searching certificate: %s\n"),
1582                    gpg_strerror (err));
1583       keydb_release (kh);
1584       return err;
1585     }
1586
1587   err = keydb_get_flags (kh, which, idx, &old_value);
1588   if (err)
1589     {
1590       log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
1591       keydb_release (kh);
1592       return err;
1593     }
1594
1595   value = ((old_value & ~mask) | (value & mask));
1596
1597   if (value != old_value)
1598     {
1599       err = keydb_set_flags (kh, which, idx, value);
1600       if (err)
1601         {
1602           log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1603           keydb_release (kh);
1604           return err;
1605         }
1606     }
1607
1608   keydb_release (kh);
1609   return 0;
1610 }
1611
1612
1613 /* Reset all the certificate flags we have stored with the certificates
1614    for performance reasons. */
1615 void
1616 keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
1617 {
1618   gpg_error_t err;
1619   KEYDB_HANDLE hd = NULL;
1620   KEYDB_SEARCH_DESC *desc = NULL;
1621   int ndesc;
1622   strlist_t sl;
1623   int rc=0;
1624   unsigned int old_value, value;
1625
1626   (void)ctrl;
1627
1628   hd = keydb_new (0);
1629   if (!hd)
1630     {
1631       log_error ("keydb_new failed\n");
1632       goto leave;
1633     }
1634
1635   if (!names)
1636     ndesc = 1;
1637   else
1638     {
1639       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
1640         ;
1641     }
1642
1643   desc = xtrycalloc (ndesc, sizeof *desc);
1644   if (!ndesc)
1645     {
1646       log_error ("allocating memory failed: %s\n",
1647                  gpg_strerror (out_of_core ()));
1648       goto leave;
1649     }
1650
1651   if (!names)
1652     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1653   else
1654     {
1655       for (ndesc=0, sl=names; sl; sl = sl->next)
1656         {
1657           rc = keydb_classify_name (sl->d, desc+ndesc);
1658           if (rc)
1659             {
1660               log_error ("key `%s' not found: %s\n",
1661                          sl->d, gpg_strerror (rc));
1662               rc = 0;
1663             }
1664           else
1665             ndesc++;
1666         }
1667     }
1668
1669   err = keydb_lock (hd);
1670   if (err)
1671     {
1672       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
1673       goto leave;
1674     }
1675
1676   while (!(rc = keydb_search (hd, desc, ndesc)))
1677     {
1678       if (!names)
1679         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1680
1681       err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
1682       if (err)
1683         {
1684           log_error (_("error getting stored flags: %s\n"),
1685                      gpg_strerror (err));
1686           goto leave;
1687         }
1688
1689       value = (old_value & ~VALIDITY_REVOKED);
1690       if (value != old_value)
1691         {
1692           err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
1693           if (err)
1694             {
1695               log_error (_("error storing flags: %s\n"), gpg_strerror (err));
1696               goto leave;
1697             }
1698         }
1699     }
1700   if (rc && rc != -1)
1701     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1702
1703  leave:
1704   xfree (desc);
1705   keydb_release (hd);
1706 }
1707
1708