/* * Update the visible key list. */ void keylist_update(void) { struct RSAKey *rkey; struct ssh2_userkey *skey; int i; if (keylist) { SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0); for (i = 0; NULL != (rkey = pageant_nth_ssh1_key(i)); i++) { char listentry[512], *p; /* * Replace two spaces in the fingerprint with tabs, for * nice alignment in the box. */ strcpy(listentry, "ssh1\t"); p = listentry + strlen(listentry); rsa_fingerprint(p, sizeof(listentry) - (p - listentry), rkey); p = strchr(listentry, ' '); if (p) *p = '\t'; p = strchr(listentry, ' '); if (p) *p = '\t'; SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM) listentry); } for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) { char *listentry, *p; int pos; /* * Replace spaces with tabs in the fingerprint prefix, for * nice alignment in the list box, until we encounter a : * meaning we're into the fingerprint proper. */ p = ssh2_fingerprint(skey->alg, skey->data); listentry = dupprintf("%s\t%s", p, skey->comment); sfree(p); pos = 0; while (1) { pos += strcspn(listentry + pos, " :"); if (listentry[pos] == ':' || !listentry[pos]) break; listentry[pos++] = '\t'; } SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM) listentry); sfree(listentry); } SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM) - 1, 0); } }
int main(int argc, char **argv) { Filename *infilename = NULL; int intype = SSH_KEYTYPE_UNOPENABLE; int encrypted = 0; char* origcomment = 0; char* line = 0; char* passphrase = 0; struct ssh2_userkey *ssh2key = NULL; char* fingerprint = 0; printf("fzputtygen\n"); printf("Copyright (C) 2008-2016 Tim Kosse\n"); printf("Based on PuTTY's puttygen\n"); printf("Copyright (C) 1997-2015 Simon Tatham and the PuTTY team\n"); printf("Converts private SSH keys into PuTTY's format.\n"); printf("This program is used by FileZilla and not intended to be used directly.\n"); printf("Use the puttygen tool from PuTTY for a human-usable tool.\n"); printf("\n"); fflush(stdout); while (1) { sfree(line); line = fgetline(stdin); if (!line || !*line || *line == '\n') break; line[strlen(line) - 1] = 0; char* cmd = line, *args = line; while (*args) { if (*args == ' ') { *(args++) = 0; break; } args++; } if (!*args) args = 0; if (!strcmp(cmd, "file")) { char const* ret = NULL; if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); ssh2key = 0; } sfree(passphrase); passphrase = 0; sfree(fingerprint); fingerprint = 0; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (infilename) { filename_free(infilename); } infilename = filename_from_str(args); intype = key_type(infilename); switch (intype) { case SSH_KEYTYPE_SSH1: ret = "incompatible"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_SSH2: ret = "ok"; encrypted = ssh2_userkey_encrypted(infilename, &origcomment); break; case SSH_KEYTYPE_UNKNOWN: case SSH_KEYTYPE_UNOPENABLE: default: ret = "error"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: encrypted = import_encrypted(infilename, intype, &origcomment); ret = encrypted ? "convertible" : "ok"; break; } fzprintf(sftpReply, "%s", ret); } else if (!strcmp(cmd, "encrypted")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } fzprintf(sftpReply, "%d", encrypted ? 1 : 0); } else if (!strcmp(cmd, "comment")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (ssh2key && ssh2key->comment) { fzprintf(sftpReply, "%s", ssh2key->comment); } else if (origcomment) fzprintf(sftpReply, "%s", origcomment); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "password")) { const char* error = NULL; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (!encrypted) { fzprintf(sftpError, "File is not encrypted"); continue; } if (ssh2key) { fzprintf(sftpError, "Already opened file"); continue; } sfree(passphrase); passphrase = strdup(args); switch (intype) { case SSH_KEYTYPE_SSH2: ssh2key = ssh2_load_userkey(infilename, passphrase, &error); break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, passphrase, &error); break; default: break; } if (ssh2key == SSH2_WRONG_PASSPHRASE) { error = "wrong passphrase"; ssh2key = 0; } if (ssh2key) { error = NULL; } else if (!error) { error = "unknown error"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "fingerprint")) { const char* error = 0; if (!fingerprint) { if (ssh2key) { fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { switch (intype) { case SSH_KEYTYPE_SSH2: { void* ssh2blob; int bloblen = 0; char* comment = NULL; ssh2blob = ssh2_userkey_loadpub(infilename, 0, &bloblen, &comment, &error); if (ssh2blob) { fingerprint = ssh2_fingerprint_blob(ssh2blob, bloblen); sfree(ssh2blob); } else if (!error) { error = "unknown error"; } if (comment) { sfree(origcomment); origcomment = comment; } break; } case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, "", &error); if (ssh2key) { if (ssh2key != SSH2_WRONG_PASSPHRASE) { error = NULL; fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { ssh2key = NULL; error = "wrong passphrase"; } } else if (!error) error = "unknown error"; break; default: error = "No file loaded"; break; } } } if (!fingerprint && !error) { error = "Could not get fingerprint"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, "%s", fingerprint); } else if (!strcmp(cmd, "write")) { Filename* outfilename; int ret; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (!ssh2key) { fzprintf(sftpError, "No key loaded"); continue; } outfilename = filename_from_str(args); ret = ssh2_save_userkey(outfilename, ssh2key, passphrase); if (!ret) { fzprintf(sftpError, "Unable to save SSH-2 private key"); continue; } filename_free(outfilename); fzprintf(sftpReply, ""); } else fzprintf(sftpError, "Unknown command"); } if (infilename) { filename_free(infilename); } sfree(line); sfree(passphrase); if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); } sfree(fingerprint); sfree(origcomment); return 0; }
void load_key_file(HWND hwnd, struct MainDlgState *state, Filename *filename, int was_import_cmd) { char *passphrase; int needs_pass; int type, realtype; int ret; const char *errmsg = NULL; char *comment; struct RSAKey newkey1; struct ssh2_userkey *newkey2 = NULL; type = realtype = key_type(filename); if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2 && !import_possible(type)) { char *msg = dupprintf("Couldn't load private key (%s)", key_type_to_str(type)); message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR, HELPCTXID(errors_cantloadkey)); sfree(msg); return; } if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) { realtype = type; type = import_target_type(type); } comment = NULL; passphrase = NULL; if (realtype == SSH_KEYTYPE_SSH1) needs_pass = rsakey_encrypted(filename, &comment); else if (realtype == SSH_KEYTYPE_SSH2) needs_pass = ssh2_userkey_encrypted(filename, &comment); else needs_pass = import_encrypted(filename, realtype, &comment); do { burnstr(passphrase); passphrase = NULL; if (needs_pass) { int dlgret; struct PassphraseProcStruct pps; pps.passphrase = &passphrase; pps.comment = comment; dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210), NULL, PassphraseProc, (LPARAM) &pps); if (!dlgret) { ret = -2; break; } assert(passphrase != NULL); } else passphrase = dupstr(""); if (type == SSH_KEYTYPE_SSH1) { if (realtype == type) ret = loadrsakey(filename, &newkey1, passphrase, &errmsg); else ret = import_ssh1(filename, realtype, &newkey1, passphrase, &errmsg); } else { if (realtype == type) newkey2 = ssh2_load_userkey(filename, passphrase, &errmsg); else newkey2 = import_ssh2(filename, realtype, passphrase, &errmsg); if (newkey2 == SSH2_WRONG_PASSPHRASE) ret = -1; else if (!newkey2) ret = 0; else ret = 1; } } while (ret == -1); if (comment) sfree(comment); if (ret == 0) { char *msg = dupprintf("Couldn't load private key (%s)", errmsg); message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR, HELPCTXID(errors_cantloadkey)); sfree(msg); } else if (ret == 1) { /* * Now update the key controls with all the * key data. */ { SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, passphrase); SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, passphrase); if (type == SSH_KEYTYPE_SSH1) { char buf[128]; char *savecomment; state->ssh2 = FALSE; state->commentptr = &state->key.comment; state->key = newkey1; /* * Set the key fingerprint. */ savecomment = state->key.comment; state->key.comment = NULL; rsa_fingerprint(buf, sizeof(buf), &state->key); state->key.comment = savecomment; SetDlgItemText(hwnd, IDC_FINGERPRINT, buf); /* * Construct a decimal representation * of the key, for pasting into * .ssh/authorized_keys on a Unix box. */ setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key); } else { char *fp; char *savecomment; state->ssh2 = TRUE; state->commentptr = &state->ssh2key.comment; state->ssh2key = *newkey2; /* structure copy */ sfree(newkey2); savecomment = state->ssh2key.comment; state->ssh2key.comment = NULL; fp = ssh2_fingerprint(state->ssh2key.alg, state->ssh2key.data); state->ssh2key.comment = savecomment; SetDlgItemText(hwnd, IDC_FINGERPRINT, fp); sfree(fp); setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->ssh2key); } SetDlgItemText(hwnd, IDC_COMMENTEDIT, *state->commentptr); } /* * Finally, hide the progress bar and show * the key data. */ ui_set_state(hwnd, state, 2); state->key_exists = TRUE; /* * If the user has imported a foreign key * using the Load command, let them know. * If they've used the Import command, be * silent. */ if (realtype != type && !was_import_cmd) { char msg[512]; sprintf(msg, "Successfully imported foreign key\n" "(%s).\n" "To use this key with PuTTY, you need to\n" "use the \"Save private key\" command to\n" "save it in PuTTY's own format.", key_type_to_str(realtype)); MessageBox(NULL, msg, "PuTTYgen Notice", MB_OK | MB_ICONINFORMATION); } } burnstr(passphrase); }
/* * Update the visible key list. */ void keylist_update(void) { struct RSAKey *rkey; struct ssh2_userkey *skey; int i; if (keylist) { SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0); for (i = 0; NULL != (rkey = pageant_nth_ssh1_key(i)); i++) { char listentry[512], *p; /* * Replace two spaces in the fingerprint with tabs, for * nice alignment in the box. */ strcpy(listentry, "ssh1\t"); p = listentry + strlen(listentry); rsa_fingerprint(p, sizeof(listentry) - (p - listentry), rkey); p = strchr(listentry, ' '); if (p) *p = '\t'; p = strchr(listentry, ' '); if (p) *p = '\t'; SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM)listentry); } for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) { char *listentry, *p; int pos; /* * For nice alignment in the list box, we would ideally * want every entry to align to the tab stop settings, and * have a column for algorithm name, one for bit count, * one for hex fingerprint, and one for key comment. * * Unfortunately, some of the algorithm names are so long * that they overflow into the bit-count field. * Fortunately, at the moment, those are _precisely_ the * algorithm names that don't need a bit count displayed * anyway (because for NIST-style ECDSA the bit count is * mentioned in the algorithm name, and for ssh-ed25519 * there is only one possible value anyway). So we fudge * this by simply omitting the bit count field in that * situation. * * This is fragile not only in the face of further key * types that don't follow this pattern, but also in the * face of font metrics changes - the Windows semantics * for list box tab stops is that \t aligns to the next * one you haven't already exceeded, so I have to guess * when the key type will overflow past the bit-count tab * stop and leave out a tab character. Urgh. */ p = ssh2_fingerprint(skey->alg, skey->data); listentry = dupprintf("%s\t%s", p, skey->comment); sfree(p); pos = 0; while (1) { pos += strcspn(listentry + pos, " :"); if (listentry[pos] == ':' || !listentry[pos]) break; listentry[pos++] = '\t'; } if (skey->alg != &ssh_dss && skey->alg != &ssh_rsa) { /* * Remove the bit-count field, which is between the * first and second \t. */ int outpos; pos = 0; while (listentry[pos] && listentry[pos] != '\t') pos++; outpos = pos; pos++; while (listentry[pos] && listentry[pos] != '\t') pos++; while (1) { if ((listentry[outpos] = listentry[pos]) == '\0') break; outpos++; pos++; } } SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM)listentry); sfree(listentry); } SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM)-1, 0); } }