LCOV - code coverage report
Current view: top level - tests - run-genkey.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 229 0.0 %
Date: 2018-11-15 08:49:49 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* run-genkey.c  - Test tool to perform key generation
       2             :  * Copyright (C) 2016 g10 Code GmbH
       3             :  *
       4             :  * This file is part of GPGME.
       5             :  *
       6             :  * GPGME is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * GPGME is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : /* We need to include config.h so that we know whether we are building
      21             :    with large file system (LFS) support. */
      22             : #ifdef HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : 
      26             : #include <stdlib.h>
      27             : #include <stdio.h>
      28             : #include <string.h>
      29             : #include <assert.h>
      30             : 
      31             : #include <gpgme.h>
      32             : 
      33             : #define PGM "run-genkey"
      34             : 
      35             : #include "run-support.h"
      36             : 
      37             : 
      38             : static int verbose;
      39             : 
      40             : 
      41             : /* Tokenize STRING using the set of delimiters in DELIM.  Leading
      42             :  * spaces and tabs are removed from all tokens.  The caller must free
      43             :  * the result.
      44             :  *
      45             :  * Returns: A malloced and NULL delimited array with the tokens.  On
      46             :  *          memory error NULL is returned and ERRNO is set.
      47             :  */
      48             : static char **
      49           0 : strtokenize (const char *string, const char *delim)
      50             : {
      51             :   const char *s;
      52             :   size_t fields;
      53             :   size_t bytes, n;
      54             :   char *buffer;
      55             :   char *p, *px, *pend;
      56             :   char **result;
      57             : 
      58             :   /* Count the number of fields.  */
      59           0 :   for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
      60           0 :     fields++;
      61           0 :   fields++; /* Add one for the terminating NULL.  */
      62             : 
      63             :   /* Allocate an array for all fields, a terminating NULL, and space
      64             :      for a copy of the string.  */
      65           0 :   bytes = fields * sizeof *result;
      66           0 :   if (bytes / sizeof *result != fields)
      67             :     {
      68           0 :       gpg_err_set_errno (ENOMEM);
      69           0 :       return NULL;
      70             :     }
      71           0 :   n = strlen (string) + 1;
      72           0 :   bytes += n;
      73           0 :   if (bytes < n)
      74             :     {
      75           0 :       gpg_err_set_errno (ENOMEM);
      76           0 :       return NULL;
      77             :     }
      78           0 :   result = malloc (bytes);
      79           0 :   if (!result)
      80           0 :     return NULL;
      81           0 :   buffer = (char*)(result + fields);
      82             : 
      83             :   /* Copy and parse the string.  */
      84           0 :   strcpy (buffer, string);
      85           0 :   for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
      86             :     {
      87           0 :       *pend = 0;
      88           0 :       while (*p == ' ' || *p == '\t')
      89           0 :         p++;
      90           0 :       for (px = pend - 1; px >= p && (*px == ' ' || *px == '\t'); px--)
      91           0 :         *px = 0;
      92           0 :       result[n++] = p;
      93             :     }
      94           0 :   while (*p == ' ' || *p == '\t')
      95           0 :     p++;
      96           0 :   for (px = p + strlen (p) - 1; px >= p && (*px == ' ' || *px == '\t'); px--)
      97           0 :     *px = 0;
      98           0 :   result[n++] = p;
      99           0 :   result[n] = NULL;
     100             : 
     101           0 :   assert ((char*)(result + n + 1) == buffer);
     102             : 
     103           0 :   return result;
     104             : }
     105             : 
     106             : 
     107             : static gpg_error_t
     108           0 : status_cb (void *opaque, const char *keyword, const char *value)
     109             : {
     110             :   (void)opaque;
     111           0 :   fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
     112           0 :   return 0;
     113             : }
     114             : 
     115             : 
     116             : static void
     117           0 : progress_cb (void *opaque, const char *what, int type, int current, int total)
     118             : {
     119             :   (void)opaque;
     120             :   (void)type;
     121             : 
     122           0 :   if (total)
     123           0 :     fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
     124             :              nonnull (what),
     125           0 :              (unsigned)(((double)current / total) * 100), current, total);
     126             :   else
     127           0 :     fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
     128           0 :   fflush (stderr);
     129           0 : }
     130             : 
     131             : 
     132             : static unsigned long
     133           0 : parse_expire_string (const char *string)
     134             : {
     135             :   unsigned long seconds;
     136             : 
     137           0 :   if (!string || !*string || !strcmp (string, "none")
     138           0 :       || !strcmp (string, "never") || !strcmp (string, "-"))
     139           0 :     seconds = 0;
     140           0 :   else if (strspn (string, "01234567890") == strlen (string))
     141           0 :     seconds = strtoul (string, NULL, 10);
     142             :   else
     143             :     {
     144           0 :       fprintf (stderr, PGM ": invalid value '%s'\n", string);
     145           0 :       exit (1);
     146             :     }
     147             : 
     148           0 :   return seconds;
     149             : }
     150             : 
     151             : 
     152             : /* Parse a usage string and return flags for gpgme_op_createkey.  */
     153             : static unsigned int
     154           0 : parse_usage_string (const char *string)
     155             : {
     156             :   gpg_error_t err;
     157           0 :   char **tokens = NULL;
     158             :   const char *s;
     159             :   int i;
     160           0 :   unsigned int flags = 0;
     161             : 
     162           0 :   tokens = strtokenize (string, " \t,");
     163           0 :   if (!tokens)
     164             :     {
     165           0 :       err = gpg_error_from_syserror ();
     166           0 :       fprintf (stderr, PGM": strtokenize failed: %s\n", gpg_strerror (err));
     167           0 :       exit (1);
     168             :     }
     169             : 
     170           0 :   for (i=0; (s = tokens[i]); i++)
     171             :     {
     172           0 :       if (!*s)
     173             :         ;
     174           0 :       else if (!strcmp (s, "default"))
     175             :         ;
     176           0 :       else if (!strcmp (s, "sign"))
     177           0 :         flags |= GPGME_CREATE_SIGN;
     178           0 :       else if (!strcmp (s, "encr"))
     179           0 :         flags |= GPGME_CREATE_ENCR;
     180           0 :       else if (!strcmp (s, "cert"))
     181           0 :         flags |= GPGME_CREATE_CERT;
     182           0 :       else if (!strcmp (s, "auth"))
     183           0 :         flags |= GPGME_CREATE_AUTH;
     184             :       else
     185             :         {
     186           0 :           free (tokens);
     187           0 :           fprintf (stderr, PGM": invalid value '%s': %s\n",
     188             :                    string, "bad usage");
     189           0 :           exit (1);
     190             :         }
     191             :     }
     192             : 
     193           0 :   free (tokens);
     194           0 :   return flags;
     195             : }
     196             : 
     197             : 
     198             : 
     199             : static int
     200           0 : show_usage (int ex)
     201             : {
     202           0 :   fputs ("usage: " PGM " [options] ARGS\n"
     203             :          "         args: USERID [ALGO [USAGE [EXPIRESECONDS]]]\n"
     204             :          "   for addkey: FPR    [ALGO [USAGE [EXPIRESECONDS]]]\n"
     205             :          "   for adduid: FPR    USERID\n"
     206             :          "   for revuid: FPR    USERID\n"
     207             :          "   for set-primary: FPR    USERID\n"
     208             :          "Options:\n"
     209             :          "  --addkey         add a subkey to the key with FPR\n"
     210             :          "  --adduid         add a user id to the key with FPR\n"
     211             :          "  --revuid         revoke a user id from the key with FPR\n"
     212             :          "  --set-primary    set the primary key flag on USERID\n"
     213             :          "  --verbose        run in verbose mode\n"
     214             :          "  --status         print status lines from the backend\n"
     215             :          "  --progress       print progress info\n"
     216             :          "  --openpgp        use the OpenPGP protocol (default)\n"
     217             :          "  --cms            use the CMS protocol\n"
     218             :          "  --loopback       use a loopback pinentry\n"
     219             :          "  --unprotected    do not use a passphrase\n"
     220             :          "  --force          do not check for a duplicated user id\n"
     221             :          , stderr);
     222           0 :   exit (ex);
     223             : }
     224             : 
     225             : 
     226             : int
     227           0 : main (int argc, char **argv)
     228             : {
     229           0 :   int last_argc = -1;
     230             :   gpgme_error_t err;
     231             :   gpgme_ctx_t ctx;
     232           0 :   gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
     233           0 :   int print_status = 0;
     234           0 :   int print_progress = 0;
     235           0 :   int use_loopback = 0;
     236           0 :   int addkey = 0;
     237           0 :   int adduid = 0;
     238           0 :   int revuid = 0;
     239           0 :   int setpri = 0;
     240             :   const char *userid;
     241           0 :   const char *algo = NULL;
     242           0 :   const char *newuserid = NULL;
     243           0 :   unsigned int flags = 0;
     244           0 :   unsigned long expire = 0;
     245             :   gpgme_genkey_result_t result;
     246             : 
     247           0 :   if (argc)
     248           0 :     { argc--; argv++; }
     249             : 
     250           0 :   while (argc && last_argc != argc )
     251             :     {
     252           0 :       last_argc = argc;
     253           0 :       if (!strcmp (*argv, "--"))
     254             :         {
     255           0 :           argc--; argv++;
     256           0 :           break;
     257             :         }
     258           0 :       else if (!strcmp (*argv, "--help"))
     259           0 :         show_usage (0);
     260           0 :       else if (!strcmp (*argv, "--addkey"))
     261             :         {
     262           0 :           addkey = 1;
     263           0 :           adduid = 0;
     264           0 :           revuid = 0;
     265           0 :           setpri = 0;
     266           0 :           argc--; argv++;
     267             :         }
     268           0 :       else if (!strcmp (*argv, "--adduid"))
     269             :         {
     270           0 :           addkey = 0;
     271           0 :           adduid = 1;
     272           0 :           revuid = 0;
     273           0 :           setpri = 0;
     274           0 :           argc--; argv++;
     275             :         }
     276           0 :       else if (!strcmp (*argv, "--revuid"))
     277             :         {
     278           0 :           addkey = 0;
     279           0 :           adduid = 0;
     280           0 :           revuid = 1;
     281           0 :           setpri = 0;
     282           0 :           argc--; argv++;
     283             :         }
     284           0 :       else if (!strcmp (*argv, "--set-primary"))
     285             :         {
     286           0 :           addkey = 0;
     287           0 :           adduid = 0;
     288           0 :           revuid = 0;
     289           0 :           setpri = 1;
     290           0 :           argc--; argv++;
     291             :         }
     292           0 :       else if (!strcmp (*argv, "--verbose"))
     293             :         {
     294           0 :           verbose = 1;
     295           0 :           argc--; argv++;
     296             :         }
     297           0 :       else if (!strcmp (*argv, "--status"))
     298             :         {
     299           0 :           print_status = 1;
     300           0 :           argc--; argv++;
     301             :         }
     302           0 :       else if (!strcmp (*argv, "--progress"))
     303             :         {
     304           0 :           print_progress = 1;
     305           0 :           argc--; argv++;
     306             :         }
     307           0 :       else if (!strcmp (*argv, "--openpgp"))
     308             :         {
     309           0 :           protocol = GPGME_PROTOCOL_OpenPGP;
     310           0 :           argc--; argv++;
     311             :         }
     312           0 :       else if (!strcmp (*argv, "--cms"))
     313             :         {
     314           0 :           protocol = GPGME_PROTOCOL_CMS;
     315           0 :           argc--; argv++;
     316             :         }
     317           0 :       else if (!strcmp (*argv, "--loopback"))
     318             :         {
     319           0 :           use_loopback = 1;
     320           0 :           argc--; argv++;
     321             :         }
     322           0 :       else if (!strcmp (*argv, "--unprotected"))
     323             :         {
     324           0 :           flags |= GPGME_CREATE_NOPASSWD;
     325           0 :           argc--; argv++;
     326             :         }
     327           0 :       else if (!strcmp (*argv, "--force"))
     328             :         {
     329           0 :           flags |= GPGME_CREATE_FORCE;
     330           0 :           argc--; argv++;
     331             :         }
     332           0 :       else if (!strncmp (*argv, "--", 2))
     333           0 :         show_usage (1);
     334             :     }
     335             : 
     336           0 :   if (adduid || revuid || setpri)
     337             :     {
     338           0 :       if (argc != 2)
     339           0 :         show_usage (1);
     340           0 :       userid = argv[0];
     341           0 :       newuserid = argv[1];
     342             :     }
     343             :   else
     344             :     {
     345           0 :       if (!argc || argc > 4)
     346           0 :         show_usage (1);
     347           0 :       userid = argv[0];
     348           0 :       if (argc > 1)
     349           0 :         algo = argv[1];
     350           0 :       if (argc > 2)
     351           0 :         flags |= parse_usage_string (argv[2]);
     352           0 :       if (argc > 3)
     353           0 :         expire = parse_expire_string (argv[3]);
     354             :     }
     355             : 
     356           0 :   init_gpgme (protocol);
     357             : 
     358           0 :   err = gpgme_new (&ctx);
     359           0 :   fail_if_err (err);
     360           0 :   gpgme_set_protocol (ctx, protocol);
     361           0 :   gpgme_set_armor (ctx, 1);
     362           0 :   if (print_status)
     363             :     {
     364           0 :       gpgme_set_status_cb (ctx, status_cb, NULL);
     365           0 :       gpgme_set_ctx_flag (ctx, "full-status", "1");
     366             :     }
     367           0 :   if (print_progress)
     368           0 :     gpgme_set_progress_cb (ctx, progress_cb, NULL);
     369           0 :   if (use_loopback)
     370             :     {
     371           0 :       gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
     372           0 :       gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
     373             :     }
     374             : 
     375           0 :   if (addkey || adduid || revuid || setpri)
     376           0 :     {
     377             :       gpgme_key_t akey;
     378             : 
     379           0 :       err = gpgme_get_key (ctx, userid, &akey, 1);
     380           0 :       if (err)
     381             :         {
     382           0 :           fprintf (stderr, PGM ": error getting secret key for '%s': %s\n",
     383             :                    userid, gpg_strerror (err));
     384           0 :           exit (1);
     385             :         }
     386             : 
     387           0 :       if (addkey)
     388             :         {
     389           0 :           err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
     390           0 :           if (err)
     391             :             {
     392           0 :               fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
     393             :                        gpg_strerror (err));
     394           0 :               exit (1);
     395             :             }
     396             :         }
     397           0 :       else if (adduid)
     398             :         {
     399           0 :           err = gpgme_op_adduid (ctx, akey, newuserid, flags);
     400           0 :           if (err)
     401             :             {
     402           0 :               fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
     403             :                        gpg_strerror (err));
     404           0 :               exit (1);
     405             :             }
     406             :         }
     407           0 :       else if (revuid)
     408             :         {
     409           0 :           err = gpgme_op_revuid (ctx, akey, newuserid, flags);
     410           0 :           if (err)
     411             :             {
     412           0 :               fprintf (stderr, PGM ": gpgme_op_revuid failed: %s\n",
     413             :                        gpg_strerror (err));
     414           0 :               exit (1);
     415             :             }
     416             :         }
     417           0 :       else if (setpri)
     418             :         {
     419           0 :           err = gpgme_op_set_uid_flag (ctx, akey, newuserid, "primary", NULL);
     420           0 :           if (err)
     421             :             {
     422           0 :               fprintf (stderr, PGM ": gpgme_op_set_uid_flag failed: %s\n",
     423             :                        gpg_strerror (err));
     424           0 :               exit (1);
     425             :             }
     426             :         }
     427           0 :       gpgme_key_unref (akey);
     428             :     }
     429             :   else
     430             :     {
     431           0 :       err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags);
     432           0 :       if (err)
     433             :         {
     434           0 :           fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n",
     435             :                    gpg_strerror (err));
     436           0 :           exit (1);
     437             :         }
     438             :     }
     439             : 
     440           0 :   if (!setpri)
     441             :     {
     442           0 :       result = gpgme_op_genkey_result (ctx);
     443           0 :       if (!result)
     444             :         {
     445           0 :           fprintf (stderr, PGM": gpgme_op_genkey_result returned NULL\n");
     446           0 :           exit (1);
     447             :         }
     448             : 
     449           0 :       printf ("Generated key: %s (%s)\n",
     450           0 :               result->fpr ? result->fpr : "none",
     451           0 :               result->primary ? (result->sub ? "primary, sub" : "primary")
     452           0 :               /**/            : (result->sub ? "sub" : "none"));
     453             : 
     454           0 :       if (result->fpr && strlen (result->fpr) < 40)
     455           0 :         fprintf (stderr, PGM": generated key has unexpected fingerprint\n");
     456           0 :       if (!result->primary)
     457           0 :         fprintf (stderr, PGM": primary key was not generated\n");
     458           0 :       if (!result->sub)
     459           0 :         fprintf (stderr, PGM": sub key was not generated\n");
     460           0 :       if (!result->uid)
     461           0 :         fprintf (stderr, PGM": uid was not generated\n");
     462             :     }
     463             : 
     464           0 :   gpgme_release (ctx);
     465           0 :   return 0;
     466             : }

Generated by: LCOV version 1.13