~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to sm/keydb.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

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