LCOV - code coverage report
Current view: top level - sm - keydb.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 207 570 36.3 %
Date: 2015-11-05 17:10:59 Functions: 13 32 40.6 %

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

Generated by: LCOV version 1.11