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

« back to all changes in this revision

Viewing changes to kbx/kbxutil.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
/* kbxutil.c - The Keybox utility
 
2
 *      Copyright (C) 2000, 2001, 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 <errno.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <ctype.h>
 
27
#include <sys/stat.h>
 
28
#include <unistd.h>
 
29
#include <assert.h>
 
30
 
 
31
#define JNLIB_NEED_LOG_LOGV
 
32
#include "../jnlib/logging.h"
 
33
#include "../jnlib/argparse.h"
 
34
#include "../jnlib/stringhelp.h"
 
35
#include "../jnlib/utf8conv.h"
 
36
#include "../common/i18n.h"
 
37
#include "keybox-defs.h"
 
38
 
 
39
#include <gcrypt.h>
 
40
 
 
41
 
 
42
enum cmd_and_opt_values {
 
43
  aNull = 0,
 
44
  oArmor          = 'a',
 
45
  oDryRun         = 'n',
 
46
  oOutput         = 'o',
 
47
  oQuiet          = 'q',
 
48
  oVerbose        = 'v',
 
49
  
 
50
  aNoSuchCmd    = 500,   /* force other values not to be a letter */
 
51
  aFindByFpr,
 
52
  aFindByKid,
 
53
  aFindByUid,
 
54
  aStats,
 
55
  aImportOpenPGP,
 
56
 
 
57
  oDebug,
 
58
  oDebugAll,
 
59
 
 
60
  oNoArmor,
 
61
  
 
62
 
 
63
  aTest
 
64
};
 
65
 
 
66
 
 
67
static ARGPARSE_OPTS opts[] = {
 
68
  { 300, NULL, 0, N_("@Commands:\n ") },
 
69
 
 
70
/*   { aFindByFpr,  "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */
 
71
/*   { aFindByKid,  "find-by-kid", 0, "|KID| find key using it's keyid" }, */
 
72
/*   { aFindByUid,  "find-by-uid", 0, "|NAME| find key by user name" }, */
 
73
  { aStats,      "stats",       0, "show key statistics" }, 
 
74
  { aImportOpenPGP, "import-openpgp", 0, "import OpenPGP keyblocks"},
 
75
  
 
76
  { 301, NULL, 0, N_("@\nOptions:\n ") },
 
77
  
 
78
/*   { oArmor, "armor",     0, N_("create ascii armored output")}, */
 
79
/*   { oArmor, "armour",     0, "@" }, */
 
80
/*   { oOutput, "output",    2, N_("use as output file")}, */
 
81
  { oVerbose, "verbose",   0, N_("verbose") },
 
82
  { oQuiet,     "quiet",   0, N_("be somewhat more quiet") },
 
83
  { oDryRun, "dry-run",   0, N_("do not make any changes") },
 
84
  
 
85
  { oDebug, "debug"     ,4|16, N_("set debugging flags")},
 
86
  { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
 
87
 
 
88
  {0} /* end of list */
 
89
};
 
90
 
 
91
 
 
92
void myexit (int rc);
 
93
 
 
94
int keybox_errors_seen = 0;
 
95
 
 
96
 
 
97
static const char *
 
98
my_strusage( int level )
 
99
{
 
100
    const char *p;
 
101
    switch( level ) {
 
102
      case 11: p = "kbxutil (GnuPG)";
 
103
        break;
 
104
      case 13: p = VERSION; break;
 
105
      case 17: p = PRINTABLE_OS_NAME; break;
 
106
      case 19: p =
 
107
            _("Please report bugs to " PACKAGE_BUGREPORT ".\n");
 
108
        break;
 
109
      case 1:
 
110
      case 40:  p =
 
111
            _("Usage: kbxutil [options] [files] (-h for help)");
 
112
        break;
 
113
      case 41:  p =
 
114
            _("Syntax: kbxutil [options] [files]\n"
 
115
              "list, export, import Keybox data\n");
 
116
        break;
 
117
 
 
118
 
 
119
      default:  p = NULL;
 
120
    }
 
121
    return p;
 
122
}
 
123
 
 
124
 
 
125
static void
 
126
i18n_init(void)
 
127
{
 
128
#ifdef USE_SIMPLE_GETTEXT
 
129
    set_gettext_file( PACKAGE_GT );
 
130
#else
 
131
#ifdef ENABLE_NLS
 
132
    setlocale( LC_ALL, "" );
 
133
    bindtextdomain( PACKAGE_GT, LOCALEDIR );
 
134
    textdomain( PACKAGE_GT );
 
135
#endif
 
136
#endif
 
137
}
 
138
 
 
139
/* Used by gcry for logging */
 
140
static void
 
141
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
 
142
{
 
143
  /* Map the log levels.  */
 
144
  switch (level)
 
145
    {
 
146
    case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
 
147
    case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
 
148
    case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
 
149
    case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
 
150
    case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
 
151
    case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
 
152
    case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
 
153
    default:            level = JNLIB_LOG_ERROR; break;  
 
154
    }
 
155
  log_logv (level, fmt, arg_ptr);
 
156
}
 
157
 
 
158
 
 
159
 
 
160
/*  static void */
 
161
/*  wrong_args( const char *text ) */
 
162
/*  { */
 
163
/*      log_error("usage: kbxutil %s\n", text); */
 
164
/*      myexit ( 1 ); */
 
165
/*  } */
 
166
 
 
167
 
 
168
#if 0
 
169
static int
 
170
hextobyte( const byte *s )
 
171
{
 
172
    int c;
 
173
 
 
174
    if( *s >= '0' && *s <= '9' )
 
175
        c = 16 * (*s - '0');
 
176
    else if( *s >= 'A' && *s <= 'F' )
 
177
        c = 16 * (10 + *s - 'A');
 
178
    else if( *s >= 'a' && *s <= 'f' )
 
179
        c = 16 * (10 + *s - 'a');
 
180
    else
 
181
        return -1;
 
182
    s++;
 
183
    if( *s >= '0' && *s <= '9' )
 
184
        c += *s - '0';
 
185
    else if( *s >= 'A' && *s <= 'F' )
 
186
        c += 10 + *s - 'A';
 
187
    else if( *s >= 'a' && *s <= 'f' )
 
188
        c += 10 + *s - 'a';
 
189
    else
 
190
        return -1;
 
191
    return c;
 
192
}
 
193
#endif
 
194
 
 
195
#if 0
 
196
static char *
 
197
format_fingerprint ( const char *s )
 
198
{
 
199
    int i, c;
 
200
    byte fpr[20];
 
201
 
 
202
    for (i=0; i < 20 && *s; ) {
 
203
        if ( *s == ' ' || *s == '\t' ) {
 
204
            s++;
 
205
            continue;
 
206
        }
 
207
        c = hextobyte(s);
 
208
        if (c == -1) {
 
209
            return NULL;
 
210
        }
 
211
        fpr[i++] = c;
 
212
        s += 2;
 
213
    }
 
214
    return gcry_xstrdup ( fpr );
 
215
}
 
216
#endif
 
217
 
 
218
#if 0
 
219
static int
 
220
format_keyid ( const char *s, u32 *kid )
 
221
{
 
222
    char helpbuf[9];
 
223
    switch ( strlen ( s ) ) {
 
224
      case 8:
 
225
        kid[0] = 0;
 
226
        kid[1] = strtoul( s, NULL, 16 );
 
227
        return 10;
 
228
 
 
229
      case 16:
 
230
        mem2str( helpbuf, s, 9 );
 
231
        kid[0] = strtoul( helpbuf, NULL, 16 );
 
232
        kid[1] = strtoul( s+8, NULL, 16 );
 
233
        return 11;
 
234
    }
 
235
    return 0; /* error */
 
236
}
 
237
#endif
 
238
 
 
239
static char *
 
240
read_file (const char *fname, size_t *r_length)
 
241
{
 
242
  FILE *fp;
 
243
  char *buf;
 
244
  size_t buflen;
 
245
  
 
246
  if (!strcmp (fname, "-"))
 
247
    {
 
248
      size_t nread, bufsize = 0;
 
249
 
 
250
      fp = stdin;
 
251
      buf = NULL;
 
252
      buflen = 0;
 
253
#define NCHUNK 8192
 
254
      do 
 
255
        {
 
256
          bufsize += NCHUNK;
 
257
          if (!buf)
 
258
            buf = xtrymalloc (bufsize);
 
259
          else
 
260
            buf = xtryrealloc (buf, bufsize);
 
261
          if (!buf)
 
262
            log_fatal ("can't allocate buffer: %s\n", strerror (errno));
 
263
 
 
264
          nread = fread (buf+buflen, 1, NCHUNK, fp);
 
265
          if (nread < NCHUNK && ferror (fp))
 
266
            {
 
267
              log_error ("error reading `[stdin]': %s\n", strerror (errno));
 
268
              xfree (buf);
 
269
              return NULL;
 
270
            }
 
271
          buflen += nread;
 
272
        }
 
273
      while (nread == NCHUNK);
 
274
#undef NCHUNK
 
275
 
 
276
    }
 
277
  else
 
278
    {
 
279
      struct stat st;
 
280
 
 
281
      fp = fopen (fname, "rb");
 
282
      if (!fp)
 
283
        {
 
284
          log_error ("can't open `%s': %s\n", fname, strerror (errno));
 
285
          return NULL;
 
286
        }
 
287
  
 
288
      if (fstat (fileno(fp), &st))
 
289
        {
 
290
          log_error ("can't stat `%s': %s\n", fname, strerror (errno));
 
291
          fclose (fp);
 
292
          return NULL;
 
293
        }
 
294
      
 
295
      buflen = st.st_size;
 
296
      buf = xtrymalloc (buflen+1);
 
297
      if (!buf)
 
298
        log_fatal ("can't allocate buffer: %s\n", strerror (errno));
 
299
      if (fread (buf, buflen, 1, fp) != 1)
 
300
        {
 
301
          log_error ("error reading `%s': %s\n", fname, strerror (errno));
 
302
          fclose (fp);
 
303
          xfree (buf);
 
304
          return NULL;
 
305
        }
 
306
      fclose (fp);
 
307
    }
 
308
 
 
309
  *r_length = buflen;
 
310
  return buf;
 
311
}
 
312
 
 
313
 
 
314
static void
 
315
dump_fpr (const unsigned char *buffer, size_t len)
 
316
{
 
317
  int i;
 
318
 
 
319
  for (i=0; i < len; i++, buffer++)
 
320
    {
 
321
      if (len == 20)
 
322
        {
 
323
          if (i == 10)
 
324
            putchar (' ');
 
325
          printf (" %02X%02X", buffer[0], buffer[1]);
 
326
          i++; buffer++;
 
327
        }
 
328
      else
 
329
        {
 
330
          if (i && !(i % 8))
 
331
            putchar (' ');
 
332
          printf (" %02X", buffer[0]);
 
333
        }
 
334
    }
 
335
}
 
336
 
 
337
 
 
338
static void
 
339
dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
 
340
{
 
341
  printf ("pub %02X%02X%02X%02X",
 
342
          info->primary.keyid[4], info->primary.keyid[5],
 
343
          info->primary.keyid[6], info->primary.keyid[7] );
 
344
  dump_fpr (info->primary.fpr, info->primary.fprlen);
 
345
  putchar ('\n');
 
346
  if (info->nsubkeys)
 
347
    {
 
348
      struct _keybox_openpgp_key_info *k;
 
349
 
 
350
      k = &info->subkeys;
 
351
      do 
 
352
        {
 
353
          printf ("sub %02X%02X%02X%02X",
 
354
                  k->keyid[4], k->keyid[5],
 
355
                  k->keyid[6], k->keyid[7] );
 
356
          dump_fpr (k->fpr, k->fprlen);
 
357
          putchar ('\n');
 
358
          k = k->next;
 
359
        }
 
360
      while (k);
 
361
    }
 
362
  if (info->nuids)
 
363
    {
 
364
      struct _keybox_openpgp_uid_info *u;
 
365
 
 
366
      u = &info->uids;
 
367
      do 
 
368
        {
 
369
          printf ("uid\t\t%.*s\n", u->len, image + u->off);
 
370
          u = u->next;
 
371
        }
 
372
      while (u);
 
373
    }
 
374
}
 
375
 
 
376
 
 
377
static void
 
378
import_openpgp (const char *filename)
 
379
{
 
380
  gpg_error_t err;
 
381
  char *buffer;
 
382
  size_t buflen, nparsed;
 
383
  unsigned char *p;
 
384
  struct _keybox_openpgp_info info;
 
385
 
 
386
  buffer = read_file (filename, &buflen);
 
387
  if (!buffer)
 
388
    return;
 
389
  p = buffer;
 
390
  for (;;)
 
391
    {
 
392
      err = _keybox_parse_openpgp (p, buflen, &nparsed, &info);
 
393
      assert (nparsed <= buflen);
 
394
      if (err)
 
395
        {
 
396
          if (gpg_err_code (err) == GPG_ERR_NO_DATA)
 
397
            break;
 
398
          log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
 
399
                    filename, gpg_strerror (err));
 
400
        }
 
401
      else
 
402
        {
 
403
          dump_openpgp_key (&info, p);
 
404
          _keybox_destroy_openpgp_info (&info);
 
405
        }
 
406
      p += nparsed;
 
407
      buflen -= nparsed;
 
408
    }
 
409
  xfree (buffer);
 
410
}
 
411
 
 
412
 
 
413
 
 
414
 
 
415
int
 
416
main( int argc, char **argv )
 
417
{
 
418
  ARGPARSE_ARGS pargs;
 
419
  enum cmd_and_opt_values cmd = 0;
 
420
  
 
421
  set_strusage( my_strusage );
 
422
  gcry_control (GCRYCTL_DISABLE_SECMEM);
 
423
  log_set_prefix ("kbxutil", 1); 
 
424
  set_native_charset (NULL); 
 
425
  i18n_init ();
 
426
 
 
427
  /* Check that the libraries are suitable.  Do it here because
 
428
     the option parsing may need services of the library.  */
 
429
  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
 
430
    {
 
431
      log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
 
432
                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
 
433
    }
 
434
 
 
435
  gcry_set_log_handler (my_gcry_logger, NULL);
 
436
 
 
437
  /*create_dotlock(NULL); register locking cleanup */
 
438
 
 
439
  /* We need to use the gcry malloc function because jnlib does use them */
 
440
  keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
 
441
  ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
 
442
 
 
443
 
 
444
  pargs.argc = &argc;
 
445
  pargs.argv = &argv;
 
446
  pargs.flags=  1;  /* do not remove the args */
 
447
  while (arg_parse( &pargs, opts) )
 
448
    {
 
449
      switch (pargs.r_opt)
 
450
        {
 
451
        case oVerbose:
 
452
          /*opt.verbose++;*/
 
453
          /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
 
454
          break;
 
455
        case oDebug:
 
456
          /*opt.debug |= pargs.r.ret_ulong; */
 
457
          break;
 
458
        case oDebugAll:
 
459
          /*opt.debug = ~0;*/
 
460
          break;
 
461
 
 
462
        case aFindByFpr:
 
463
        case aFindByKid:
 
464
        case aFindByUid:
 
465
        case aStats:
 
466
        case aImportOpenPGP:
 
467
          cmd = pargs.r_opt;
 
468
          break;
 
469
 
 
470
        default:
 
471
          pargs.err = 2;
 
472
          break;
 
473
        }
 
474
    }
 
475
  if (log_get_errorcount(0) )
 
476
    myexit(2);
 
477
  
 
478
  if (!cmd)
 
479
    { /* Default is to list a KBX file */
 
480
      if (!argc) 
 
481
        _keybox_dump_file (NULL, 0, stdout);
 
482
      else
 
483
        {
 
484
          for (; argc; argc--, argv++) 
 
485
            _keybox_dump_file (*argv, 0, stdout);
 
486
        }
 
487
    }
 
488
  else if (cmd == aStats )
 
489
    {
 
490
      if (!argc) 
 
491
        _keybox_dump_file (NULL, 1, stdout);
 
492
      else
 
493
        {
 
494
          for (; argc; argc--, argv++) 
 
495
            _keybox_dump_file (*argv, 1, stdout);
 
496
        }
 
497
    }
 
498
  else if (cmd == aImportOpenPGP)
 
499
    {
 
500
      if (!argc)
 
501
        import_openpgp ("-");
 
502
      else
 
503
        {
 
504
          for (; argc; argc--, argv++) 
 
505
            import_openpgp (*argv);
 
506
        }
 
507
    }
 
508
#if 0
 
509
  else if ( cmd == aFindByFpr ) 
 
510
    {
 
511
      char *fpr;
 
512
      if ( argc != 2 )
 
513
        wrong_args ("kbxfile foingerprint");
 
514
      fpr = format_fingerprint ( argv[1] );
 
515
      if ( !fpr )
 
516
        log_error ("invalid formatted fingerprint\n");
 
517
      else 
 
518
        {
 
519
          kbxfile_search_by_fpr ( argv[0], fpr );
 
520
          gcry_free ( fpr );
 
521
        }
 
522
    }
 
523
  else if ( cmd == aFindByKid ) 
 
524
    {
 
525
      u32 kid[2];
 
526
      int mode;
 
527
      
 
528
      if ( argc != 2 )
 
529
        wrong_args ("kbxfile short-or-long-keyid");
 
530
      mode = format_keyid ( argv[1], kid );
 
531
      if ( !mode )
 
532
        log_error ("invalid formatted keyID\n");
 
533
      else
 
534
        {
 
535
          kbxfile_search_by_kid ( argv[0], kid, mode );
 
536
        }
 
537
    }
 
538
  else if ( cmd == aFindByUid ) 
 
539
    {
 
540
      if ( argc != 2 )
 
541
        wrong_args ("kbxfile userID");
 
542
      kbxfile_search_by_uid ( argv[0], argv[1] );
 
543
    }
 
544
#endif
 
545
  else
 
546
      log_error ("unsupported action\n");
 
547
  
 
548
  myexit(0);
 
549
  return 8; /*NEVER REACHED*/
 
550
}
 
551
 
 
552
 
 
553
void
 
554
myexit( int rc )
 
555
{
 
556
  /*    if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
 
557
/*      gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
 
558
/*      gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
 
559
  /*    }*/
 
560
/*      if( opt.debug ) */
 
561
/*      gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
 
562
    rc = rc? rc : log_get_errorcount(0)? 2 :
 
563
                        keybox_errors_seen? 1 : 0;
 
564
    exit(rc );
 
565
}
 
566
 
 
567