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;
113 case 19: p
= _("Please report bugs to <@EMAIL@>.\n"); break;
117 _("Usage: kbxutil [options] [files] (-h for help)");
120 _("Syntax: kbxutil [options] [files]\n"
121 "list, export, import Keybox data\n");
131 /* Used by gcry for logging */
133 my_gcry_logger (void *dummy
, int level
, const char *fmt
, va_list arg_ptr
)
137 /* Map the log levels. */
140 case GCRY_LOG_CONT
: level
= JNLIB_LOG_CONT
; break;
141 case GCRY_LOG_INFO
: level
= JNLIB_LOG_INFO
; break;
142 case GCRY_LOG_WARN
: level
= JNLIB_LOG_WARN
; break;
143 case GCRY_LOG_ERROR
:level
= JNLIB_LOG_ERROR
; break;
144 case GCRY_LOG_FATAL
:level
= JNLIB_LOG_FATAL
; break;
145 case GCRY_LOG_BUG
: level
= JNLIB_LOG_BUG
; break;
146 case GCRY_LOG_DEBUG
:level
= JNLIB_LOG_DEBUG
; break;
147 default: level
= JNLIB_LOG_ERROR
; break;
149 log_logv (level
, fmt
, arg_ptr
);
155 /* wrong_args( const char *text ) */
157 /* log_error("usage: kbxutil %s\n", text); */
164 hextobyte( const byte
*s
)
168 if( *s
>= '0' && *s
<= '9' )
170 else if( *s
>= 'A' && *s
<= 'F' )
171 c
= 16 * (10 + *s
- 'A');
172 else if( *s
>= 'a' && *s
<= 'f' )
173 c
= 16 * (10 + *s
- 'a');
177 if( *s
>= '0' && *s
<= '9' )
179 else if( *s
>= 'A' && *s
<= 'F' )
181 else if( *s
>= 'a' && *s
<= 'f' )
191 format_fingerprint ( const char *s
)
196 for (i
=0; i
< 20 && *s
; ) {
197 if ( *s
== ' ' || *s
== '\t' ) {
208 return gcry_xstrdup ( fpr
);
214 format_keyid ( const char *s
, u32
*kid
)
217 switch ( strlen ( s
) ) {
220 kid
[1] = strtoul( s
, NULL
, 16 );
224 mem2str( helpbuf
, s
, 9 );
225 kid
[0] = strtoul( helpbuf
, NULL
, 16 );
226 kid
[1] = strtoul( s
+8, NULL
, 16 );
229 return 0; /* error */
234 read_file (const char *fname
, size_t *r_length
)
240 if (!strcmp (fname
, "-"))
242 size_t nread
, bufsize
= 0;
252 buf
= xtrymalloc (bufsize
);
254 buf
= xtryrealloc (buf
, bufsize
);
256 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
258 nread
= fread (buf
+buflen
, 1, NCHUNK
, fp
);
259 if (nread
< NCHUNK
&& ferror (fp
))
261 log_error ("error reading `[stdin]': %s\n", strerror (errno
));
267 while (nread
== NCHUNK
);
275 fp
= fopen (fname
, "rb");
278 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
282 if (fstat (fileno(fp
), &st
))
284 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
290 buf
= xtrymalloc (buflen
+1);
292 log_fatal ("can't allocate buffer: %s\n", strerror (errno
));
293 if (fread (buf
, buflen
, 1, fp
) != 1)
295 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
309 dump_fpr (const unsigned char *buffer
, size_t len
)
313 for (i
=0; i
< len
; i
++, buffer
++)
319 printf (" %02X%02X", buffer
[0], buffer
[1]);
326 printf (" %02X", buffer
[0]);
333 dump_openpgp_key (keybox_openpgp_info_t info
, const unsigned char *image
)
335 printf ("pub %02X%02X%02X%02X",
336 info
->primary
.keyid
[4], info
->primary
.keyid
[5],
337 info
->primary
.keyid
[6], info
->primary
.keyid
[7] );
338 dump_fpr (info
->primary
.fpr
, info
->primary
.fprlen
);
342 struct _keybox_openpgp_key_info
*k
;
347 printf ("sub %02X%02X%02X%02X",
348 k
->keyid
[4], k
->keyid
[5],
349 k
->keyid
[6], k
->keyid
[7] );
350 dump_fpr (k
->fpr
, k
->fprlen
);
358 struct _keybox_openpgp_uid_info
*u
;
363 printf ("uid\t\t%.*s\n", (int)u
->len
, image
+ u
->off
);
372 import_openpgp (const char *filename
)
376 size_t buflen
, nparsed
;
378 struct _keybox_openpgp_info info
;
380 buffer
= read_file (filename
, &buflen
);
383 p
= (unsigned char *)buffer
;
386 err
= _keybox_parse_openpgp (p
, buflen
, &nparsed
, &info
);
387 assert (nparsed
<= buflen
);
390 if (gpg_err_code (err
) == GPG_ERR_NO_DATA
)
392 log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
393 filename
, gpg_strerror (err
));
397 dump_openpgp_key (&info
, p
);
398 _keybox_destroy_openpgp_info (&info
);
410 main( int argc
, char **argv
)
413 enum cmd_and_opt_values cmd
= 0;
414 unsigned long from
= 0, to
= ULONG_MAX
;
416 set_strusage( my_strusage
);
417 gcry_control (GCRYCTL_DISABLE_SECMEM
);
418 log_set_prefix ("kbxutil", 1);
420 /* Make sure that our subsystems are ready. */
422 init_common_subsystems ();
424 /* Check that the libraries are suitable. Do it here because
425 the option parsing may need services of the library. */
426 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
428 log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
429 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
432 gcry_set_log_handler (my_gcry_logger
, NULL
);
434 /*create_dotlock(NULL); register locking cleanup */
436 /* We need to use the gcry malloc function because jnlib does use them */
437 keybox_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
438 ksba_set_malloc_hooks (gcry_malloc
, gcry_realloc
, gcry_free
);
443 pargs
.flags
= 1; /* do not remove the args */
444 while (arg_parse( &pargs
, opts
) )
450 /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
453 /*opt.debug |= pargs.r.ret_ulong; */
469 case oFrom
: from
= pargs
.r
.ret_ulong
; break;
470 case oTo
: to
= pargs
.r
.ret_ulong
; break;
479 log_error ("record number of \"--to\" is lower than \"--from\" one\n");
482 if (log_get_errorcount(0) )
486 { /* Default is to list a KBX file */
488 _keybox_dump_file (NULL
, 0, stdout
);
491 for (; argc
; argc
--, argv
++)
492 _keybox_dump_file (*argv
, 0, stdout
);
495 else if (cmd
== aStats
)
498 _keybox_dump_file (NULL
, 1, stdout
);
501 for (; argc
; argc
--, argv
++)
502 _keybox_dump_file (*argv
, 1, stdout
);
505 else if (cmd
== aFindDups
)
508 _keybox_dump_find_dups (NULL
, 0, stdout
);
511 for (; argc
; argc
--, argv
++)
512 _keybox_dump_find_dups (*argv
, 0, stdout
);
515 else if (cmd
== aCut
)
518 _keybox_dump_cut_records (NULL
, from
, to
, stdout
);
521 for (; argc
; argc
--, argv
++)
522 _keybox_dump_cut_records (*argv
, from
, to
, stdout
);
525 else if (cmd
== aImportOpenPGP
)
528 import_openpgp ("-");
531 for (; argc
; argc
--, argv
++)
532 import_openpgp (*argv
);
536 else if ( cmd
== aFindByFpr
)
540 wrong_args ("kbxfile foingerprint");
541 fpr
= format_fingerprint ( argv
[1] );
543 log_error ("invalid formatted fingerprint\n");
546 kbxfile_search_by_fpr ( argv
[0], fpr
);
550 else if ( cmd
== aFindByKid
)
556 wrong_args ("kbxfile short-or-long-keyid");
557 mode
= format_keyid ( argv
[1], kid
);
559 log_error ("invalid formatted keyID\n");
562 kbxfile_search_by_kid ( argv
[0], kid
, mode
);
565 else if ( cmd
== aFindByUid
)
568 wrong_args ("kbxfile userID");
569 kbxfile_search_by_uid ( argv
[0], argv
[1] );
573 log_error ("unsupported action\n");
576 return 8; /*NEVER REACHED*/
583 /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
584 /* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
585 /* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
587 /* if( opt.debug ) */
588 /* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
589 rc
= rc
? rc
: log_get_errorcount(0)? 2 :
590 keybox_errors_seen
? 1 : 0;