LCOV - code coverage report
Current view: top level - kbx - kbxutil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 191 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /* kbxutil.c - The Keybox utility
       2             :  * Copyright (C) 2000, 2001, 2004, 2007, 2011 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 3 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, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <errno.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <ctype.h>
      26             : #include <sys/stat.h>
      27             : #include <unistd.h>
      28             : #include <limits.h>
      29             : #include <assert.h>
      30             : 
      31             : #include <gpg-error.h>
      32             : #include "../common/logging.h"
      33             : #include "../common/argparse.h"
      34             : #include "../common/stringhelp.h"
      35             : #include "../common/utf8conv.h"
      36             : #include "i18n.h"
      37             : #include "keybox-defs.h"
      38             : #include "../common/init.h"
      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             :   aFindDups,
      57             :   aCut,
      58             : 
      59             :   oDebug,
      60             :   oDebugAll,
      61             : 
      62             :   oNoArmor,
      63             :   oFrom,
      64             :   oTo,
      65             : 
      66             :   aTest
      67             : };
      68             : 
      69             : 
      70             : static ARGPARSE_OPTS opts[] = {
      71             :   { 300, NULL, 0, N_("@Commands:\n ") },
      72             : 
      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" },
      80             : 
      81             :   { 301, NULL, 0, N_("@\nOptions:\n ") },
      82             : 
      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") },
      91             : 
      92             :   { oDebug, "debug"     ,4|16, N_("set debugging flags")},
      93             :   { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
      94             : 
      95             :   {0} /* end of list */
      96             : };
      97             : 
      98             : 
      99             : void myexit (int rc);
     100             : 
     101             : int keybox_errors_seen = 0;
     102             : 
     103             : 
     104             : static const char *
     105           0 : my_strusage( int level )
     106             : {
     107             :     const char *p;
     108           0 :     switch( level ) {
     109           0 :       case 11: p = "kbxutil (@GNUPG@)";
     110           0 :         break;
     111           0 :       case 13: p = VERSION; break;
     112           0 :       case 17: p = PRINTABLE_OS_NAME; break;
     113           0 :       case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
     114             : 
     115             :       case 1:
     116           0 :       case 40:  p =
     117             :             _("Usage: kbxutil [options] [files] (-h for help)");
     118           0 :         break;
     119           0 :       case 41:  p =
     120             :             _("Syntax: kbxutil [options] [files]\n"
     121             :               "List, export, import Keybox data\n");
     122           0 :         break;
     123             : 
     124             : 
     125           0 :       default:  p = NULL;
     126             :     }
     127           0 :     return p;
     128             : }
     129             : 
     130             : 
     131             : /* Used by gcry for logging */
     132             : static void
     133           0 : my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
     134             : {
     135             :   (void)dummy;
     136             : 
     137             :   /* Map the log levels.  */
     138           0 :   switch (level)
     139             :     {
     140           0 :     case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
     141           0 :     case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
     142           0 :     case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
     143           0 :     case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
     144           0 :     case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
     145           0 :     case GCRY_LOG_BUG:  level = GPGRT_LOG_BUG; break;
     146           0 :     case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
     147           0 :     default:            level = GPGRT_LOG_ERROR; break;
     148             :     }
     149           0 :   log_logv (level, fmt, arg_ptr);
     150           0 : }
     151             : 
     152             : 
     153             : 
     154             : /*  static void */
     155             : /*  wrong_args( const char *text ) */
     156             : /*  { */
     157             : /*      log_error("usage: kbxutil %s\n", text); */
     158             : /*      myexit ( 1 ); */
     159             : /*  } */
     160             : 
     161             : 
     162             : #if 0
     163             : static int
     164             : hextobyte( const byte *s )
     165             : {
     166             :     int c;
     167             : 
     168             :     if( *s >= '0' && *s <= '9' )
     169             :         c = 16 * (*s - '0');
     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');
     174             :     else
     175             :         return -1;
     176             :     s++;
     177             :     if( *s >= '0' && *s <= '9' )
     178             :         c += *s - '0';
     179             :     else if( *s >= 'A' && *s <= 'F' )
     180             :         c += 10 + *s - 'A';
     181             :     else if( *s >= 'a' && *s <= 'f' )
     182             :         c += 10 + *s - 'a';
     183             :     else
     184             :         return -1;
     185             :     return c;
     186             : }
     187             : #endif
     188             : 
     189             : #if 0
     190             : static char *
     191             : format_fingerprint ( const char *s )
     192             : {
     193             :     int i, c;
     194             :     byte fpr[20];
     195             : 
     196             :     for (i=0; i < 20 && *s; ) {
     197             :         if ( *s == ' ' || *s == '\t' ) {
     198             :             s++;
     199             :             continue;
     200             :         }
     201             :         c = hextobyte(s);
     202             :         if (c == -1) {
     203             :             return NULL;
     204             :         }
     205             :         fpr[i++] = c;
     206             :         s += 2;
     207             :     }
     208             :     return gcry_xstrdup ( fpr );
     209             : }
     210             : #endif
     211             : 
     212             : #if 0
     213             : static int
     214             : format_keyid ( const char *s, u32 *kid )
     215             : {
     216             :     char helpbuf[9];
     217             :     switch ( strlen ( s ) ) {
     218             :       case 8:
     219             :         kid[0] = 0;
     220             :         kid[1] = strtoul( s, NULL, 16 );
     221             :         return 10;
     222             : 
     223             :       case 16:
     224             :         mem2str( helpbuf, s, 9 );
     225             :         kid[0] = strtoul( helpbuf, NULL, 16 );
     226             :         kid[1] = strtoul( s+8, NULL, 16 );
     227             :         return 11;
     228             :     }
     229             :     return 0; /* error */
     230             : }
     231             : #endif
     232             : 
     233             : static char *
     234           0 : read_file (const char *fname, size_t *r_length)
     235             : {
     236             :   FILE *fp;
     237             :   char *buf;
     238             :   size_t buflen;
     239             : 
     240           0 :   if (!strcmp (fname, "-"))
     241             :     {
     242           0 :       size_t nread, bufsize = 0;
     243             : 
     244           0 :       fp = stdin;
     245           0 :       buf = NULL;
     246           0 :       buflen = 0;
     247             : #define NCHUNK 8192
     248             :       do
     249             :         {
     250           0 :           bufsize += NCHUNK;
     251           0 :           if (!buf)
     252           0 :             buf = xtrymalloc (bufsize);
     253             :           else
     254           0 :             buf = xtryrealloc (buf, bufsize);
     255           0 :           if (!buf)
     256           0 :             log_fatal ("can't allocate buffer: %s\n", strerror (errno));
     257             : 
     258           0 :           nread = fread (buf+buflen, 1, NCHUNK, fp);
     259           0 :           if (nread < NCHUNK && ferror (fp))
     260             :             {
     261           0 :               log_error ("error reading '[stdin]': %s\n", strerror (errno));
     262           0 :               xfree (buf);
     263           0 :               return NULL;
     264             :             }
     265           0 :           buflen += nread;
     266             :         }
     267           0 :       while (nread == NCHUNK);
     268             : #undef NCHUNK
     269             : 
     270             :     }
     271             :   else
     272             :     {
     273             :       struct stat st;
     274             : 
     275           0 :       fp = fopen (fname, "rb");
     276           0 :       if (!fp)
     277             :         {
     278           0 :           log_error ("can't open '%s': %s\n", fname, strerror (errno));
     279           0 :           return NULL;
     280             :         }
     281             : 
     282           0 :       if (fstat (fileno(fp), &st))
     283             :         {
     284           0 :           log_error ("can't stat '%s': %s\n", fname, strerror (errno));
     285           0 :           fclose (fp);
     286           0 :           return NULL;
     287             :         }
     288             : 
     289           0 :       buflen = st.st_size;
     290           0 :       buf = xtrymalloc (buflen+1);
     291           0 :       if (!buf)
     292           0 :         log_fatal ("can't allocate buffer: %s\n", strerror (errno));
     293           0 :       if (fread (buf, buflen, 1, fp) != 1)
     294             :         {
     295           0 :           log_error ("error reading '%s': %s\n", fname, strerror (errno));
     296           0 :           fclose (fp);
     297           0 :           xfree (buf);
     298           0 :           return NULL;
     299             :         }
     300           0 :       fclose (fp);
     301             :     }
     302             : 
     303           0 :   *r_length = buflen;
     304           0 :   return buf;
     305             : }
     306             : 
     307             : 
     308             : static void
     309           0 : dump_fpr (const unsigned char *buffer, size_t len)
     310             : {
     311             :   int i;
     312             : 
     313           0 :   for (i=0; i < len; i++, buffer++)
     314             :     {
     315           0 :       if (len == 20)
     316             :         {
     317           0 :           if (i == 10)
     318           0 :             putchar (' ');
     319           0 :           printf (" %02X%02X", buffer[0], buffer[1]);
     320           0 :           i++; buffer++;
     321             :         }
     322             :       else
     323             :         {
     324           0 :           if (i && !(i % 8))
     325           0 :             putchar (' ');
     326           0 :           printf (" %02X", buffer[0]);
     327             :         }
     328             :     }
     329           0 : }
     330             : 
     331             : 
     332             : static void
     333           0 : dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
     334             : {
     335           0 :   printf ("pub %2d %02X%02X%02X%02X",
     336             :           info->primary.algo,
     337           0 :           info->primary.keyid[4], info->primary.keyid[5],
     338           0 :           info->primary.keyid[6], info->primary.keyid[7] );
     339           0 :   dump_fpr (info->primary.fpr, info->primary.fprlen);
     340           0 :   putchar ('\n');
     341           0 :   if (info->nsubkeys)
     342             :     {
     343             :       struct _keybox_openpgp_key_info *k;
     344             : 
     345           0 :       k = &info->subkeys;
     346             :       do
     347             :         {
     348           0 :           printf ("sub %2d %02X%02X%02X%02X",
     349             :                   k->algo,
     350           0 :                   k->keyid[4], k->keyid[5],
     351           0 :                   k->keyid[6], k->keyid[7] );
     352           0 :           dump_fpr (k->fpr, k->fprlen);
     353           0 :           putchar ('\n');
     354           0 :           k = k->next;
     355             :         }
     356           0 :       while (k);
     357             :     }
     358           0 :   if (info->nuids)
     359             :     {
     360             :       struct _keybox_openpgp_uid_info *u;
     361             : 
     362           0 :       u = &info->uids;
     363             :       do
     364             :         {
     365           0 :           printf ("uid\t\t%.*s\n", (int)u->len, image + u->off);
     366           0 :           u = u->next;
     367             :         }
     368           0 :       while (u);
     369             :     }
     370           0 : }
     371             : 
     372             : 
     373             : static void
     374           0 : import_openpgp (const char *filename, int dryrun)
     375             : {
     376             :   gpg_error_t err;
     377             :   char *buffer;
     378             :   size_t buflen, nparsed;
     379             :   unsigned char *p;
     380             :   struct _keybox_openpgp_info info;
     381             :   KEYBOXBLOB blob;
     382             : 
     383           0 :   buffer = read_file (filename, &buflen);
     384           0 :   if (!buffer)
     385           0 :     return;
     386           0 :   p = (unsigned char *)buffer;
     387             :   for (;;)
     388             :     {
     389           0 :       err = _keybox_parse_openpgp (p, buflen, &nparsed, &info);
     390           0 :       assert (nparsed <= buflen);
     391           0 :       if (err)
     392             :         {
     393           0 :           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     394           0 :             break;
     395           0 :           if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
     396             :             {
     397             :               /* This is likely a v3 key packet with a non-RSA
     398             :                  algorithm.  These are keys from very early versions
     399             :                  of GnuPG (pre-OpenPGP).  */
     400             :             }
     401             :           else
     402             :             {
     403           0 :               fflush (stdout);
     404           0 :               log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
     405             :                         filename, gpg_strerror (err));
     406             :             }
     407             :         }
     408             :       else
     409             :         {
     410           0 :           if (dryrun)
     411           0 :             dump_openpgp_key (&info, p);
     412             :           else
     413             :             {
     414           0 :               err = _keybox_create_openpgp_blob (&blob, &info, p, nparsed,
     415             :                                                  NULL, 0);
     416           0 :               if (err)
     417             :                 {
     418           0 :                   fflush (stdout);
     419           0 :                   log_error ("%s: failed to create OpenPGP keyblock: %s\n",
     420             :                              filename, gpg_strerror (err));
     421             :                 }
     422             :               else
     423             :                 {
     424           0 :                   err = _keybox_write_blob (blob, stdout);
     425           0 :                   _keybox_release_blob (blob);
     426           0 :                   if (err)
     427             :                     {
     428           0 :                       fflush (stdout);
     429           0 :                       log_error ("%s: failed to write OpenPGP keyblock: %s\n",
     430             :                                  filename, gpg_strerror (err));
     431             :                     }
     432             :                 }
     433             :             }
     434             : 
     435           0 :           _keybox_destroy_openpgp_info (&info);
     436             :         }
     437           0 :       p += nparsed;
     438           0 :       buflen -= nparsed;
     439           0 :     }
     440           0 :   xfree (buffer);
     441             : }
     442             : 
     443             : 
     444             : 
     445             : 
     446             : int
     447           0 : main( int argc, char **argv )
     448             : {
     449             :   ARGPARSE_ARGS pargs;
     450           0 :   enum cmd_and_opt_values cmd = 0;
     451           0 :   unsigned long from = 0, to = ULONG_MAX;
     452           0 :   int dry_run = 0;
     453             : 
     454           0 :   early_system_init ();
     455           0 :   set_strusage( my_strusage );
     456           0 :   gcry_control (GCRYCTL_DISABLE_SECMEM);
     457           0 :   log_set_prefix ("kbxutil", 1);
     458             : 
     459             :   /* Make sure that our subsystems are ready.  */
     460           0 :   i18n_init ();
     461           0 :   init_common_subsystems (&argc, &argv);
     462             : 
     463             :   /* Check that the libraries are suitable.  Do it here because
     464             :      the option parsing may need services of the library.  */
     465           0 :   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
     466             :     {
     467           0 :       log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
     468             :                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
     469             :     }
     470             : 
     471           0 :   gcry_set_log_handler (my_gcry_logger, NULL);
     472             : 
     473             :   /*create_dotlock(NULL); register locking cleanup */
     474             : 
     475             :   /* We need to use the gcry malloc function because jnlib uses them.  */
     476           0 :   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
     477           0 :   ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
     478             : 
     479             : 
     480           0 :   pargs.argc = &argc;
     481           0 :   pargs.argv = &argv;
     482           0 :   pargs.flags=  1;  /* do not remove the args */
     483           0 :   while (arg_parse( &pargs, opts) )
     484             :     {
     485           0 :       switch (pargs.r_opt)
     486             :         {
     487             :         case oVerbose:
     488             :           /*opt.verbose++;*/
     489             :           /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
     490           0 :           break;
     491             :         case oDebug:
     492             :           /*opt.debug |= pargs.r.ret_ulong; */
     493           0 :           break;
     494             :         case oDebugAll:
     495             :           /*opt.debug = ~0;*/
     496           0 :           break;
     497             : 
     498             :         case aFindByFpr:
     499             :         case aFindByKid:
     500             :         case aFindByUid:
     501             :         case aStats:
     502             :         case aImportOpenPGP:
     503             :         case aFindDups:
     504             :         case aCut:
     505           0 :           cmd = pargs.r_opt;
     506           0 :           break;
     507             : 
     508           0 :         case oFrom: from = pargs.r.ret_ulong; break;
     509           0 :         case oTo: to = pargs.r.ret_ulong; break;
     510             : 
     511           0 :         case oDryRun: dry_run = 1; break;
     512             : 
     513             :         default:
     514           0 :           pargs.err = 2;
     515           0 :           break;
     516             :         }
     517             :     }
     518             : 
     519           0 :   if (to < from)
     520           0 :     log_error ("record number of \"--to\" is lower than \"--from\" one\n");
     521             : 
     522             : 
     523           0 :   if (log_get_errorcount(0) )
     524           0 :     myexit(2);
     525             : 
     526           0 :   if (!cmd)
     527             :     { /* Default is to list a KBX file */
     528           0 :       if (!argc)
     529           0 :         _keybox_dump_file (NULL, 0, stdout);
     530             :       else
     531             :         {
     532           0 :           for (; argc; argc--, argv++)
     533           0 :             _keybox_dump_file (*argv, 0, stdout);
     534             :         }
     535             :     }
     536           0 :   else if (cmd == aStats )
     537             :     {
     538           0 :       if (!argc)
     539           0 :         _keybox_dump_file (NULL, 1, stdout);
     540             :       else
     541             :         {
     542           0 :           for (; argc; argc--, argv++)
     543           0 :             _keybox_dump_file (*argv, 1, stdout);
     544             :         }
     545             :     }
     546           0 :   else if (cmd == aFindDups )
     547             :     {
     548           0 :       if (!argc)
     549           0 :         _keybox_dump_find_dups (NULL, 0, stdout);
     550             :       else
     551             :         {
     552           0 :           for (; argc; argc--, argv++)
     553           0 :             _keybox_dump_find_dups (*argv, 0, stdout);
     554             :         }
     555             :     }
     556           0 :   else if (cmd == aCut )
     557             :     {
     558           0 :       if (!argc)
     559           0 :         _keybox_dump_cut_records (NULL, from, to, stdout);
     560             :       else
     561             :         {
     562           0 :           for (; argc; argc--, argv++)
     563           0 :             _keybox_dump_cut_records (*argv, from, to, stdout);
     564             :         }
     565             :     }
     566           0 :   else if (cmd == aImportOpenPGP)
     567             :     {
     568           0 :       if (!argc)
     569           0 :         import_openpgp ("-", dry_run);
     570             :       else
     571             :         {
     572           0 :           for (; argc; argc--, argv++)
     573           0 :             import_openpgp (*argv, dry_run);
     574             :         }
     575             :     }
     576             : #if 0
     577             :   else if ( cmd == aFindByFpr )
     578             :     {
     579             :       char *fpr;
     580             :       if ( argc != 2 )
     581             :         wrong_args ("kbxfile foingerprint");
     582             :       fpr = format_fingerprint ( argv[1] );
     583             :       if ( !fpr )
     584             :         log_error ("invalid formatted fingerprint\n");
     585             :       else
     586             :         {
     587             :           kbxfile_search_by_fpr ( argv[0], fpr );
     588             :           gcry_free ( fpr );
     589             :         }
     590             :     }
     591             :   else if ( cmd == aFindByKid )
     592             :     {
     593             :       u32 kid[2];
     594             :       int mode;
     595             : 
     596             :       if ( argc != 2 )
     597             :         wrong_args ("kbxfile short-or-long-keyid");
     598             :       mode = format_keyid ( argv[1], kid );
     599             :       if ( !mode )
     600             :         log_error ("invalid formatted keyID\n");
     601             :       else
     602             :         {
     603             :           kbxfile_search_by_kid ( argv[0], kid, mode );
     604             :         }
     605             :     }
     606             :   else if ( cmd == aFindByUid )
     607             :     {
     608             :       if ( argc != 2 )
     609             :         wrong_args ("kbxfile userID");
     610             :       kbxfile_search_by_uid ( argv[0], argv[1] );
     611             :     }
     612             : #endif
     613             :   else
     614           0 :       log_error ("unsupported action\n");
     615             : 
     616           0 :   myexit(0);
     617           0 :   return 8; /*NEVER REACHED*/
     618             : }
     619             : 
     620             : 
     621             : void
     622           0 : myexit( int rc )
     623             : {
     624             :   /*    if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
     625             : /*      gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
     626             : /*      gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
     627             :   /*    }*/
     628             : /*      if( opt.debug ) */
     629             : /*      gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
     630           0 :     rc = rc? rc : log_get_errorcount(0)? 2 :
     631           0 :                         keybox_errors_seen? 1 : 0;
     632           0 :     exit(rc );
     633             : }

Generated by: LCOV version 1.11