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

Generated by: LCOV version 1.11