LCOV - code coverage report
Current view: top level - sm - certreqgen-ui.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 236 0.0 %
Date: 2016-09-12 13:01:59 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* certreqgen-ui.c - Simple user interface for certreqgen.c
       2             :  * Copyright (C) 2007, 2010, 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 <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : #include <unistd.h>
      26             : #include <time.h>
      27             : #include <assert.h>
      28             : 
      29             : #include "gpgsm.h"
      30             : #include <gcrypt.h>
      31             : 
      32             : #include "i18n.h"
      33             : #include "ttyio.h"
      34             : #include "membuf.h"
      35             : 
      36             : 
      37             : /* Prompt for lines and append them to MB.  */
      38             : static void
      39           0 : ask_mb_lines (membuf_t *mb, const char *prefix)
      40             : {
      41           0 :   char *answer = NULL;
      42             : 
      43             :   do
      44             :     {
      45           0 :       xfree (answer);
      46           0 :       answer = tty_get ("> ");
      47           0 :       tty_kill_prompt ();
      48           0 :       trim_spaces (answer);
      49           0 :       if (*answer)
      50             :         {
      51           0 :           put_membuf_str (mb, prefix);
      52           0 :           put_membuf_str (mb, answer);
      53           0 :           put_membuf (mb, "\n", 1);
      54             :         }
      55             :     }
      56           0 :   while (*answer);
      57           0 :   xfree (answer);
      58           0 : }
      59             : 
      60             : /* Helper to store stuff in a membuf.  */
      61             : void
      62           0 : store_key_value_lf (membuf_t *mb, const char *key, const char *value)
      63             : {
      64           0 :   put_membuf_str (mb, key);
      65           0 :   put_membuf_str (mb, value);
      66           0 :   put_membuf (mb, "\n", 1);
      67           0 : }
      68             : 
      69             : /* Helper tp store a membuf create by mb_ask_lines into MB.  Returns
      70             :    -1 on error. */
      71             : int
      72           0 : store_mb_lines (membuf_t *mb, membuf_t *lines)
      73             : {
      74             :   char *p;
      75             : 
      76           0 :   if (get_membuf_len (lines))
      77             :     {
      78           0 :       put_membuf (lines, "", 1);
      79           0 :       p = get_membuf (lines, NULL);
      80           0 :       if (!p)
      81           0 :         return -1;
      82           0 :       put_membuf_str (mb, p);
      83           0 :       xfree (p);
      84             :     }
      85           0 :   return 0;
      86             : }
      87             : 
      88             : 
      89             : /* Chech whether we have a key for the key with HEXGRIP.  Returns NULL
      90             :    if not or a string describing the type of the key (RSA, ELG, DSA,
      91             :    etc..).  */
      92             : static const char *
      93           0 : check_keygrip (ctrl_t ctrl, const char *hexgrip)
      94             : {
      95             :   gpg_error_t err;
      96             :   ksba_sexp_t public;
      97             :   size_t publiclen;
      98             :   const char *algostr;
      99             : 
     100           0 :   if (hexgrip[0] == '&')
     101           0 :     hexgrip++;
     102             : 
     103           0 :   err = gpgsm_agent_readkey (ctrl, 0, hexgrip, &public);
     104           0 :   if (err)
     105           0 :     return NULL;
     106           0 :   publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
     107             : 
     108           0 :   get_pk_algo_from_canon_sexp (public, publiclen, &algostr);
     109           0 :   xfree (public);
     110             : 
     111           0 :   if (!algostr)
     112           0 :     return NULL;
     113           0 :   else if (!strcmp (algostr, "rsa"))
     114           0 :     return "RSA";
     115           0 :   else if (!strcmp (algostr, "dsa"))
     116           0 :     return "DSA";
     117           0 :   else if (!strcmp (algostr, "elg"))
     118           0 :     return "ELG";
     119           0 :   else if (!strcmp (algostr, "ecdsa"))
     120           0 :     return "ECDSA";
     121             :   else
     122           0 :     return NULL;
     123             : }
     124             : 
     125             : 
     126             : /* This function is used to create a certificate request from the
     127             :    command line.  In the past the similar gpgsm-gencert.sh script has
     128             :    been used for it; however that scripts requires a full Unix shell
     129             :    and thus is not suitable for the Windows port.  So here is the
     130             :    re-implementation.  */
     131             : void
     132           0 : gpgsm_gencertreq_tty (ctrl_t ctrl, estream_t output_stream)
     133             : {
     134             :   gpg_error_t err;
     135             :   char *answer;
     136             :   int selection;
     137           0 :   estream_t fp = NULL;
     138             :   int method;
     139           0 :   char *keytype_buffer = NULL;
     140             :   const char *keytype;
     141           0 :   char *keygrip = NULL;
     142             :   unsigned int nbits;
     143           0 :   int minbits = 1024;
     144           0 :   int maxbits = 4096;
     145           0 :   int defbits = 2048;
     146             :   const char *keyusage;
     147             :   char *subject_name;
     148             :   membuf_t mb_email, mb_dns, mb_uri, mb_result;
     149           0 :   char *result = NULL;
     150             :   const char *s, *s2;
     151             :   int selfsigned;
     152             : 
     153           0 :   answer = NULL;
     154           0 :   init_membuf (&mb_email, 100);
     155           0 :   init_membuf (&mb_dns, 100);
     156           0 :   init_membuf (&mb_uri, 100);
     157           0 :   init_membuf (&mb_result, 512);
     158             : 
     159             :  again:
     160             :   /* Get the type of the key.  */
     161           0 :   tty_printf (_("Please select what kind of key you want:\n"));
     162           0 :   tty_printf (_("   (%d) RSA\n"), 1 );
     163           0 :   tty_printf (_("   (%d) Existing key\n"), 2 );
     164           0 :   tty_printf (_("   (%d) Existing key from card\n"), 3 );
     165             : 
     166             :   do
     167             :     {
     168           0 :       xfree (answer);
     169           0 :       answer = tty_get (_("Your selection? "));
     170           0 :       tty_kill_prompt ();
     171           0 :       selection = *answer? atoi (answer): 1;
     172             :     }
     173           0 :   while (!(selection >= 1 && selection <= 3));
     174           0 :   method = selection;
     175             : 
     176             :   /* Get  size of the key.  */
     177           0 :   if (method == 1)
     178             :     {
     179           0 :       keytype = "RSA";
     180             :       for (;;)
     181             :         {
     182           0 :           xfree (answer);
     183           0 :           answer = tty_getf (_("What keysize do you want? (%u) "), defbits);
     184           0 :           tty_kill_prompt ();
     185           0 :           trim_spaces (answer);
     186           0 :           nbits = *answer? atoi (answer): defbits;
     187           0 :           if (nbits < minbits || nbits > maxbits)
     188           0 :             tty_printf(_("%s keysizes must be in the range %u-%u\n"),
     189             :                          "RSA", minbits, maxbits);
     190             :           else
     191             :             break; /* Okay.  */
     192           0 :         }
     193           0 :       tty_printf (_("Requested keysize is %u bits\n"), nbits);
     194             :       /* We round it up so that it better matches the word size.  */
     195           0 :       if (( nbits % 64))
     196             :         {
     197           0 :           nbits = ((nbits + 63) / 64) * 64;
     198           0 :           tty_printf (_("rounded up to %u bits\n"), nbits);
     199             :         }
     200             :     }
     201           0 :   else if (method == 2)
     202             :     {
     203             :       for (;;)
     204             :         {
     205           0 :           xfree (answer);
     206           0 :           answer = tty_get (_("Enter the keygrip: "));
     207           0 :           tty_kill_prompt ();
     208           0 :           trim_spaces (answer);
     209             : 
     210           0 :           if (!*answer)
     211           0 :             goto again;
     212           0 :           else if (strlen (answer) != 40 &&
     213           0 :                    !(answer[0] == '&' && strlen (answer+1) == 40))
     214           0 :             tty_printf (_("Not a valid keygrip (expecting 40 hex digits)\n"));
     215           0 :           else if (!(keytype = check_keygrip (ctrl, answer)) )
     216           0 :             tty_printf (_("No key with this keygrip\n"));
     217             :           else
     218           0 :             break; /* Okay.  */
     219           0 :         }
     220           0 :       xfree (keygrip);
     221           0 :       keygrip = answer;
     222           0 :       answer = NULL;
     223           0 :       nbits = 1024; /* A dummy value is sufficient.  */
     224             :     }
     225             :   else /* method == 3 */
     226             :     {
     227             :       char *serialno;
     228             :       strlist_t keypairlist, sl;
     229             :       int count;
     230             : 
     231           0 :       err = gpgsm_agent_scd_serialno (ctrl, &serialno);
     232           0 :       if (err)
     233             :         {
     234           0 :           tty_printf (_("error reading the card: %s\n"), gpg_strerror (err));
     235           0 :           goto again;
     236             :         }
     237           0 :       tty_printf (_("Serial number of the card: %s\n"), serialno);
     238           0 :       xfree (serialno);
     239             : 
     240           0 :       err = gpgsm_agent_scd_keypairinfo (ctrl, &keypairlist);
     241           0 :       if (err)
     242             :         {
     243           0 :           tty_printf (_("error reading the card: %s\n"), gpg_strerror (err));
     244           0 :           goto again;
     245             :         }
     246             : 
     247             :       do
     248             :         {
     249           0 :           tty_printf (_("Available keys:\n"));
     250           0 :           for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
     251           0 :             tty_printf ("   (%d) %s\n", count, sl->d);
     252           0 :           xfree (answer);
     253           0 :           answer = tty_get (_("Your selection? "));
     254           0 :           tty_kill_prompt ();
     255           0 :           trim_spaces (answer);
     256           0 :           selection = atoi (answer);
     257             :         }
     258           0 :       while (!(selection > 0 && selection < count));
     259             : 
     260           0 :       for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
     261           0 :         if (count == selection)
     262           0 :           break;
     263             : 
     264           0 :       s = sl->d;
     265           0 :       while (*s && !spacep (s))
     266           0 :         s++;
     267           0 :       while (spacep (s))
     268           0 :         s++;
     269             : 
     270           0 :       xfree (keygrip);
     271           0 :       keygrip = NULL;
     272           0 :       xfree (keytype_buffer);
     273           0 :       keytype_buffer = xasprintf ("card:%s", s);
     274           0 :       free_strlist (keypairlist);
     275           0 :       keytype = keytype_buffer;
     276           0 :       nbits = 1024; /* A dummy value is sufficient.  */
     277             :     }
     278             : 
     279             :   /* Ask for the key usage.  */
     280           0 :   tty_printf (_("Possible actions for a %s key:\n"), "RSA");
     281           0 :   tty_printf (_("   (%d) sign, encrypt\n"), 1 );
     282           0 :   tty_printf (_("   (%d) sign\n"), 2 );
     283           0 :   tty_printf (_("   (%d) encrypt\n"), 3 );
     284             :   do
     285             :     {
     286           0 :       xfree (answer);
     287           0 :       answer = tty_get (_("Your selection? "));
     288           0 :       tty_kill_prompt ();
     289           0 :       trim_spaces (answer);
     290           0 :       selection = *answer? atoi (answer): 1;
     291           0 :       switch (selection)
     292             :         {
     293           0 :         case 1: keyusage = "sign, encrypt"; break;
     294           0 :         case 2: keyusage = "sign"; break;
     295           0 :         case 3: keyusage = "encrypt"; break;
     296           0 :         default: keyusage = NULL; break;
     297             :         }
     298             :     }
     299           0 :   while (!keyusage);
     300             : 
     301             :   /* Get the subject name.  */
     302             :   do
     303             :     {
     304             :       size_t erroff, errlen;
     305             : 
     306           0 :       xfree (answer);
     307           0 :       answer = tty_get (_("Enter the X.509 subject name: "));
     308           0 :       tty_kill_prompt ();
     309           0 :       trim_spaces (answer);
     310           0 :       if (!*answer)
     311           0 :         tty_printf (_("No subject name given\n"));
     312           0 :       else if ( (err = ksba_dn_teststr (answer, 0, &erroff, &errlen)) )
     313             :         {
     314           0 :           if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
     315           0 :             tty_printf (_("Invalid subject name label '%.*s'\n"),
     316             :                         (int)errlen, answer+erroff);
     317             :           else
     318             :             {
     319             :               /* TRANSLATORS: The 22 in the second string is the
     320             :                  length of the first string up to the "%s".  Please
     321             :                  adjust it do the length of your translation.  The
     322             :                  second string is merely passed to atoi so you can
     323             :                  drop everything after the number.  */
     324           0 :               tty_printf (_("Invalid subject name '%s'\n"), answer);
     325           0 :               tty_printf ("%*s^\n",
     326           0 :                           atoi (_("22 translator: see "
     327             :                                   "certreg-ui.c:gpgsm_gencertreq_tty"))
     328           0 :                           + (int)erroff, "");
     329             :             }
     330           0 :           *answer = 0;
     331             :         }
     332             :     }
     333           0 :   while (!*answer);
     334           0 :   subject_name = answer;
     335           0 :   answer = NULL;
     336             : 
     337             :   /* Get the email addresses. */
     338           0 :   tty_printf (_("Enter email addresses"));
     339           0 :   tty_printf (_(" (end with an empty line):\n"));
     340           0 :   ask_mb_lines (&mb_email, "Name-Email: ");
     341             : 
     342             :   /* DNS names.  */
     343           0 :   tty_printf (_("Enter DNS names"));
     344           0 :   tty_printf (_(" (optional; end with an empty line):\n"));
     345           0 :   ask_mb_lines (&mb_dns, "Name-DNS: ");
     346             : 
     347             :   /* URIs.  */
     348           0 :   tty_printf (_("Enter URIs"));
     349           0 :   tty_printf (_(" (optional; end with an empty line):\n"));
     350           0 :   ask_mb_lines (&mb_uri, "Name-URI: ");
     351             : 
     352             : 
     353             :   /* Want a self-signed certificate?  */
     354           0 :   selfsigned = tty_get_answer_is_yes
     355           0 :     (_("Create self-signed certificate? (y/N) "));
     356             : 
     357             : 
     358             :   /* Put it all together.  */
     359           0 :   store_key_value_lf (&mb_result, "Key-Type: ", keytype);
     360             :   {
     361             :     char numbuf[30];
     362           0 :     snprintf (numbuf, sizeof numbuf, "%u", nbits);
     363           0 :     store_key_value_lf (&mb_result, "Key-Length: ", numbuf);
     364             :   }
     365           0 :   if (keygrip)
     366           0 :     store_key_value_lf (&mb_result, "Key-Grip: ", keygrip);
     367           0 :   store_key_value_lf (&mb_result, "Key-Usage: ", keyusage);
     368           0 :   if (selfsigned)
     369           0 :     store_key_value_lf (&mb_result, "Serial: ", "random");
     370           0 :   store_key_value_lf (&mb_result, "Name-DN: ", subject_name);
     371           0 :   if (store_mb_lines (&mb_result, &mb_email))
     372           0 :     goto mem_error;
     373           0 :   if (store_mb_lines (&mb_result, &mb_dns))
     374           0 :     goto mem_error;
     375           0 :   if (store_mb_lines (&mb_result, &mb_uri))
     376           0 :     goto mem_error;
     377           0 :   put_membuf (&mb_result, "", 1);
     378           0 :   result = get_membuf (&mb_result, NULL);
     379           0 :   if (!result)
     380           0 :     goto mem_error;
     381             : 
     382           0 :   tty_printf (_("These parameters are used:\n"));
     383           0 :   for (s=result; (s2 = strchr (s, '\n')); s = s2+1)
     384           0 :     tty_printf ("    %.*s\n", (int)(s2-s), s);
     385           0 :   tty_printf ("\n");
     386             : 
     387           0 :   if (!tty_get_answer_is_yes ("Proceed with creation? (y/N) "))
     388           0 :     goto leave;
     389             : 
     390             :   /* Now create a parameter file and generate the key.  */
     391           0 :   fp = es_fopenmem (0, "w+");
     392           0 :   if (!fp)
     393             :     {
     394           0 :       log_error (_("error creating temporary file: %s\n"), strerror (errno));
     395           0 :       goto leave;
     396             :     }
     397           0 :   es_fputs (result, fp);
     398           0 :   es_rewind (fp);
     399           0 :   if (selfsigned)
     400           0 :     tty_printf ("%s", _("Now creating self-signed certificate.  "));
     401             :   else
     402           0 :     tty_printf ("%s", _("Now creating certificate request.  "));
     403           0 :   tty_printf ("%s", _("This may take a while ...\n"));
     404             : 
     405             :   {
     406           0 :     int save_pem = ctrl->create_pem;
     407           0 :     ctrl->create_pem = 1; /* Force creation of PEM. */
     408           0 :     err = gpgsm_genkey (ctrl, fp, output_stream);
     409           0 :     ctrl->create_pem = save_pem;
     410             :   }
     411           0 :   if (!err)
     412             :     {
     413           0 :       if (selfsigned)
     414           0 :         tty_printf (_("Ready.\n"));
     415             :       else
     416           0 :         tty_printf
     417           0 :           (_("Ready.  You should now send this request to your CA.\n"));
     418             :     }
     419             : 
     420             : 
     421           0 :   goto leave;
     422             :  mem_error:
     423           0 :   log_error (_("resource problem: out of core\n"));
     424             :  leave:
     425           0 :   es_fclose (fp);
     426           0 :   xfree (answer);
     427           0 :   xfree (subject_name);
     428           0 :   xfree (keytype_buffer);
     429           0 :   xfree (keygrip);
     430           0 :   xfree (get_membuf (&mb_email, NULL));
     431           0 :   xfree (get_membuf (&mb_dns, NULL));
     432           0 :   xfree (get_membuf (&mb_uri, NULL));
     433           0 :   xfree (get_membuf (&mb_result, NULL));
     434           0 :   xfree (result);
     435           0 : }

Generated by: LCOV version 1.11