1 /* kbxutil.c - The Keybox utility
2 * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
32 #define JNLIB_NEED_LOG_LOGV
33 #include "../jnlib/logging.h"
34 #include "../jnlib/argparse.h"
35 #include "../jnlib/stringhelp.h"
36 #include "../jnlib/utf8conv.h"
37 #include "../common/i18n.h"
38 #include "keybox-defs.h"
43 enum cmd_and_opt_values
{
51 aNoSuchCmd
= 500, /* force other values not to be a letter */
68 static ARGPARSE_OPTS opts
[] = {
69 { 300, NULL
, 0, N_("@Commands:\n ") },
71 /* { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */
72 /* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */
73 /* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */
74 { aStats
, "stats", 0, "show key statistics" },
75 { aImportOpenPGP
, "import-openpgp", 0, "import OpenPGP keyblocks"},
77 { 301, NULL
, 0, N_("@\nOptions:\n ") },
79 /* { oArmor, "armor", 0, N_("create ascii armored output")}, */
80 /* { oArmor, "armour", 0, "@" }, */
81 /* { oOutput, "output", 2, N_("use as output file")}, */
82 { oVerbose
, "verbose", 0, N_("verbose") },
83 { oQuiet
, "quiet", 0, N_("be somewhat more quiet") },
84 { oDryRun
, "dry-run", 0, N_("do not make any changes") },
86 { oDebug
, "debug" ,4|16, N_("set debugging flags")},
87 { oDebugAll
, "debug-all" ,0, N_("enable full debugging")},
95 int keybox_errors_seen
= 0;
99 my_strusage( int level
)
103 case 11: p
= "kbxutil (GnuPG)";
105 case 13: p
= VERSION
; break;
106 case 17: p
= PRINTABLE_OS_NAME
; break;
108 _("Please report bugs to " PACKAGE_BUGREPORT
".\n");
112 _("Usage: kbxutil [options] [files] (-h for help)");
115 _("Syntax: kbxutil [options] [files]\n"
116 "list, export, import Keybox data\n");
129 #ifdef USE_SIMPLE_GETTEXT
130 set_gettext_file( PACKAGE_GT
);
133 setlocale( LC_ALL
, "" );
134 bindtextdomain( PACKAGE_GT
, LOCALEDIR
);
135 textdomain( PACKAGE_GT
);
140 /* Used by gcry for logging */
142 my_gcry_logger (void *dummy
, int level
, const char *fmt
, va_list arg_ptr
)
144 /* Map the log levels. */
147 case GCRY_LOG_CONT
: level
= JNLIB_LOG_CONT
; break;
148 case GCRY_LOG_INFO
: level
= JNLIB_LOG_INFO
; break;
149 case GCRY_LOG_WARN
: level
= JNLIB_LOG_WARN
; break;
150 case GCRY_LOG_ERROR
:level
= JNLIB_LOG_ERROR
; break;
151 case GCRY_LOG_FATAL
:level
= JNLIB_LOG_FATAL
; break;
152 case GCRY_LOG_BUG
: level
= JNLIB_LOG_BUG
; break;
153 case GCRY_LOG_DEBUG
:level
= JNLIB_LOG_DEBUG
; break;
154 default: level
= JNLIB_LOG_ERROR
; break;
156 log_logv (level
, fmt
, arg_ptr
);
162 /* wrong_args( const char *text ) */
164 /* log_error("usage: kbxutil %s\n", text); */
171 hextobyte( const byte
*s
)
175 if( *s
>= '0' && *s
<= '9' )
177 else if( *s
>= 'A' && *s
<= 'F' )
178 c
= 16 * (10 + *s
- 'A');
179 else if( *s
>= 'a' && *s
<= 'f' )
180 c
= 16 * (10 + *s
- 'a');
184 if( *s
>= '0' && *s
<= '9' )
186 else if( *s
>= 'A' && *s
<= 'F' )
188 else if( *s
>= 'a' && *s
<= 'f' )
198 format_fingerprint ( const char *s
)
203 for (i
=0; i
< 20 && *s
; ) {
204 if ( *s
== ' ' || *s
== '\t' ) {
215 return gcry_xstrdup ( fpr
);
221 format_keyid ( const char *s
, u32
*kid
)
224 switch ( strlen ( s
) ) {
227 kid
[1] = strtoul( s
, NULL
, 16 );
231 mem2str( helpbuf
, s
, 9 );
232 kid
[0] = strtoul( helpbuf
, NULL
, 16 );
233 kid
[1] = strtoul( s
+8, NULL
, 16 );
236 return 0; /* error */
241 read_file (const char *fname
, size_t *r_length
)
247 if (!strcmp (fname
, "-"))
249 size_t nread
, bufsize
= 0;
259 buf
= xtrymalloc (bufsize
);
261 buf
= xtryrealloc (buf
, bufsize
);
263 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
265 nread
= fread (buf
+buflen
, 1, NCHUNK
, fp
);
266 if (nread
< NCHUNK
&& ferror (fp
))
268 log_error ("error reading `[stdin]': %s\n", strerror (errno
));
274 while (nread
== NCHUNK
);
282 fp
= fopen (fname
, "rb");
285 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
289 if (fstat (fileno(fp
), &st
))
291 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
297 buf
= xtrymalloc (buflen
+1);
299 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
300 if (fread (buf
, buflen
, 1, fp
) != 1)
302 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
316 dump_fpr (const unsigned char *buffer
, size_t len
)
320 for (i
=0; i
< len
; i
++, buffer
++)
326 printf (" %02X%02X", buffer
[0], buffer
[1]);
333 printf (" %02X", buffer
[0]);
340 dump_openpgp_key (keybox_openpgp_info_t info
, const unsigned char *image
)
342 printf ("pub %02X%02X%02X%02X",
343 info
->primary
.keyid
[4], info
->primary
.keyid
[5],
344 info
->primary
.keyid
[6], info
->primary
.keyid
[7] );
345 dump_fpr (info
->primary
.fpr
, info
->primary
.fprlen
);
349 struct _keybox_openpgp_key_info
*k
;
354 printf ("sub %02X%02X%02X%02X",
355 k
->keyid
[4], k
->keyid
[5],
356 k
->keyid
[6], k
->keyid
[7] );
357 dump_fpr (k
->fpr
, k
->fprlen
);
365 struct _keybox_openpgp_uid_info
*u
;
370 printf ("uid\t\t%.*s\n", u
->len
, image
+ u
->off
);
379 import_openpgp (const char *filename
)
383 size_t buflen
, nparsed
;
385 struct _keybox_openpgp_info info
;
387 buffer
= read_file (filename
, &buflen
);
390 p
= (unsigned char *)buffer
;
393 err
= _keybox_parse_openpgp (p
, buflen
, &nparsed
, &info
);
394 assert (nparsed
<= buflen
);
397 if (gpg_err_code (err
) == GPG_ERR_NO_DATA
)
399 log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
400 filename
, gpg_strerror (err
));
404 dump_openpgp_key (&info
, p
);
405 _keybox_destroy_openpgp_info (&info
);
417 main( int argc
, char **argv
)
420 enum cmd_and_opt_values cmd
= 0;
422 set_strusage( my_strusage
);
423 gcry_control (GCRYCTL_DISABLE_SECMEM
);
424 log_set_prefix ("kbxutil", 1);
425 set_native_charset (NULL
);
428 /* Check that the libraries are suitable. Do it here because
429 the option parsing may need services of the library. */
430 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
432 log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
433 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
436 gcry_set_log_handler (my_gcry_logger
, NULL
);
438 /*create_dotlock(NULL); register locking cleanup */
440 /* We need to use the gcry malloc function because jnlib does use them */
441 keybox_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
442 ksba_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
447 pargs
.flags
= 1; /* do not remove the args */
448 while (arg_parse( &pargs
, opts
) )
454 /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
457 /*opt.debug |= pargs.r.ret_ulong; */
476 if (log_get_errorcount(0) )
480 { /* Default is to list a KBX file */
482 _keybox_dump_file (NULL
, 0, stdout
);
485 for (; argc
; argc
--, argv
++)
486 _keybox_dump_file (*argv
, 0, stdout
);
489 else if (cmd
== aStats
)
492 _keybox_dump_file (NULL
, 1, stdout
);
495 for (; argc
; argc
--, argv
++)
496 _keybox_dump_file (*argv
, 1, stdout
);
499 else if (cmd
== aImportOpenPGP
)
502 import_openpgp ("-");
505 for (; argc
; argc
--, argv
++)
506 import_openpgp (*argv
);
510 else if ( cmd
== aFindByFpr
)
514 wrong_args ("kbxfile foingerprint");
515 fpr
= format_fingerprint ( argv
[1] );
517 log_error ("invalid formatted fingerprint\n");
520 kbxfile_search_by_fpr ( argv
[0], fpr
);
524 else if ( cmd
== aFindByKid
)
530 wrong_args ("kbxfile short-or-long-keyid");
531 mode
= format_keyid ( argv
[1], kid
);
533 log_error ("invalid formatted keyID\n");
536 kbxfile_search_by_kid ( argv
[0], kid
, mode
);
539 else if ( cmd
== aFindByUid
)
542 wrong_args ("kbxfile userID");
543 kbxfile_search_by_uid ( argv
[0], argv
[1] );
547 log_error ("unsupported action\n");
550 return 8; /*NEVER REACHED*/
557 /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
558 /* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
559 /* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
561 /* if( opt.debug ) */
562 /* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
563 rc
= rc
? rc
: log_get_errorcount(0)? 2 :
564 keybox_errors_seen
? 1 : 0;