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: 2016-11-29 15:00:56 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 <https://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             :   dotlock_t lockhandle;
      51             : };
      52             : 
      53             : static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
      54             : static int used_resources;
      55             : 
      56             : /* Whether we have successfully registered any resource.  */
      57             : static int any_registered;
      58             : 
      59             : 
      60             : struct keydb_handle {
      61             :   int locked;
      62             :   int found;
      63             :   int saved_found;
      64             :   int current;
      65             :   int is_ephemeral;
      66             :   int used; /* items in active */
      67             :   struct resource_item active[MAX_KEYDB_RESOURCES];
      68             : };
      69             : 
      70             : 
      71             : static int lock_all (KEYDB_HANDLE hd);
      72             : static void unlock_all (KEYDB_HANDLE hd);
      73             : 
      74             : 
      75             : static void
      76           0 : try_make_homedir (const char *fname)
      77             : {
      78           0 :   const char *defhome = standard_homedir ();
      79             : 
      80             :   /* Create the directory only if the supplied directory name is the
      81             :      same as the default one.  This way we avoid to create arbitrary
      82             :      directories when a non-default home directory is used.  To cope
      83             :      with HOME, we do compare only the suffix if we see that the
      84             :      default homedir does start with a tilde.  */
      85           0 :   if ( opt.dry_run || opt.no_homedir_creation )
      86           0 :     return;
      87             : 
      88           0 :   if (
      89             : #ifdef HAVE_W32_SYSTEM
      90             :       ( !compare_filenames (fname, defhome) )
      91             : #else
      92           0 :       ( *defhome == '~'
      93           0 :         && (strlen(fname) >= strlen (defhome+1)
      94           0 :             && !strcmp(fname+strlen(fname)-strlen(defhome+1), defhome+1 ) ))
      95           0 :       || (*defhome != '~'  && !compare_filenames( fname, defhome ) )
      96             : #endif
      97             :       )
      98             :     {
      99           0 :       if (gnupg_mkdir (fname, "-rwx"))
     100           0 :         log_info (_("can't create directory '%s': %s\n"),
     101           0 :                   fname, strerror(errno) );
     102           0 :       else if (!opt.quiet )
     103           0 :         log_info (_("directory '%s' created\n"), fname);
     104             :     }
     105             : }
     106             : 
     107             : 
     108             : /* Handle the creation of a keybox if it does not yet exist.  Take
     109             :    into acount that other processes might have the keybox already
     110             :    locked.  This lock check does not work if the directory itself is
     111             :    not yet available.  If R_CREATED is not NULL it will be set to true
     112             :    if the function created a new keybox.  */
     113             : static gpg_error_t
     114           3 : maybe_create_keybox (char *filename, int force, int *r_created)
     115             : {
     116           3 :   dotlock_t lockhd = NULL;
     117             :   FILE *fp;
     118             :   int rc;
     119             :   mode_t oldmask;
     120             :   char *last_slash_in_filename;
     121             :   int save_slash;
     122             : 
     123           3 :   if (r_created)
     124           3 :     *r_created = 0;
     125             : 
     126             :   /* A quick test whether the filename already exists. */
     127           3 :   if (!access (filename, F_OK))
     128           2 :     return !access (filename, R_OK)? 0 : gpg_error (GPG_ERR_EACCES);
     129             : 
     130             :   /* If we don't want to create a new file at all, there is no need to
     131             :      go any further - bail out right here.  */
     132           1 :   if (!force)
     133           0 :     return gpg_error (GPG_ERR_ENOENT);
     134             : 
     135             :   /* First of all we try to create the home directory.  Note, that we
     136             :      don't do any locking here because any sane application of gpg
     137             :      would create the home directory by itself and not rely on gpg's
     138             :      tricky auto-creation which is anyway only done for some home
     139             :      directory name patterns. */
     140           1 :   last_slash_in_filename = strrchr (filename, DIRSEP_C);
     141             : #if HAVE_W32_SYSTEM
     142             :   {
     143             :     /* Windows may either have a slash or a backslash.  Take care of it.  */
     144             :     char *p = strrchr (filename, '/');
     145             :     if (!last_slash_in_filename || p > last_slash_in_filename)
     146             :       last_slash_in_filename = p;
     147             :   }
     148             : #endif /*HAVE_W32_SYSTEM*/
     149           1 :   if (!last_slash_in_filename)
     150           0 :     return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
     151             :                                            not happen though.  */
     152           1 :   save_slash = *last_slash_in_filename;
     153           1 :   *last_slash_in_filename = 0;
     154           1 :   if (access(filename, F_OK))
     155             :     {
     156             :       static int tried;
     157             : 
     158           0 :       if (!tried)
     159             :         {
     160           0 :           tried = 1;
     161           0 :           try_make_homedir (filename);
     162             :         }
     163           0 :       if (access (filename, F_OK))
     164             :         {
     165           0 :           rc = gpg_error_from_syserror ();
     166           0 :           *last_slash_in_filename = save_slash;
     167           0 :           goto leave;
     168             :         }
     169             :     }
     170           1 :   *last_slash_in_filename = save_slash;
     171             : 
     172             :   /* To avoid races with other instances of gpg trying to create or
     173             :      update the keybox (it is removed during an update for a short
     174             :      time), we do the next stuff in a locked state. */
     175           1 :   lockhd = dotlock_create (filename, 0);
     176           1 :   if (!lockhd)
     177             :     {
     178             :       /* A reason for this to fail is that the directory is not
     179             :          writable. However, this whole locking stuff does not make
     180             :          sense if this is the case. An empty non-writable directory
     181             :          with no keyring is not really useful at all. */
     182           0 :       if (opt.verbose)
     183           0 :         log_info ("can't allocate lock for '%s'\n", filename );
     184             : 
     185           0 :       if (!force)
     186           0 :         return gpg_error (GPG_ERR_ENOENT);
     187             :       else
     188           0 :         return gpg_error (GPG_ERR_GENERAL);
     189             :     }
     190             : 
     191           1 :   if ( dotlock_take (lockhd, -1) )
     192             :     {
     193             :       /* This is something bad.  Probably a stale lockfile.  */
     194           0 :       log_info ("can't lock '%s'\n", filename);
     195           0 :       rc = gpg_error (GPG_ERR_GENERAL);
     196           0 :       goto leave;
     197             :     }
     198             : 
     199             :   /* Now the real test while we are locked. */
     200           1 :   if (!access(filename, F_OK))
     201             :     {
     202           0 :       rc = 0;  /* Okay, we may access the file now.  */
     203           0 :       goto leave;
     204             :     }
     205             : 
     206             :   /* The file does not yet exist, create it now. */
     207           1 :   oldmask = umask (077);
     208           1 :   fp = fopen (filename, "w");
     209           1 :   if (!fp)
     210             :     {
     211           0 :       rc = gpg_error_from_syserror ();
     212           0 :       umask (oldmask);
     213           0 :       log_error (_("error creating keybox '%s': %s\n"),
     214             :                  filename, gpg_strerror (rc));
     215           0 :       goto leave;
     216             :     }
     217           1 :   umask (oldmask);
     218             : 
     219             :   /* Make sure that at least one record is in a new keybox file, so
     220             :      that the detection magic for OpenPGP keyboxes works the next time
     221             :      it is used.  */
     222           1 :   rc = _keybox_write_header_blob (fp, 0);
     223           1 :   if (rc)
     224             :     {
     225           0 :       fclose (fp);
     226           0 :       log_error (_("error creating keybox '%s': %s\n"),
     227             :                  filename, gpg_strerror (rc));
     228           0 :       goto leave;
     229             :     }
     230             : 
     231           1 :   if (!opt.quiet)
     232           1 :     log_info (_("keybox '%s' created\n"), filename);
     233           1 :   if (r_created)
     234           1 :     *r_created = 1;
     235             : 
     236           1 :   fclose (fp);
     237           1 :   rc = 0;
     238             : 
     239             :  leave:
     240           1 :   if (lockhd)
     241             :     {
     242           1 :       dotlock_release (lockhd);
     243           1 :       dotlock_destroy (lockhd);
     244             :     }
     245           1 :   return rc;
     246             : }
     247             : 
     248             : 
     249             : /*
     250             :  * Register a resource (which currently may only be a keybox file).
     251             :  * The first keybox which is added by this function is created if it
     252             :  * does not exist.  If AUTO_CREATED is not NULL it will be set to true
     253             :  * if the function has created a new keybox.
     254             :  */
     255             : gpg_error_t
     256           3 : keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created)
     257             : {
     258           3 :   const char *resname = url;
     259           3 :   char *filename = NULL;
     260           3 :   gpg_error_t err = 0;
     261           3 :   KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
     262             : 
     263           3 :   if (auto_created)
     264           3 :     *auto_created = 0;
     265             : 
     266             :   /* Do we have an URL?
     267             :      gnupg-kbx:filename := this is a plain keybox
     268             :      filename := See what is is, but create as plain keybox.
     269             :   */
     270           3 :   if (strlen (resname) > 10)
     271             :     {
     272           3 :       if (!strncmp (resname, "gnupg-kbx:", 10) )
     273             :         {
     274           0 :           rt = KEYDB_RESOURCE_TYPE_KEYBOX;
     275           0 :           resname += 10;
     276             :         }
     277             : #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
     278           3 :       else if (strchr (resname, ':'))
     279             :         {
     280           0 :           log_error ("invalid key resource URL '%s'\n", url );
     281           0 :           err = gpg_error (GPG_ERR_GENERAL);
     282           0 :           goto leave;
     283             :         }
     284             : #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
     285             :     }
     286             : 
     287           3 :   if (*resname != DIRSEP_C )
     288             :     { /* do tilde expansion etc */
     289           3 :       if (strchr(resname, DIRSEP_C) )
     290           0 :         filename = make_filename (resname, NULL);
     291             :       else
     292           3 :         filename = make_filename (gnupg_homedir (), resname, NULL);
     293             :     }
     294             :   else
     295           0 :     filename = xstrdup (resname);
     296             : 
     297           3 :   if (!force)
     298           3 :     force = !any_registered;
     299             : 
     300             :   /* see whether we can determine the filetype */
     301           3 :   if (rt == KEYDB_RESOURCE_TYPE_NONE)
     302             :     {
     303           3 :       FILE *fp = fopen( filename, "rb" );
     304             : 
     305           3 :       if (fp)
     306             :         {
     307             :           u32 magic;
     308             : 
     309             :           /* FIXME: check for the keybox magic */
     310           2 :           if (fread (&magic, 4, 1, fp) == 1 )
     311             :             {
     312           2 :               if (magic == 0x13579ace || magic == 0xce9a5713)
     313             :                 ; /* GDBM magic - no more support */
     314             :               else
     315           2 :                 rt = KEYDB_RESOURCE_TYPE_KEYBOX;
     316             :             }
     317             :           else /* maybe empty: assume keybox */
     318           0 :             rt = KEYDB_RESOURCE_TYPE_KEYBOX;
     319           2 :           fclose (fp);
     320             :         }
     321             :       else /* no file yet: create keybox */
     322           1 :         rt = KEYDB_RESOURCE_TYPE_KEYBOX;
     323             :     }
     324             : 
     325           3 :   switch (rt)
     326             :     {
     327             :     case KEYDB_RESOURCE_TYPE_NONE:
     328           0 :       log_error ("unknown type of key resource '%s'\n", url );
     329           0 :       err = gpg_error (GPG_ERR_GENERAL);
     330           0 :       goto leave;
     331             : 
     332             :     case KEYDB_RESOURCE_TYPE_KEYBOX:
     333           3 :       err = maybe_create_keybox (filename, force, auto_created);
     334           3 :       if (err)
     335           0 :         goto leave;
     336             :       /* Now register the file */
     337             :       {
     338             :         void *token;
     339             : 
     340           3 :         err = keybox_register_file (filename, 0, &token);
     341           3 :         if (gpg_err_code (err) == GPG_ERR_EEXIST)
     342             :           ; /* Already registered - ignore.  */
     343           3 :         else if (err)
     344             :           ; /* Other error.  */
     345           3 :         else if (used_resources >= MAX_KEYDB_RESOURCES)
     346           0 :           err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
     347             :         else
     348             :           {
     349           3 :             all_resources[used_resources].type = rt;
     350           3 :             all_resources[used_resources].u.kr = NULL; /* Not used here */
     351           3 :             all_resources[used_resources].token = token;
     352             : 
     353           3 :             all_resources[used_resources].lockhandle
     354           3 :               = dotlock_create (filename, 0);
     355           3 :             if (!all_resources[used_resources].lockhandle)
     356           0 :               log_fatal ( _("can't create lock for '%s'\n"), filename);
     357             : 
     358             :             /* Do a compress run if needed and the file is not locked. */
     359           3 :             if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
     360             :               {
     361           3 :                 KEYBOX_HANDLE kbxhd = keybox_new_x509 (token, 0);
     362             : 
     363           3 :                 if (kbxhd)
     364             :                   {
     365           3 :                     keybox_compress (kbxhd);
     366           3 :                     keybox_release (kbxhd);
     367             :                   }
     368           3 :                 dotlock_release (all_resources[used_resources].lockhandle);
     369             :               }
     370             : 
     371           3 :             used_resources++;
     372             :           }
     373             :       }
     374           3 :       break;
     375             : 
     376             :     default:
     377           0 :       log_error ("resource type of '%s' not supported\n", url);
     378           0 :       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
     379           0 :       goto leave;
     380             :     }
     381             : 
     382             :   /* fixme: check directory permissions and print a warning */
     383             : 
     384             :  leave:
     385           3 :   if (err)
     386             :     {
     387           0 :       log_error ("keyblock resource '%s': %s\n", filename, gpg_strerror (err));
     388           0 :       gpgsm_status_with_error (ctrl, STATUS_ERROR,
     389             :                                "add_keyblock_resource", err);
     390             :     }
     391             :   else
     392           3 :     any_registered = 1;
     393           3 :   xfree (filename);
     394           3 :   return err;
     395             : }
     396             : 
     397             : 
     398             : KEYDB_HANDLE
     399           9 : keydb_new (void)
     400             : {
     401             :   KEYDB_HANDLE hd;
     402             :   int i, j;
     403             : 
     404           9 :   hd = xcalloc (1, sizeof *hd);
     405           9 :   hd->found = -1;
     406           9 :   hd->saved_found = -1;
     407             : 
     408           9 :   assert (used_resources <= MAX_KEYDB_RESOURCES);
     409          18 :   for (i=j=0; i < used_resources; i++)
     410             :     {
     411           9 :       switch (all_resources[i].type)
     412             :         {
     413             :         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
     414           0 :           break;
     415             :         case KEYDB_RESOURCE_TYPE_KEYBOX:
     416           9 :           hd->active[j].type   = all_resources[i].type;
     417           9 :           hd->active[j].token  = all_resources[i].token;
     418           9 :           hd->active[j].lockhandle = all_resources[i].lockhandle;
     419           9 :           hd->active[j].u.kr = keybox_new_x509 (all_resources[i].token, 0);
     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 :       switch (all_resources[i].type)
     923             :         {
     924             :         case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
     925           0 :           break;
     926             :         case KEYDB_RESOURCE_TYPE_KEYBOX:
     927             : /*            rc = keybox_rebuild_cache (all_resources[i].token); */
     928             : /*            if (rc) */
     929             : /*              log_error (_("failed to rebuild keybox cache: %s\n"), */
     930             : /*                         g10_errstr (rc)); */
     931           0 :           break;
     932             :         }
     933             :     }
     934           0 : }
     935             : 
     936             : 
     937             : 
     938             : /*
     939             :  * Start the next search on this handle right at the beginning
     940             :  */
     941             : gpg_error_t
     942           3 : keydb_search_reset (KEYDB_HANDLE hd)
     943             : {
     944             :   int i;
     945           3 :   gpg_error_t rc = 0;
     946             : 
     947           3 :   if (!hd)
     948           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     949             : 
     950           3 :   hd->current = 0;
     951           3 :   hd->found = -1;
     952             :   /* and reset all resources */
     953           6 :   for (i=0; !rc && i < hd->used; i++)
     954             :     {
     955           3 :       switch (hd->active[i].type)
     956             :         {
     957             :         case KEYDB_RESOURCE_TYPE_NONE:
     958           0 :           break;
     959             :         case KEYDB_RESOURCE_TYPE_KEYBOX:
     960           3 :           rc = keybox_search_reset (hd->active[i].u.kr);
     961           3 :           break;
     962             :         }
     963             :     }
     964           3 :   return rc;
     965             : }
     966             : 
     967             : /*
     968             :  * Search through all keydb resources, starting at the current position,
     969             :  * for a keyblock which contains one of the keys described in the DESC array.
     970             :  */
     971             : int
     972           3 : keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
     973             :               KEYDB_SEARCH_DESC *desc, size_t ndesc)
     974             : {
     975           3 :   int rc = -1;
     976             :   unsigned long skipped;
     977             : 
     978           3 :   if (!hd)
     979           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     980             : 
     981           3 :   if (!any_registered)
     982             :     {
     983           0 :       gpgsm_status_with_error (ctrl, STATUS_ERROR, "keydb_search",
     984             :                                gpg_error (GPG_ERR_KEYRING_OPEN));
     985           0 :       return gpg_error (GPG_ERR_NOT_FOUND);
     986             :     }
     987             : 
     988           9 :   while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
     989             :     {
     990           3 :       switch (hd->active[hd->current].type)
     991             :         {
     992             :         case KEYDB_RESOURCE_TYPE_NONE:
     993           0 :           BUG(); /* we should never see it here */
     994             :           break;
     995             :         case KEYDB_RESOURCE_TYPE_KEYBOX:
     996           3 :           rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc,
     997             :                               KEYBOX_BLOBTYPE_X509,
     998             :                               NULL, &skipped);
     999           3 :           break;
    1000             :         }
    1001           3 :       if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
    1002             :         { /* EOF -> switch to next resource */
    1003           3 :           hd->current++;
    1004             :         }
    1005           0 :       else if (!rc)
    1006           0 :         hd->found = hd->current;
    1007             :     }
    1008             : 
    1009           3 :   return rc;
    1010             : }
    1011             : 
    1012             : 
    1013             : int
    1014           0 : keydb_search_first (ctrl_t ctrl, KEYDB_HANDLE hd)
    1015             : {
    1016             :   KEYDB_SEARCH_DESC desc;
    1017             : 
    1018           0 :   memset (&desc, 0, sizeof desc);
    1019           0 :   desc.mode = KEYDB_SEARCH_MODE_FIRST;
    1020           0 :   return keydb_search (ctrl, hd, &desc, 1);
    1021             : }
    1022             : 
    1023             : int
    1024           0 : keydb_search_next (ctrl_t ctrl, KEYDB_HANDLE hd)
    1025             : {
    1026             :   KEYDB_SEARCH_DESC desc;
    1027             : 
    1028           0 :   memset (&desc, 0, sizeof desc);
    1029           0 :   desc.mode = KEYDB_SEARCH_MODE_NEXT;
    1030           0 :   return keydb_search (ctrl, hd, &desc, 1);
    1031             : }
    1032             : 
    1033             : int
    1034           0 : keydb_search_kid (ctrl_t ctrl, KEYDB_HANDLE hd, u32 *kid)
    1035             : {
    1036             :   KEYDB_SEARCH_DESC desc;
    1037             : 
    1038             :   (void)kid;
    1039             : 
    1040           0 :   memset (&desc, 0, sizeof desc);
    1041           0 :   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
    1042           0 :   desc.u.kid[0] = kid[0];
    1043           0 :   desc.u.kid[1] = kid[1];
    1044           0 :   return keydb_search (ctrl, hd, &desc, 1);
    1045             : }
    1046             : 
    1047             : int
    1048           3 : keydb_search_fpr (ctrl_t ctrl, KEYDB_HANDLE hd, const byte *fpr)
    1049             : {
    1050             :   KEYDB_SEARCH_DESC desc;
    1051             : 
    1052           3 :   memset (&desc, 0, sizeof desc);
    1053           3 :   desc.mode = KEYDB_SEARCH_MODE_FPR;
    1054           3 :   memcpy (desc.u.fpr, fpr, 20);
    1055           3 :   return keydb_search (ctrl, hd, &desc, 1);
    1056             : }
    1057             : 
    1058             : int
    1059           0 : keydb_search_issuer (ctrl_t ctrl, KEYDB_HANDLE hd, const char *issuer)
    1060             : {
    1061             :   KEYDB_SEARCH_DESC desc;
    1062             :   int rc;
    1063             : 
    1064           0 :   memset (&desc, 0, sizeof desc);
    1065           0 :   desc.mode = KEYDB_SEARCH_MODE_ISSUER;
    1066           0 :   desc.u.name = issuer;
    1067           0 :   rc = keydb_search (ctrl, hd, &desc, 1);
    1068           0 :   return rc;
    1069             : }
    1070             : 
    1071             : int
    1072           0 : keydb_search_issuer_sn (ctrl_t ctrl, KEYDB_HANDLE hd,
    1073             :                         const char *issuer, ksba_const_sexp_t serial)
    1074             : {
    1075             :   KEYDB_SEARCH_DESC desc;
    1076             :   int rc;
    1077             :   const unsigned char *s;
    1078             : 
    1079           0 :   memset (&desc, 0, sizeof desc);
    1080           0 :   desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
    1081           0 :   s = serial;
    1082           0 :   if (*s !='(')
    1083           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1084           0 :   s++;
    1085           0 :   for (desc.snlen = 0; digitp (s); s++)
    1086           0 :     desc.snlen = 10*desc.snlen + atoi_1 (s);
    1087           0 :   if (*s !=':')
    1088           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1089           0 :   desc.sn = s+1;
    1090           0 :   desc.u.name = issuer;
    1091           0 :   rc = keydb_search (ctrl, hd, &desc, 1);
    1092           0 :   return rc;
    1093             : }
    1094             : 
    1095             : int
    1096           0 : keydb_search_subject (ctrl_t ctrl, KEYDB_HANDLE hd, const char *name)
    1097             : {
    1098             :   KEYDB_SEARCH_DESC desc;
    1099             :   int rc;
    1100             : 
    1101           0 :   memset (&desc, 0, sizeof desc);
    1102           0 :   desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
    1103           0 :   desc.u.name = name;
    1104           0 :   rc = keydb_search (ctrl, hd, &desc, 1);
    1105           0 :   return rc;
    1106             : }
    1107             : 
    1108             : 
    1109             : 
    1110             : /* Store the certificate in the key DB but make sure that it does not
    1111             :    already exists.  We do this simply by comparing the fingerprint.
    1112             :    If EXISTED is not NULL it will be set to true if the certificate
    1113             :    was already in the DB. */
    1114             : int
    1115           3 : keydb_store_cert (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, int *existed)
    1116             : {
    1117             :   KEYDB_HANDLE kh;
    1118             :   int rc;
    1119             :   unsigned char fpr[20];
    1120             : 
    1121           3 :   if (existed)
    1122           3 :     *existed = 0;
    1123             : 
    1124           3 :   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
    1125             :     {
    1126           0 :       log_error (_("failed to get the fingerprint\n"));
    1127           0 :       return gpg_error (GPG_ERR_GENERAL);
    1128             :     }
    1129             : 
    1130           3 :   kh = keydb_new ();
    1131           3 :   if (!kh)
    1132             :     {
    1133           0 :       log_error (_("failed to allocate keyDB handle\n"));
    1134           0 :       return gpg_error (GPG_ERR_ENOMEM);;
    1135             :     }
    1136             : 
    1137             :   /* Set the ephemeral flag so that the search looks at all
    1138             :      records.  */
    1139           3 :   keydb_set_ephemeral (kh, 1);
    1140             : 
    1141           3 :   rc = lock_all (kh);
    1142           3 :   if (rc)
    1143           0 :     return rc;
    1144             : 
    1145           3 :   rc = keydb_search_fpr (ctrl, kh, fpr);
    1146           3 :   if (rc != -1)
    1147             :     {
    1148           0 :       keydb_release (kh);
    1149           0 :       if (!rc)
    1150             :         {
    1151           0 :           if (existed)
    1152           0 :             *existed = 1;
    1153           0 :           if (!ephemeral)
    1154             :             {
    1155             :               /* Remove ephemeral flags from existing certificate to "store"
    1156             :                  it permanently. */
    1157           0 :               rc = keydb_set_cert_flags (ctrl, cert, 1, KEYBOX_FLAG_BLOB, 0,
    1158             :                                          KEYBOX_FLAG_BLOB_EPHEMERAL, 0);
    1159           0 :               if (rc)
    1160             :                 {
    1161           0 :                   log_error ("clearing ephemeral flag failed: %s\n",
    1162             :                              gpg_strerror (rc));
    1163           0 :                   return rc;
    1164             :                 }
    1165             :             }
    1166           0 :           return 0; /* okay */
    1167             :         }
    1168           0 :       log_error (_("problem looking for existing certificate: %s\n"),
    1169             :                  gpg_strerror (rc));
    1170           0 :       return rc;
    1171             :     }
    1172             : 
    1173             :   /* Reset the ephemeral flag if not requested.  */
    1174           3 :   if (!ephemeral)
    1175           3 :     keydb_set_ephemeral (kh, 0);
    1176             : 
    1177           3 :   rc = keydb_locate_writable (kh, 0);
    1178           3 :   if (rc)
    1179             :     {
    1180           0 :       log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
    1181           0 :       keydb_release (kh);
    1182           0 :       return rc;
    1183             :     }
    1184             : 
    1185           3 :   rc = keydb_insert_cert (kh, cert);
    1186           3 :   if (rc)
    1187             :     {
    1188           0 :       log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
    1189           0 :       keydb_release (kh);
    1190           0 :       return rc;
    1191             :     }
    1192           3 :   keydb_release (kh);
    1193           3 :   return 0;
    1194             : }
    1195             : 
    1196             : 
    1197             : /* This is basically keydb_set_flags but it implements a complete
    1198             :    transaction by locating the certificate in the DB and updating the
    1199             :    flags. */
    1200             : gpg_error_t
    1201           0 : keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
    1202             :                       int which, int idx,
    1203             :                       unsigned int mask, unsigned int value)
    1204             : {
    1205             :   KEYDB_HANDLE kh;
    1206             :   gpg_error_t err;
    1207             :   unsigned char fpr[20];
    1208             :   unsigned int old_value;
    1209             : 
    1210           0 :   if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
    1211             :     {
    1212           0 :       log_error (_("failed to get the fingerprint\n"));
    1213           0 :       return gpg_error (GPG_ERR_GENERAL);
    1214             :     }
    1215             : 
    1216           0 :   kh = keydb_new ();
    1217           0 :   if (!kh)
    1218             :     {
    1219           0 :       log_error (_("failed to allocate keyDB handle\n"));
    1220           0 :       return gpg_error (GPG_ERR_ENOMEM);;
    1221             :     }
    1222             : 
    1223           0 :   if (ephemeral)
    1224           0 :     keydb_set_ephemeral (kh, 1);
    1225             : 
    1226           0 :   err = keydb_lock (kh);
    1227           0 :   if (err)
    1228             :     {
    1229           0 :       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
    1230           0 :       keydb_release (kh);
    1231           0 :       return err;
    1232             :     }
    1233             : 
    1234           0 :   err = keydb_search_fpr (ctrl, kh, fpr);
    1235           0 :   if (err)
    1236             :     {
    1237           0 :       if (err == -1)
    1238           0 :         err = gpg_error (GPG_ERR_NOT_FOUND);
    1239             :       else
    1240           0 :         log_error (_("problem re-searching certificate: %s\n"),
    1241             :                    gpg_strerror (err));
    1242           0 :       keydb_release (kh);
    1243           0 :       return err;
    1244             :     }
    1245             : 
    1246           0 :   err = keydb_get_flags (kh, which, idx, &old_value);
    1247           0 :   if (err)
    1248             :     {
    1249           0 :       log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
    1250           0 :       keydb_release (kh);
    1251           0 :       return err;
    1252             :     }
    1253             : 
    1254           0 :   value = ((old_value & ~mask) | (value & mask));
    1255             : 
    1256           0 :   if (value != old_value)
    1257             :     {
    1258           0 :       err = keydb_set_flags (kh, which, idx, value);
    1259           0 :       if (err)
    1260             :         {
    1261           0 :           log_error (_("error storing flags: %s\n"), gpg_strerror (err));
    1262           0 :           keydb_release (kh);
    1263           0 :           return err;
    1264             :         }
    1265             :     }
    1266             : 
    1267           0 :   keydb_release (kh);
    1268           0 :   return 0;
    1269             : }
    1270             : 
    1271             : 
    1272             : /* Reset all the certificate flags we have stored with the certificates
    1273             :    for performance reasons. */
    1274             : void
    1275           0 : keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
    1276             : {
    1277             :   gpg_error_t err;
    1278           0 :   KEYDB_HANDLE hd = NULL;
    1279           0 :   KEYDB_SEARCH_DESC *desc = NULL;
    1280             :   int ndesc;
    1281             :   strlist_t sl;
    1282           0 :   int rc=0;
    1283             :   unsigned int old_value, value;
    1284             : 
    1285             :   (void)ctrl;
    1286             : 
    1287           0 :   hd = keydb_new ();
    1288           0 :   if (!hd)
    1289             :     {
    1290           0 :       log_error ("keydb_new failed\n");
    1291           0 :       goto leave;
    1292             :     }
    1293             : 
    1294           0 :   if (!names)
    1295           0 :     ndesc = 1;
    1296             :   else
    1297             :     {
    1298           0 :       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
    1299             :         ;
    1300             :     }
    1301             : 
    1302           0 :   desc = xtrycalloc (ndesc, sizeof *desc);
    1303           0 :   if (!ndesc)
    1304             :     {
    1305           0 :       log_error ("allocating memory failed: %s\n",
    1306             :                  gpg_strerror (out_of_core ()));
    1307           0 :       goto leave;
    1308             :     }
    1309             : 
    1310           0 :   if (!names)
    1311           0 :     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
    1312             :   else
    1313             :     {
    1314           0 :       for (ndesc=0, sl=names; sl; sl = sl->next)
    1315             :         {
    1316           0 :           rc = classify_user_id (sl->d, desc+ndesc, 0);
    1317           0 :           if (rc)
    1318           0 :             log_error ("key '%s' not found: %s\n", sl->d, gpg_strerror (rc));
    1319             :           else
    1320           0 :             ndesc++;
    1321             :         }
    1322             :     }
    1323             : 
    1324           0 :   err = keydb_lock (hd);
    1325           0 :   if (err)
    1326             :     {
    1327           0 :       log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
    1328           0 :       goto leave;
    1329             :     }
    1330             : 
    1331           0 :   while (!(rc = keydb_search (ctrl, hd, desc, ndesc)))
    1332             :     {
    1333           0 :       if (!names)
    1334           0 :         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
    1335             : 
    1336           0 :       err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
    1337           0 :       if (err)
    1338             :         {
    1339           0 :           log_error (_("error getting stored flags: %s\n"),
    1340             :                      gpg_strerror (err));
    1341           0 :           goto leave;
    1342             :         }
    1343             : 
    1344           0 :       value = (old_value & ~VALIDITY_REVOKED);
    1345           0 :       if (value != old_value)
    1346             :         {
    1347           0 :           err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
    1348           0 :           if (err)
    1349             :             {
    1350           0 :               log_error (_("error storing flags: %s\n"), gpg_strerror (err));
    1351           0 :               goto leave;
    1352             :             }
    1353             :         }
    1354             :     }
    1355           0 :   if (rc && rc != -1)
    1356           0 :     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
    1357             : 
    1358             :  leave:
    1359           0 :   xfree (desc);
    1360           0 :   keydb_release (hd);
    1361           0 : }

Generated by: LCOV version 1.11