Fixes (mostly from Colin Watson, a couple redone by me) to make Unix
[u/mdw/putty] / cmdgen.c
index e46e697..9911db1 100644 (file)
--- a/cmdgen.c
+++ b/cmdgen.c
@@ -119,7 +119,7 @@ void sk_cleanup(void)
 void showversion(void)
 {
     char *verstr = dupstr(ver);
-    verstr[0] = tolower(verstr[0]);
+    verstr[0] = tolower((unsigned char)verstr[0]);
     printf("PuTTYgen %s\n", verstr);
     sfree(verstr);
 }
@@ -128,7 +128,7 @@ void usage(int standalone)
 {
     fprintf(stderr,
            "Usage: puttygen ( keyfile | -t type [ -b bits ] )\n"
-           "                [ -C comment ] [ -P ]\n"
+           "                [ -C comment ] [ -P ] [ -q ]\n"
            "                [ -o output-keyfile ] [ -O type | -l | -L"
            " | -p ]\n");
     if (standalone)
@@ -149,6 +149,7 @@ void help(void)
            "  -b    specify number of bits when generating key\n"
            "  -C    change or specify key comment\n"
            "  -P    change key passphrase\n"
+           "  -q    quiet: do not display progress bar\n"
            "  -O    specify output type:\n"
            "           private             output PuTTY private key format\n"
            "           private-openssh     export OpenSSH private key\n"
@@ -232,7 +233,7 @@ static int move(char *from, char *to)
     return TRUE;
 }
 
-static char *blobfp(char *alg, int bits, char *blob, int bloblen)
+static char *blobfp(char *alg, int bits, unsigned char *blob, int bloblen)
 {
     char buffer[128];
     unsigned char digest[16];
@@ -269,7 +270,8 @@ int main(int argc, char **argv)
     int sshver = 0;
     struct ssh2_userkey *ssh2key = NULL;
     struct RSAKey *ssh1key = NULL;
-    char *ssh2blob = NULL, *ssh2alg = NULL;
+    unsigned char *ssh2blob = NULL;
+    char *ssh2alg = NULL;
     const struct ssh_signkey *ssh2algf = NULL;
     int ssh2bloblen;
     char *passphrase = NULL;
@@ -314,32 +316,54 @@ int main(int argc, char **argv)
                            *p++ = '\0';
                            val = p;
                        } else
-                           val = NULL;
+                            val = NULL;
+
                        if (!strcmp(opt, "-help")) {
-                           help();
-                           nogo = TRUE;
+                            if (val) {
+                                errs = TRUE;
+                                fprintf(stderr, "puttygen: option `-%s'"
+                                        " expects no argument\n", opt);
+                            } else {
+                                help();
+                                nogo = TRUE;
+                            }
                        } else if (!strcmp(opt, "-version")) {
-                           showversion();
-                           nogo = TRUE;
+                            if (val) {
+                                errs = TRUE;
+                                fprintf(stderr, "puttygen: option `-%s'"
+                                        " expects no argument\n", opt);
+                            } else {
+                                showversion();
+                                nogo = TRUE;
+                            }
                        } else if (!strcmp(opt, "-pgpfp")) {
-                            /* support "-pgpfp" for consistency with others */
-                            pgp_fingerprints();
-                            nogo = TRUE;
+                            if (val) {
+                                errs = TRUE;
+                                fprintf(stderr, "puttygen: option `-%s'"
+                                        " expects no argument\n", opt);
+                            } else {
+                                /* support --pgpfp for consistency */
+                                pgp_fingerprints();
+                                nogo = TRUE;
+                            }
                         }
                        /*
-                        * A sample option requiring an argument:
+                        * For long options requiring an argument, add
+                        * code along the lines of
                         * 
                         * else if (!strcmp(opt, "-output")) {
-                        *     if (!val)
-                        *         errs = TRUE, error(err_optnoarg, opt);
-                        *     else
+                        *     if (!val) {
+                        *         errs = TRUE;
+                         *         fprintf(stderr, "puttygen: option `-%s'"
+                         *                 " expects an argument\n", opt);
+                        *     } else
                         *         ofile = val;
                         * }
                         */
                        else {
                            errs = TRUE;
                            fprintf(stderr,
-                                   "puttygen: no such option `--%s'\n", opt);
+                                   "puttygen: no such option `-%s'\n", opt);
                        }
                    }
                    p = NULL;
@@ -490,11 +514,21 @@ int main(int argc, char **argv)
      * Bomb out if we've been asked to both load and generate a
      * key.
      */
-    if (keytype != NOKEYGEN && intype) {
+    if (keytype != NOKEYGEN && infile) {
        fprintf(stderr, "puttygen: cannot both load and generate a key\n");
        return 1;
     }
 
+    /* 
+     * We must save the private part when generating a new key.
+     */
+    if (keytype != NOKEYGEN &&
+       (outtype != PRIVATE && outtype != OPENSSH && outtype != SSHCOM)) {
+       fprintf(stderr, "puttygen: this would generate a new key but "
+               "discard the private part\n");
+       return 1;
+    }
+
     /*
      * Analyse the type of the input file, in case this affects our
      * course of action.
@@ -628,6 +662,11 @@ int main(int argc, char **argv)
 
        random_ref();
        entropy = get_random_data(bits / 8);
+       if (!entropy) {
+           fprintf(stderr, "puttygen: failed to collect entropy, "
+                   "could not generate key\n");
+           return 1;
+       }
        random_add_heavynoise(entropy, bits / 8);
        memset(entropy, 0, bits/8);
        sfree(entropy);
@@ -704,12 +743,12 @@ int main(int argc, char **argv)
            ssh1key = snew(struct RSAKey);
            if (!load_encrypted) {
                void *vblob;
-               char *blob;
+               unsigned char *blob;
                int n, l, bloblen;
 
                ret = rsakey_pubblob(&infilename, &vblob, &bloblen,
                                     &origcomment, &error);
-               blob = (char *)vblob;
+               blob = (unsigned char *)vblob;
 
                n = 4;                 /* skip modulus bits */
                
@@ -881,7 +920,7 @@ int main(int argc, char **argv)
            assert(ssh1key);
 
            if (outfile)
-               fp = f_open(outfilename, "w");
+               fp = f_open(outfilename, "w", FALSE);
            else
                fp = stdout;
            dec1 = bignum_decimal(ssh1key->exponent);
@@ -939,7 +978,7 @@ int main(int argc, char **argv)
                *p++ = '\0';
 
            if (outfile)
-               fp = f_open(outfilename, "w");
+               fp = f_open(outfilename, "w", FALSE);
            else
                fp = stdout;
            fprintf(fp, "%s\n", buffer);
@@ -969,7 +1008,7 @@ int main(int argc, char **argv)
            }
 
            if (outfile)
-               fp = f_open(outfilename, "w");
+               fp = f_open(outfilename, "w", FALSE);
            else
                fp = stdout;
            fprintf(fp, "%s\n", fingerprint);