1 /* kbxutil.c - The Keybox utility
2 * Copyright (C) 2000, 2001, 2004, 2007 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 3 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, see <http://www.gnu.org/licenses/>.
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"
38 #include "keybox-defs.h"
42 enum cmd_and_opt_values
{
50 aNoSuchCmd
= 500, /* force other values not to be a letter */
70 static ARGPARSE_OPTS opts
[] = {
71 { 300, NULL
, 0, N_("@Commands:\n ") },
73 /* { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */
74 /* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */
75 /* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */
76 { aStats
, "stats", 0, "show key statistics" },
77 { aImportOpenPGP
, "import-openpgp", 0, "import OpenPGP keyblocks"},
78 { aFindDups
, "find-dups", 0, "find duplicates" },
79 { aCut
, "cut", 0, "export records" },
81 { 301, NULL
, 0, N_("@\nOptions:\n ") },
83 { oFrom
, "from", 4, "|N|first record to export" },
84 { oTo
, "to", 4, "|N|last record to export" },
85 /* { oArmor, "armor", 0, N_("create ascii armored output")}, */
86 /* { oArmor, "armour", 0, "@" }, */
87 /* { oOutput, "output", 2, N_("use as output file")}, */
88 { oVerbose
, "verbose", 0, N_("verbose") },
89 { oQuiet
, "quiet", 0, N_("be somewhat more quiet") },
90 { oDryRun
, "dry-run", 0, N_("do not make any changes") },
92 { oDebug
, "debug" ,4|16, N_("set debugging flags")},
93 { oDebugAll
, "debug-all" ,0, N_("enable full debugging")},
101 int keybox_errors_seen
= 0;
105 my_strusage( int level
)
109 case 11: p
= "kbxutil (GnuPG)";
111 case 13: p
= VERSION
; break;
112 case 17: p
= PRINTABLE_OS_NAME
; break;
114 _("Please report bugs to " PACKAGE_BUGREPORT
".\n");
118 _("Usage: kbxutil [options] [files] (-h for help)");
121 _("Syntax: kbxutil [options] [files]\n"
122 "list, export, import Keybox data\n");
132 /* Used by gcry for logging */
134 my_gcry_logger (void *dummy
, int level
, const char *fmt
, va_list arg_ptr
)
138 /* Map the log levels. */
141 case GCRY_LOG_CONT
: level
= JNLIB_LOG_CONT
; break;
142 case GCRY_LOG_INFO
: level
= JNLIB_LOG_INFO
; break;
143 case GCRY_LOG_WARN
: level
= JNLIB_LOG_WARN
; break;
144 case GCRY_LOG_ERROR
:level
= JNLIB_LOG_ERROR
; break;
145 case GCRY_LOG_FATAL
:level
= JNLIB_LOG_FATAL
; break;
146 case GCRY_LOG_BUG
: level
= JNLIB_LOG_BUG
; break;
147 case GCRY_LOG_DEBUG
:level
= JNLIB_LOG_DEBUG
; break;
148 default: level
= JNLIB_LOG_ERROR
; break;
150 log_logv (level
, fmt
, arg_ptr
);
156 /* wrong_args( const char *text ) */
158 /* log_error("usage: kbxutil %s\n", text); */
165 hextobyte( const byte
*s
)
169 if( *s
>= '0' && *s
<= '9' )
171 else if( *s
>= 'A' && *s
<= 'F' )
172 c
= 16 * (10 + *s
- 'A');
173 else if( *s
>= 'a' && *s
<= 'f' )
174 c
= 16 * (10 + *s
- 'a');
178 if( *s
>= '0' && *s
<= '9' )
180 else if( *s
>= 'A' && *s
<= 'F' )
182 else if( *s
>= 'a' && *s
<= 'f' )
192 format_fingerprint ( const char *s
)
197 for (i
=0; i
< 20 && *s
; ) {
198 if ( *s
== ' ' || *s
== '\t' ) {
209 return gcry_xstrdup ( fpr
);
215 format_keyid ( const char *s
, u32
*kid
)
218 switch ( strlen ( s
) ) {
221 kid
[1] = strtoul( s
, NULL
, 16 );
225 mem2str( helpbuf
, s
, 9 );
226 kid
[0] = strtoul( helpbuf
, NULL
, 16 );
227 kid
[1] = strtoul( s
+8, NULL
, 16 );
230 return 0; /* error */
235 read_file (const char *fname
, size_t *r_length
)
241 if (!strcmp (fname
, "-"))
243 size_t nread
, bufsize
= 0;
253 buf
= xtrymalloc (bufsize
);
255 buf
= xtryrealloc (buf
, bufsize
);
257 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
259 nread
= fread (buf
+buflen
, 1, NCHUNK
, fp
);
260 if (nread
< NCHUNK
&& ferror (fp
))
262 log_error ("error reading `[stdin]': %s\n", strerror (errno
));
268 while (nread
== NCHUNK
);
276 fp
= fopen (fname
, "rb");
279 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
283 if (fstat (fileno(fp
), &st
))
285 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
291 buf
= xtrymalloc (buflen
+1);
293 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
294 if (fread (buf
, buflen
, 1, fp
) != 1)
296 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
310 dump_fpr (const unsigned char *buffer
, size_t len
)
314 for (i
=0; i
< len
; i
++, buffer
++)
320 printf (" %02X%02X", buffer
[0], buffer
[1]);
327 printf (" %02X", buffer
[0]);
334 dump_openpgp_key (keybox_openpgp_info_t info
, const unsigned char *image
)
336 printf ("pub %02X%02X%02X%02X",
337 info
->primary
.keyid
[4], info
->primary
.keyid
[5],
338 info
->primary
.keyid
[6], info
->primary
.keyid
[7] );
339 dump_fpr (info
->primary
.fpr
, info
->primary
.fprlen
);
343 struct _keybox_openpgp_key_info
*k
;
348 printf ("sub %02X%02X%02X%02X",
349 k
->keyid
[4], k
->keyid
[5],
350 k
->keyid
[6], k
->keyid
[7] );
351 dump_fpr (k
->fpr
, k
->fprlen
);
359 struct _keybox_openpgp_uid_info
*u
;
364 printf ("uid\t\t%.*s\n", (int)u
->len
, image
+ u
->off
);
373 import_openpgp (const char *filename
)
377 size_t buflen
, nparsed
;
379 struct _keybox_openpgp_info info
;
381 buffer
= read_file (filename
, &buflen
);
384 p
= (unsigned char *)buffer
;
387 err
= _keybox_parse_openpgp (p
, buflen
, &nparsed
, &info
);
388 assert (nparsed
<= buflen
);
391 if (gpg_err_code (err
) == GPG_ERR_NO_DATA
)
393 log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
394 filename
, gpg_strerror (err
));
398 dump_openpgp_key (&info
, p
);
399 _keybox_destroy_openpgp_info (&info
);
411 main( int argc
, char **argv
)
414 enum cmd_and_opt_values cmd
= 0;
415 unsigned long from
= 0, to
= ULONG_MAX
;
417 set_strusage( my_strusage
);
418 gcry_control (GCRYCTL_DISABLE_SECMEM
);
419 log_set_prefix ("kbxutil", 1);
421 /* Make sure that our subsystems are ready. */
422 init_common_subsystems ();
426 /* Check that the libraries are suitable. Do it here because
427 the option parsing may need services of the library. */
428 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
430 log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
431 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
434 gcry_set_log_handler (my_gcry_logger
, NULL
);
436 /*create_dotlock(NULL); register locking cleanup */
438 /* We need to use the gcry malloc function because jnlib does use them */
439 keybox_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
440 ksba_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
445 pargs
.flags
= 1; /* do not remove the args */
446 while (arg_parse( &pargs
, opts
) )
452 /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
455 /*opt.debug |= pargs.r.ret_ulong; */
471 case oFrom
: from
= pargs
.r
.ret_ulong
; break;
472 case oTo
: to
= pargs
.r
.ret_ulong
; break;
481 log_error ("record number of \"--to\" is lower than \"--from\" one\n");
484 if (log_get_errorcount(0) )
488 { /* Default is to list a KBX file */
490 _keybox_dump_file (NULL
, 0, stdout
);
493 for (; argc
; argc
--, argv
++)
494 _keybox_dump_file (*argv
, 0, stdout
);
497 else if (cmd
== aStats
)
500 _keybox_dump_file (NULL
, 1, stdout
);
503 for (; argc
; argc
--, argv
++)
504 _keybox_dump_file (*argv
, 1, stdout
);
507 else if (cmd
== aFindDups
)
510 _keybox_dump_find_dups (NULL
, 0, stdout
);
513 for (; argc
; argc
--, argv
++)
514 _keybox_dump_find_dups (*argv
, 0, stdout
);
517 else if (cmd
== aCut
)
520 _keybox_dump_cut_records (NULL
, from
, to
, stdout
);
523 for (; argc
; argc
--, argv
++)
524 _keybox_dump_cut_records (*argv
, from
, to
, stdout
);
527 else if (cmd
== aImportOpenPGP
)
530 import_openpgp ("-");
533 for (; argc
; argc
--, argv
++)
534 import_openpgp (*argv
);
538 else if ( cmd
== aFindByFpr
)
542 wrong_args ("kbxfile foingerprint");
543 fpr
= format_fingerprint ( argv
[1] );
545 log_error ("invalid formatted fingerprint\n");
548 kbxfile_search_by_fpr ( argv
[0], fpr
);
552 else if ( cmd
== aFindByKid
)
558 wrong_args ("kbxfile short-or-long-keyid");
559 mode
= format_keyid ( argv
[1], kid
);
561 log_error ("invalid formatted keyID\n");
564 kbxfile_search_by_kid ( argv
[0], kid
, mode
);
567 else if ( cmd
== aFindByUid
)
570 wrong_args ("kbxfile userID");
571 kbxfile_search_by_uid ( argv
[0], argv
[1] );
575 log_error ("unsupported action\n");
578 return 8; /*NEVER REACHED*/
585 /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
586 /* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
587 /* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
589 /* if( opt.debug ) */
590 /* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
591 rc
= rc
? rc
: log_get_errorcount(0)? 2 :
592 keybox_errors_seen
? 1 : 0;