]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Centralise public-key output code into sshpubk.c.
authorSimon Tatham <anakin@pobox.com>
Tue, 12 May 2015 12:42:26 +0000 (13:42 +0100)
committerSimon Tatham <anakin@pobox.com>
Tue, 12 May 2015 13:56:38 +0000 (14:56 +0100)
There was a fair amount of duplication between Windows and Unix
PuTTYgen, and some confusion over writing things to FILE * and
formatting them internally into strings. I think all the public-key
output code now lives in sshpubk.c, and there's only one copy of the
code to generate each format.

cmdgen.c
ssh.h
sshpubk.c
windows/winpgen.c

index adfe027f5e727136bc52d9c3239ec307f8dba3c0..aa03cb544bacebdf9069c307d2965528d97e9478 100644 (file)
--- a/cmdgen.c
+++ b/cmdgen.c
@@ -173,56 +173,6 @@ void help(void)
            );
 }
 
-static int save_ssh2_pubkey(char *filename, char *comment,
-                           void *v_pub_blob, int pub_len)
-{
-    unsigned char *pub_blob = (unsigned char *)v_pub_blob;
-    char *p;
-    int i, column;
-    FILE *fp;
-
-    if (filename) {
-       fp = fopen(filename, "wb");
-       if (!fp)
-           return 0;
-    } else
-       fp = stdout;
-
-    fprintf(fp, "---- BEGIN SSH2 PUBLIC KEY ----\n");
-
-    if (comment) {
-       fprintf(fp, "Comment: \"");
-       for (p = comment; *p; p++) {
-           if (*p == '\\' || *p == '\"')
-               fputc('\\', fp);
-           fputc(*p, fp);
-       }
-       fprintf(fp, "\"\n");
-    }
-
-    i = 0;
-    column = 0;
-    while (i < pub_len) {
-       char buf[5];
-       int n = (pub_len - i < 3 ? pub_len - i : 3);
-       base64_encode_atom(pub_blob + i, n, buf);
-       i += n;
-       buf[4] = '\0';
-       fputs(buf, fp);
-       if (++column >= 16) {
-           fputc('\n', fp);
-           column = 0;
-       }
-    }
-    if (column > 0)
-       fputc('\n', fp);
-    
-    fprintf(fp, "---- END SSH2 PUBLIC KEY ----\n");
-    if (filename)
-       fclose(fp);
-    return 1;
-}
-
 static int move(char *from, char *to)
 {
     int ret;
@@ -990,80 +940,33 @@ int main(int argc, char **argv)
 
       case PUBLIC:
       case PUBLICO:
-       if (sshver == 1) {
-           FILE *fp;
-           char *dec1, *dec2;
+        {
+            FILE *fp;
 
-           assert(ssh1key);
+            if (outfile)
+                fp = f_open(outfilename, "w", FALSE);
+            else
+                fp = stdout;
 
-           if (outfile)
-               fp = f_open(outfilename, "w", FALSE);
-           else
-               fp = stdout;
-           dec1 = bignum_decimal(ssh1key->exponent);
-           dec2 = bignum_decimal(ssh1key->modulus);
-           fprintf(fp, "%d %s %s %s\n", bignum_bitcount(ssh1key->modulus),
-                   dec1, dec2, ssh1key->comment);
-           sfree(dec1);
-           sfree(dec2);
-           if (outfile)
-               fclose(fp);
-       } else if (outtype == PUBLIC) {
-           if (!ssh2blob) {
-               assert(ssh2key);
-               ssh2blob = ssh2key->alg->public_blob(ssh2key->data,
-                                                    &ssh2bloblen);
-           }
-           save_ssh2_pubkey(outfile, ssh2key ? ssh2key->comment : origcomment,
-                            ssh2blob, ssh2bloblen);
-       } else if (outtype == PUBLICO) {
-           char *buffer, *p;
-           int i;
-           FILE *fp;
+            if (sshver == 1) {
+                ssh1_write_pubkey(fp, ssh1key);
+            } else {
+                if (!ssh2blob) {
+                    assert(ssh2key);
+                    ssh2blob = ssh2key->alg->public_blob(ssh2key->data,
+                                                         &ssh2bloblen);
+                }
 
-           if (!ssh2blob) {
-               assert(ssh2key);
-               ssh2blob = ssh2key->alg->public_blob(ssh2key->data,
-                                                    &ssh2bloblen);
-           }
-           if (!ssh2alg) {
-               assert(ssh2key);
-               ssh2alg = ssh2key->alg->name;
-           }
-           if (ssh2key)
-               comment = ssh2key->comment;
-           else
-               comment = origcomment;
-
-           buffer = snewn(strlen(ssh2alg) +
-                          4 * ((ssh2bloblen+2) / 3) +
-                          strlen(comment) + 3, char);
-           strcpy(buffer, ssh2alg);
-           p = buffer + strlen(buffer);
-           *p++ = ' ';
-           i = 0;
-           while (i < ssh2bloblen) {
-               int n = (ssh2bloblen - i < 3 ? ssh2bloblen - i : 3);
-               base64_encode_atom(ssh2blob + i, n, p);
-               i += n;
-               p += 4;
-           }
-           if (*comment) {
-               *p++ = ' ';
-               strcpy(p, comment);
-           } else
-               *p++ = '\0';
+                ssh2_write_pubkey(fp, ssh2key ? ssh2key->comment : origcomment,
+                                  ssh2blob, ssh2bloblen,
+                                  (outtype == PUBLIC ?
+                                   SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 :
+                                   SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH));
+            }
 
-           if (outfile)
-               fp = f_open(outfilename, "w", FALSE);
-           else
-               fp = stdout;
-           fprintf(fp, "%s\n", buffer);
            if (outfile)
                fclose(fp);
-
-           sfree(buffer);
-       }
+        }
        break;
 
       case FP:
diff --git a/ssh.h b/ssh.h
index ec4f1f996896040aadb9b20786a608760466e7fd..4e36ad4584ae8aa2893ab7e154926fcce11ca746 100644 (file)
--- a/ssh.h
+++ b/ssh.h
@@ -716,6 +716,12 @@ enum {
     SSH_KEYTYPE_SSH2_PUBLIC_RFC4716,
     SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH
 };
+char *ssh1_pubkey_str(struct RSAKey *ssh1key);
+void ssh1_write_pubkey(FILE *fp, struct RSAKey *ssh1key);
+char *ssh2_pubkey_openssh_str(struct ssh2_userkey *key);
+void ssh2_write_pubkey(FILE *fp, const char *comment,
+                       const void *v_pub_blob, int pub_len,
+                       int keytype);
 int key_type(const Filename *filename);
 char *key_type_to_str(int type);
 
index f3c558345a63a776485956e7ac41b1317a38f68d..053eeb6f233b66d0e13b0a9888404d1811bbb152 100644 (file)
--- a/sshpubk.c
+++ b/sshpubk.c
@@ -1433,6 +1433,141 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
     return 1;
 }
 
+/* ----------------------------------------------------------------------
+ * Output public keys.
+ */
+char *ssh1_pubkey_str(struct RSAKey *key)
+{
+    char *buffer;
+    char *dec1, *dec2;
+
+    dec1 = bignum_decimal(key->exponent);
+    dec2 = bignum_decimal(key->modulus);
+    buffer = dupprintf("%d %s %s%s%s", bignum_bitcount(key->modulus),
+                      dec1, dec2,
+                       key->comment ? " " : "",
+                       key->comment ? key->comment : "");
+    sfree(dec1);
+    sfree(dec2);
+    return buffer;
+}
+
+void ssh1_write_pubkey(FILE *fp, struct RSAKey *key)
+{
+    char *buffer = ssh1_pubkey_str(key);
+    fprintf(fp, "%s\n", buffer);
+    sfree(buffer);
+}
+
+static char *ssh2_pubkey_openssh_str_internal(const char *comment,
+                                              const void *v_pub_blob,
+                                              int pub_len)
+{
+    const unsigned char *ssh2blob = (const unsigned char *)v_pub_blob;
+    const char *alg;
+    int alglen;
+    char *buffer, *p;
+    int i;
+
+    if (pub_len < 4) {
+        alg = NULL;
+    } else {
+        alglen = GET_32BIT(ssh2blob);
+        if (alglen > 0 && alglen < pub_len - 4) {
+            alg = (const char *)ssh2blob + 4;
+        } else {
+            alg = NULL;
+        }
+    }
+
+    if (!alg) {
+        alg = "INVALID-ALGORITHM";
+        alglen = strlen(alg);
+    }
+
+    buffer = snewn(alglen +
+                   4 * ((pub_len+2) / 3) +
+                   (comment ? strlen(comment) : 0) + 3, char);
+    p = buffer + sprintf(buffer, "%.*s ", alglen, alg);
+    i = 0;
+    while (i < pub_len) {
+        int n = (pub_len - i < 3 ? pub_len - i : 3);
+        base64_encode_atom(ssh2blob + i, n, p);
+        i += n;
+        p += 4;
+    }
+    if (*comment) {
+        *p++ = ' ';
+        strcpy(p, comment);
+    } else
+        *p++ = '\0';
+
+    return buffer;
+}
+
+char *ssh2_pubkey_openssh_str(struct ssh2_userkey *key)
+{
+    int bloblen;
+    unsigned char *blob;
+    char *ret;
+
+    blob = key->alg->public_blob(key->data, &bloblen);
+    ret = ssh2_pubkey_openssh_str_internal(key->comment, blob, bloblen);
+    sfree(blob);
+
+    return ret;
+}
+
+void ssh2_write_pubkey(FILE *fp, const char *comment,
+                       const void *v_pub_blob, int pub_len,
+                       int keytype)
+{
+    unsigned char *pub_blob = (unsigned char *)v_pub_blob;
+
+    if (keytype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716) {
+        const char *p;
+        int i, column;
+
+        fprintf(fp, "---- BEGIN SSH2 PUBLIC KEY ----\n");
+
+        if (comment) {
+            fprintf(fp, "Comment: \"");
+            for (p = comment; *p; p++) {
+                if (*p == '\\' || *p == '\"')
+                    fputc('\\', fp);
+                fputc(*p, fp);
+            }
+            fprintf(fp, "\"\n");
+        }
+
+        i = 0;
+        column = 0;
+        while (i < pub_len) {
+            char buf[5];
+            int n = (pub_len - i < 3 ? pub_len - i : 3);
+            base64_encode_atom(pub_blob + i, n, buf);
+            i += n;
+            buf[4] = '\0';
+            fputs(buf, fp);
+            if (++column >= 16) {
+                fputc('\n', fp);
+                column = 0;
+            }
+        }
+        if (column > 0)
+            fputc('\n', fp);
+
+        fprintf(fp, "---- END SSH2 PUBLIC KEY ----\n");
+    } else if (keytype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) {
+        char *buffer = ssh2_pubkey_openssh_str_internal(comment,
+                                                        v_pub_blob, pub_len);
+        fprintf(fp, "%s\n", buffer);
+        sfree(buffer);
+    } else {
+        assert(0 && "Bad key type in ssh2_write_pubkey");
+    }
+}
+
 /* ----------------------------------------------------------------------
  * Determine the type of a private key file.
  */
index 093479ff77969b55464dc42872def2f2af4772f1..8806d75f933b972bd17e675585fb7e86a8366c79 100644 (file)
@@ -383,69 +383,23 @@ static void hidemany(HWND hwnd, const int *ids, int hideit)
 
 static void setupbigedit1(HWND hwnd, int id, int idstatic, struct RSAKey *key)
 {
-    char *buffer;
-    char *dec1, *dec2;
-
-    dec1 = bignum_decimal(key->exponent);
-    dec2 = bignum_decimal(key->modulus);
-    buffer = dupprintf("%d %s %s %s", bignum_bitcount(key->modulus),
-                      dec1, dec2, key->comment);
+    char *buffer = ssh1_pubkey_str(key);
     SetDlgItemText(hwnd, id, buffer);
     SetDlgItemText(hwnd, idstatic,
                   "&Public key for pasting into authorized_keys file:");
-    sfree(dec1);
-    sfree(dec2);
     sfree(buffer);
 }
 
 static void setupbigedit2(HWND hwnd, int id, int idstatic,
                          struct ssh2_userkey *key)
 {
-    unsigned char *pub_blob;
-    char *buffer, *p;
-    int pub_len;
-    int i;
-
-    pub_blob = key->alg->public_blob(key->data, &pub_len);
-    buffer = snewn(strlen(key->alg->name) + 4 * ((pub_len + 2) / 3) +
-                  strlen(key->comment) + 3, char);
-    strcpy(buffer, key->alg->name);
-    p = buffer + strlen(buffer);
-    *p++ = ' ';
-    i = 0;
-    while (i < pub_len) {
-       int n = (pub_len - i < 3 ? pub_len - i : 3);
-       base64_encode_atom(pub_blob + i, n, p);
-       i += n;
-       p += 4;
-    }
-    *p++ = ' ';
-    strcpy(p, key->comment);
+    char *buffer = ssh2_pubkey_openssh_str(key);
     SetDlgItemText(hwnd, id, buffer);
     SetDlgItemText(hwnd, idstatic, "&Public key for pasting into "
                   "OpenSSH authorized_keys file:");
-    sfree(pub_blob);
     sfree(buffer);
 }
 
-static int save_ssh1_pubkey(char *filename, struct RSAKey *key)
-{
-    char *dec1, *dec2;
-    FILE *fp;
-
-    fp = fopen(filename, "wb");
-    if (!fp)
-       return 0;
-    dec1 = bignum_decimal(key->exponent);
-    dec2 = bignum_decimal(key->modulus);
-    fprintf(fp, "%d %s %s %s\n",
-           bignum_bitcount(key->modulus), dec1, dec2, key->comment);
-    fclose(fp);
-    sfree(dec1);
-    sfree(dec2);
-    return 1;
-}
-
 /*
  * Warn about the obsolescent key file format.
  */
@@ -1326,15 +1280,27 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                        if (ret != IDYES)
                            break;
                    }
-                   if (state->ssh2) {
-                       ret = save_ssh2_pubkey(filename, &state->ssh2key);
-                   } else {
-                       ret = save_ssh1_pubkey(filename, &state->key);
-                   }
-                   if (ret <= 0) {
-                       MessageBox(hwnd, "Unable to save key file",
-                                  "PuTTYgen Error", MB_OK | MB_ICONERROR);
-                   }
+                    fp = fopen(filename, "w");
+                    if (!fp) {
+                        MessageBox(hwnd, "Unable to open key file",
+                                   "PuTTYgen Error", MB_OK | MB_ICONERROR);
+                    } else {
+                        if (state->ssh2) {
+                            int bloblen;
+                            unsigned char *blob;
+                            blob = state->ssh2key.alg->public_blob
+                                (state->ssh2key.data, &bloblen);
+                            ssh2_write_pubkey(fp, state->ssh2key.comment,
+                                              blob, bloblen,
+                                              SSH_KEYTYPE_SSH2_PUBLIC_RFC4716);
+                        } else {
+                            ssh1_write_pubkey(fp, &state->key);
+                        }
+                        if (fclose(fp) < 0) {
+                            MessageBox(hwnd, "Unable to save key file",
+                                       "PuTTYgen Error", MB_OK | MB_ICONERROR);
+                        }
+                    }
                }
            }
            break;