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