//--------------------------------------------------------------------------- void __fastcall TKeyGenerator::SaveKey(const AnsiString FileName, const AnsiString Passphrase, TKeyFormat Format) { DebugAssert(FSSH2Key); DebugAssert(FState == kgComplete); DebugAssert((Format != kfOpenSSH && Format != kfSSHCom) || IsSSH2); int Result; if (IsSSH2) { switch (Format) { case kfPutty: Result = ssh2_save_userkey(FileName.c_str(), FSSH2Key, (char*)Passphrase.data()); break; case kfOpenSSH: Result = export_ssh2(FileName.c_str(), SSH_KEYTYPE_OPENSSH, FSSH2Key, (char*)Passphrase.data()); break; case kfSSHCom: Result = export_ssh2(FileName.c_str(), SSH_KEYTYPE_SSHCOM, FSSH2Key, (char*)Passphrase.data()); break; default: DebugFail(); } } else { DebugAssert(Format == kfPutty); Result = saversakey(FileName.c_str(), FRSAKey, (char*)Passphrase.data()); } if (Result <= 0) throw Exception(FMTLOAD(SAVE_KEY_ERROR, (FileName))); }
/* * Dialog-box function for the main PuTTYgen dialog box. */ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { enum { controlidstart = 100, IDC_TITLE, IDC_BOX_KEY, IDC_NOKEY, IDC_GENERATING, IDC_PROGRESS, IDC_PKSTATIC, IDC_KEYDISPLAY, IDC_FPSTATIC, IDC_FINGERPRINT, IDC_COMMENTSTATIC, IDC_COMMENTEDIT, IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT, IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, IDC_BOX_ACTIONS, IDC_GENSTATIC, IDC_GENERATE, IDC_LOADSTATIC, IDC_LOAD, IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB, IDC_BOX_PARAMS, IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA, IDC_BITSSTATIC, IDC_BITS, IDC_ABOUT, }; static const int nokey_ids[] = { IDC_NOKEY, 0 }; static const int generating_ids[] = { IDC_GENERATING, IDC_PROGRESS, 0 }; static const int gotkey_ids[] = { IDC_PKSTATIC, IDC_KEYDISPLAY, IDC_FPSTATIC, IDC_FINGERPRINT, IDC_COMMENTSTATIC, IDC_COMMENTEDIT, IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT, IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0 }; static const char generating_msg[] = "Please wait while a key is generated..."; static const char entropy_msg[] = "Please generate some randomness by moving the mouse over the blank area."; struct MainDlgState *state; switch (msg) { case WM_INITDIALOG: if (help_path) SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP); else { /* * If we add a Help button, this is where we destroy it * if the help file isn't present. */ } requested_help = FALSE; /* * Centre the window. */ { /* centre the window */ RECT rs, rd; HWND hw; hw = GetDesktopWindow(); if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd)) MoveWindow(hwnd, (rs.right + rs.left + rd.left - rd.right) / 2, (rs.bottom + rs.top + rd.top - rd.bottom) / 2, rd.right - rd.left, rd.bottom - rd.top, TRUE); } state = smalloc(sizeof(*state)); state->generation_thread_exists = FALSE; state->collecting_entropy = FALSE; state->entropy = NULL; state->key_exists = FALSE; SetWindowLong(hwnd, GWL_USERDATA, (LONG) state); { struct ctlpos cp, cp2; /* Accelerators used: acglops1rbd */ ctlposinit(&cp, hwnd, 4, 4, 4); bartitle(&cp, "Public and private key generation for PuTTY", IDC_TITLE); beginbox(&cp, "Key", IDC_BOX_KEY); cp2 = cp; statictext(&cp2, "No key.", 1, IDC_NOKEY); cp2 = cp; statictext(&cp2, "", 1, IDC_GENERATING); progressbar(&cp2, IDC_PROGRESS); bigeditctrl(&cp, "&Public key for pasting into authorized_keys file:", IDC_PKSTATIC, IDC_KEYDISPLAY, 5); SendDlgItemMessage(hwnd, IDC_KEYDISPLAY, EM_SETREADONLY, 1, 0); staticedit(&cp, "Key fingerprint:", IDC_FPSTATIC, IDC_FINGERPRINT, 75); SendDlgItemMessage(hwnd, IDC_FINGERPRINT, EM_SETREADONLY, 1, 0); staticedit(&cp, "Key &comment:", IDC_COMMENTSTATIC, IDC_COMMENTEDIT, 75); staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT, 75); staticpassedit(&cp, "C&onfirm passphrase:", IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 75); endbox(&cp); beginbox(&cp, "Actions", IDC_BOX_ACTIONS); staticbtn(&cp, "Generate a public/private key pair", IDC_GENSTATIC, "&Generate", IDC_GENERATE); staticbtn(&cp, "Load an existing private key file", IDC_LOADSTATIC, "&Load", IDC_LOAD); static2btn(&cp, "Save the generated key", IDC_SAVESTATIC, "Save p&ublic key", IDC_SAVEPUB, "&Save private key", IDC_SAVE); endbox(&cp); beginbox(&cp, "Parameters", IDC_BOX_PARAMS); radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 3, "SSH&1 (RSA)", IDC_KEYSSH1, "SSH2 &RSA", IDC_KEYSSH2RSA, "SSH2 &DSA", IDC_KEYSSH2DSA, NULL); staticedit(&cp, "Number of &bits in a generated key:", IDC_BITSSTATIC, IDC_BITS, 20); endbox(&cp); } CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, IDC_KEYSSH1); SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE); /* * Initially, hide the progress bar and the key display, * and show the no-key display. Also disable the Save * buttons, because with no key we obviously can't save * anything. */ hidemany(hwnd, nokey_ids, FALSE); hidemany(hwnd, generating_ids, TRUE); hidemany(hwnd, gotkey_ids, TRUE); EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0); EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0); return 1; case WM_MOUSEMOVE: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (state->collecting_entropy && state->entropy && state->entropy_got < state->entropy_required) { state->entropy[state->entropy_got++] = lParam; state->entropy[state->entropy_got++] = GetMessageTime(); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, state->entropy_got, 0); if (state->entropy_got >= state->entropy_required) { struct rsa_key_thread_params *params; DWORD threadid; /* * Seed the entropy pool */ random_add_heavynoise(state->entropy, state->entropy_size); memset(state->entropy, 0, state->entropy_size); sfree(state->entropy); state->collecting_entropy = FALSE; SetDlgItemText(hwnd, IDC_GENERATING, generating_msg); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSRANGE)); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0); params = smalloc(sizeof(*params)); params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS); params->dialog = hwnd; params->keysize = state->keysize; params->is_dsa = state->is_dsa; params->key = &state->key; params->dsskey = &state->dsskey; if (!CreateThread(NULL, 0, generate_rsa_key_thread, params, 0, &threadid)) { MessageBox(hwnd, "Out of thread resources", "Key generation error", MB_OK | MB_ICONERROR); sfree(params); } else { state->generation_thread_exists = TRUE; } } } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_COMMENTEDIT: if (HIWORD(wParam) == EN_CHANGE) { state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (state->key_exists) { HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT); int len = GetWindowTextLength(editctl); if (*state->commentptr) sfree(*state->commentptr); *state->commentptr = smalloc(len + 1); GetWindowText(editctl, *state->commentptr, len + 1); if (state->ssh2) { setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->ssh2key); } else { setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key); } } } break; case IDC_ABOUT: EnableWindow(hwnd, 0); DialogBox(hinst, MAKEINTRESOURCE(213), NULL, AboutProc); EnableWindow(hwnd, 1); SetActiveWindow(hwnd); return 0; case IDC_GENERATE: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (!state->generation_thread_exists) { BOOL ok; state->keysize = GetDlgItemInt(hwnd, IDC_BITS, &ok, FALSE); if (!ok) state->keysize = DEFAULT_KEYSIZE; /* If we ever introduce a new key type, check it here! */ state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1); state->is_dsa = IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA); if (state->keysize < 256) { int ret = MessageBox(hwnd, "PuTTYgen will not generate a key" " smaller than 256 bits.\n" "Key length reset to 256. Continue?", "PuTTYgen Warning", MB_ICONWARNING | MB_OKCANCEL); if (ret != IDOK) break; state->keysize = 256; SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE); } hidemany(hwnd, nokey_ids, TRUE); hidemany(hwnd, generating_ids, FALSE); hidemany(hwnd, gotkey_ids, TRUE); EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 0); EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 0); EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0); EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 0); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 0); EnableWindow(GetDlgItem(hwnd, IDC_BITS), 0); state->key_exists = FALSE; SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg); state->collecting_entropy = TRUE; /* * My brief statistical tests on mouse movements * suggest that there are about 2.5 bits of * randomness in the x position, 2.5 in the y * position, and 1.7 in the message time, making * 5.7 bits of unpredictability per mouse movement. * However, other people have told me it's far less * than that, so I'm going to be stupidly cautious * and knock that down to a nice round 2. With this * method, we require two words per mouse movement, * so with 2 bits per mouse movement we expect 2 * bits every 2 words. */ state->entropy_required = (state->keysize / 2) * 2; state->entropy_got = 0; state->entropy_size = (state->entropy_required * sizeof(*state->entropy)); state->entropy = smalloc(state->entropy_size); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, state->entropy_required)); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0); } break; case IDC_SAVE: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (state->key_exists) { char filename[FILENAME_MAX]; char passphrase[PASSPHRASE_MAXLEN]; char passphrase2[PASSPHRASE_MAXLEN]; GetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, passphrase, sizeof(passphrase)); GetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, passphrase2, sizeof(passphrase2)); if (strcmp(passphrase, passphrase2)) { MessageBox(hwnd, "The two passphrases given do not match.", "PuTTYgen Error", MB_OK | MB_ICONERROR); break; } if (!*passphrase) { int ret; ret = MessageBox(hwnd, "Are you sure you want to save this key\n" "without a passphrase to protect it?", "PuTTYgen Warning", MB_YESNO | MB_ICONWARNING); if (ret != IDYES) break; } if (prompt_keyfile(hwnd, "Save private key as:", filename, 1)) { int ret; FILE *fp = fopen(filename, "r"); if (fp) { char buffer[FILENAME_MAX + 80]; fclose(fp); sprintf(buffer, "Overwrite existing file\n%.*s?", FILENAME_MAX, filename); ret = MessageBox(hwnd, buffer, "PuTTYgen Warning", MB_YESNO | MB_ICONWARNING); if (ret != IDYES) break; } if (state->ssh2) { ret = ssh2_save_userkey(filename, &state->ssh2key, *passphrase ? passphrase : NULL); } else { ret = saversakey(filename, &state->key, *passphrase ? passphrase : NULL); } if (ret <= 0) { MessageBox(hwnd, "Unable to save key file", "PuTTYgen Error", MB_OK | MB_ICONERROR); } } } break; case IDC_SAVEPUB: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (state->key_exists) { char filename[FILENAME_MAX]; if (prompt_keyfile(hwnd, "Save public key as:", filename, 1)) { int ret; FILE *fp = fopen(filename, "r"); if (fp) { char buffer[FILENAME_MAX + 80]; fclose(fp); sprintf(buffer, "Overwrite existing file\n%.*s?", FILENAME_MAX, filename); ret = MessageBox(hwnd, buffer, "PuTTYgen Warning", MB_YESNO | MB_ICONWARNING); 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); } } } break; case IDC_LOAD: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); if (!state->generation_thread_exists) { char filename[FILENAME_MAX]; if (prompt_keyfile(hwnd, "Load private key:", filename, 0)) { char passphrase[PASSPHRASE_MAXLEN]; int needs_pass; int ver; int ret; char *comment; struct PassphraseProcStruct pps; struct RSAKey newkey1; struct ssh2_userkey *newkey2 = NULL; ver = keyfile_version(filename); if (ver == 0) { MessageBox(NULL, "Couldn't load private key.", "PuTTYgen Error", MB_OK | MB_ICONERROR); break; } comment = NULL; if (ver == 1) needs_pass = rsakey_encrypted(filename, &comment); else needs_pass = ssh2_userkey_encrypted(filename, &comment); pps.passphrase = passphrase; pps.comment = comment; do { if (needs_pass) { int dlgret; dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210), NULL, PassphraseProc, (LPARAM) & pps); if (!dlgret) { ret = -2; break; } } else *passphrase = '\0'; if (ver == 1) ret = loadrsakey(filename, &newkey1, passphrase); else { newkey2 = ssh2_load_userkey(filename, passphrase); 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) { MessageBox(NULL, "Couldn't load private key.", "PuTTYgen Error", MB_OK | MB_ICONERROR); } else if (ret == 1) { EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1); EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1); EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1); EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1); EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1); /* * Now update the key controls with all the * key data. */ { SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, passphrase); SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, passphrase); if (ver == 1) { 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 = state->ssh2key.alg-> fingerprint(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. */ hidemany(hwnd, nokey_ids, TRUE); hidemany(hwnd, generating_ids, TRUE); hidemany(hwnd, gotkey_ids, FALSE); state->key_exists = TRUE; } } } break; } return 0; case WM_DONEKEY: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); state->generation_thread_exists = FALSE; state->key_exists = TRUE; SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSRANGE)); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0); EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1); EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1); EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1); EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1); EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1); EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1); if (state->ssh2) { if (state->is_dsa) { state->ssh2key.data = &state->dsskey; state->ssh2key.alg = &ssh_dss; } else { state->ssh2key.data = &state->key; state->ssh2key.alg = &ssh_rsa; } state->commentptr = &state->ssh2key.comment; } else { state->commentptr = &state->key.comment; } /* * Invent a comment for the key. We'll do this by including * the date in it. This will be so horrifyingly ugly that * the user will immediately want to change it, which is * what we want :-) */ *state->commentptr = smalloc(30); { time_t t; struct tm *tm; time(&t); tm = localtime(&t); if (state->is_dsa) strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", tm); else strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", tm); } /* * Now update the key controls with all the key data. */ { char *savecomment; /* * Blank passphrase, initially. This isn't dangerous, * because we will warn (Are You Sure?) before allowing * the user to save an unprotected private key. */ SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, ""); SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, ""); /* * Set the comment. */ SetDlgItemText(hwnd, IDC_COMMENTEDIT, *state->commentptr); /* * Set the key fingerprint. */ savecomment = *state->commentptr; *state->commentptr = NULL; if (state->ssh2) { char *fp; fp = state->ssh2key.alg->fingerprint(state->ssh2key.data); SetDlgItemText(hwnd, IDC_FINGERPRINT, fp); sfree(fp); } else { char buf[128]; rsa_fingerprint(buf, sizeof(buf), &state->key); SetDlgItemText(hwnd, IDC_FINGERPRINT, buf); } *state->commentptr = savecomment; /* * Construct a decimal representation of the key, for * pasting into .ssh/authorized_keys or * .ssh/authorized_keys2 on a Unix box. */ if (state->ssh2) { setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->ssh2key); } else { setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key); } } /* * Finally, hide the progress bar and show the key data. */ hidemany(hwnd, nokey_ids, TRUE); hidemany(hwnd, generating_ids, TRUE); hidemany(hwnd, gotkey_ids, FALSE); break; case WM_HELP: if (help_path) { int id = ((LPHELPINFO)lParam)->iCtrlId; char *cmd = NULL; switch (id) { case IDC_GENERATING: case IDC_PROGRESS: case IDC_GENSTATIC: case IDC_GENERATE: cmd = "JI(`',`puttygen.generate')"; break; case IDC_PKSTATIC: case IDC_KEYDISPLAY: cmd = "JI(`',`puttygen.pastekey')"; break; case IDC_FPSTATIC: case IDC_FINGERPRINT: cmd = "JI(`',`puttygen.fingerprint')"; break; case IDC_COMMENTSTATIC: case IDC_COMMENTEDIT: cmd = "JI(`',`puttygen.comment')"; break; case IDC_PASSPHRASE1STATIC: case IDC_PASSPHRASE1EDIT: case IDC_PASSPHRASE2STATIC: case IDC_PASSPHRASE2EDIT: cmd = "JI(`',`puttygen.passphrase')"; break; case IDC_LOADSTATIC: case IDC_LOAD: cmd = "JI(`',`puttygen.load')"; break; case IDC_SAVESTATIC: case IDC_SAVE: cmd = "JI(`',`puttygen.savepriv')"; break; case IDC_SAVEPUB: cmd = "JI(`',`puttygen.savepub')"; break; case IDC_TYPESTATIC: case IDC_KEYSSH1: case IDC_KEYSSH2RSA: case IDC_KEYSSH2DSA: cmd = "JI(`',`puttygen.keytype')"; break; case IDC_BITSSTATIC: case IDC_BITS: cmd = "JI(`',`puttygen.bits')"; break; } if (cmd) { WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd); requested_help = TRUE; } else { MessageBeep(0); } } break; case WM_CLOSE: state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); sfree(state); if (requested_help) { WinHelp(hwnd, help_path, HELP_QUIT, 0); requested_help = FALSE; } EndDialog(hwnd, 1); return 0; } return 0; }
int main(int argc, char **argv) { Filename *infilename = NULL, *outfilename = NULL; int intype = SSH_KEYTYPE_UNOPENABLE; int encrypted = 0; char* origcomment = 0; char* line = 0; char* passphrase = 0; struct ssh2_userkey *ssh2key = NULL; struct RSAKey *ssh1key = NULL; printf("fzputtygen\n"); printf("Copyright (C) 2008-2015 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) { if (line) 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")) { if (ssh1key) { freersakey(ssh1key); ssh1key = 0; } if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); ssh2key = 0; } if (passphrase) { sfree(passphrase); passphrase = 0; } if (!args) { fzprintf(sftpError, "No argument given"); continue; } infilename = filename_from_str(args); intype = key_type(infilename); switch (intype) { case SSH_KEYTYPE_SSH1: case SSH_KEYTYPE_SSH2: fzprintf(sftpReply, "0"); break; case SSH_KEYTYPE_UNKNOWN: case SSH_KEYTYPE_UNOPENABLE: default: fzprintf(sftpReply, "2"); intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_OPENSSH: case SSH_KEYTYPE_SSHCOM: fzprintf(sftpReply, "1"); break; } } else if (!strcmp(cmd, "encrypted")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No keyfile opened"); continue; } if (intype == SSH_KEYTYPE_SSH1) encrypted = rsakey_encrypted(infilename, &origcomment); else if (intype == SSH_KEYTYPE_SSH2) encrypted = ssh2_userkey_encrypted(infilename, &origcomment); else encrypted = import_encrypted(infilename, intype, &origcomment); fzprintf(sftpReply, "%d", encrypted ? 1 : 0); } else if (!strcmp(cmd, "comment")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No keyfile opened"); continue; } if (origcomment) fzprintf(sftpReply, "%s", origcomment); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "password")) { if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No keyfile opened"); continue; } if (passphrase) sfree(passphrase); passphrase = strdup(args); fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "load")) { const char* error = 0; if (ssh1key) { freersakey(ssh1key); ssh1key = 0; } if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); ssh2key = 0; } if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No keyfile opened"); continue; } if (encrypted && !passphrase) { fzprintf(sftpError, "No password given"); continue; } switch (intype) { int ret; case SSH_KEYTYPE_SSH1: ssh1key = snew(struct RSAKey); ret = loadrsakey(infilename, ssh1key, passphrase, &error); if (ret > 0) error = NULL; else if (!error) error = "unknown error"; break; case SSH_KEYTYPE_SSH2: ssh2key = ssh2_load_userkey(infilename, passphrase, &error); if (ssh2key == SSH2_WRONG_PASSPHRASE) { error = "wrong passphrase"; ssh2key = 0; } else if (ssh2key) error = NULL; else if (!error) error = "unknown error"; break; case SSH_KEYTYPE_OPENSSH: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, passphrase, &error); if (ssh2key) { if (ssh2key != SSH2_WRONG_PASSPHRASE) error = NULL; else { ssh2key = NULL; error = "wrong passphrase"; } } else if (!error) error = "unknown error"; break; default: assert(0); } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "data")) { if (!ssh1key && !ssh2key) { fzprintf(sftpError, "No key loaded"); continue; } if (ssh1key) { char data[512]; char* p; strcpy(data, "ssh1 "); p = data + strlen(data); rsa_fingerprint(p, sizeof(data) - (p - data), ssh1key); fzprintf(sftpReply, "%s", data); continue; } if (ssh2key) { char* fingerprint = ssh2key->alg->fingerprint(ssh2key->data); if (fingerprint) { fzprintf(sftpReply, "%s", fingerprint); continue; } } fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "write")) { int ret; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (!ssh1key && !ssh2key) { fzprintf(sftpError, "No key loaded"); continue; } outfilename = filename_from_str(args); if (ssh1key) { ret = saversakey(outfilename, ssh1key, 0); if (!ret) { fzprintf(sftpError, "Unable to save SSH-1 private key"); continue; } } else if (ssh2key) { ret = ssh2_save_userkey(outfilename, ssh2key, 0); if (!ret) { fzprintf(sftpError, "Unable to save SSH-2 private key"); continue; } } fzprintf(sftpReply, ""); } else fzprintf(sftpError, "Unknown command"); }