X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/2e85c969d67eb14a07314802d4ac5dd63eef660b..af723f2945eccb9ae3bc44f682457150c97cfa57:/windows/winpgen.c diff --git a/windows/winpgen.c b/windows/winpgen.c index baaf3d98..33d76c64 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -5,6 +5,7 @@ #include #include #include +#include #define PUTTY_DO_GLOBALS @@ -17,9 +18,9 @@ #define ICON_BIG 1 #endif -#define WM_DONEKEY (WM_XUSER + 1) +#define WM_DONEKEY (WM_APP + 1) -#define DEFAULT_KEYSIZE 1024 +#define DEFAULT_KEYSIZE 2048 static char *cmdline_keyfile = NULL; @@ -40,6 +41,22 @@ void modalfatalbox(char *fmt, ...) exit(1); } +/* + * Print a non-fatal message box and do not exit. + */ +void nonfatal(char *fmt, ...) +{ + va_list ap; + char *stuff; + + va_start(ap, fmt); + stuff = dupvprintf(fmt, ap); + va_end(ap); + MessageBox(NULL, stuff, "PuTTYgen Error", + MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); + sfree(stuff); +} + /* ---------------------------------------------------------------------- * Progress report code. This is really horrible :-) */ @@ -116,10 +133,8 @@ static void progress_update(void *param, int action, int phase, int iprogress) extern char ver[]; -#define PASSPHRASE_MAXLEN 512 - struct PassphraseProcStruct { - char *passphrase; + char **passphrase; char *comment; }; @@ -129,7 +144,7 @@ struct PassphraseProcStruct { static int CALLBACK PassphraseProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - static char *passphrase = NULL; + static char **passphrase = NULL; struct PassphraseProcStruct *p; switch (msg) { @@ -157,8 +172,9 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg, passphrase = p->passphrase; if (p->comment) SetDlgItemText(hwnd, 101, p->comment); - *passphrase = 0; - SetDlgItemText(hwnd, 102, passphrase); + burnstr(*passphrase); + *passphrase = dupstr(""); + SetDlgItemText(hwnd, 102, *passphrase); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { @@ -173,9 +189,8 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg, return 0; case 102: /* edit box */ if ((HIWORD(wParam) == EN_CHANGE) && passphrase) { - GetDlgItemText(hwnd, 102, passphrase, - PASSPHRASE_MAXLEN - 1); - passphrase[PASSPHRASE_MAXLEN - 1] = '\0'; + burnstr(*passphrase); + *passphrase = GetDlgItemText_alloc(hwnd, 102); } return 0; } @@ -405,11 +420,11 @@ static int save_ssh1_pubkey(char *filename, struct RSAKey *key) char *dec1, *dec2; FILE *fp; - dec1 = bignum_decimal(key->exponent); - dec2 = bignum_decimal(key->modulus); 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); @@ -615,19 +630,18 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status) } void load_key_file(HWND hwnd, struct MainDlgState *state, - Filename filename, int was_import_cmd) + Filename *filename, int was_import_cmd) { - char passphrase[PASSPHRASE_MAXLEN]; + char *passphrase; int needs_pass; int type, realtype; int ret; const char *errmsg = NULL; char *comment; - struct PassphraseProcStruct pps; struct RSAKey newkey1; struct ssh2_userkey *newkey2 = NULL; - type = realtype = key_type(&filename); + type = realtype = key_type(filename); if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2 && !import_possible(type)) { @@ -646,19 +660,22 @@ void load_key_file(HWND hwnd, struct MainDlgState *state, } comment = NULL; + passphrase = NULL; if (realtype == SSH_KEYTYPE_SSH1) - needs_pass = rsakey_encrypted(&filename, &comment); + needs_pass = rsakey_encrypted(filename, &comment); else if (realtype == SSH_KEYTYPE_SSH2) - needs_pass = - ssh2_userkey_encrypted(&filename, &comment); + needs_pass = ssh2_userkey_encrypted(filename, &comment); else - needs_pass = import_encrypted(&filename, realtype, - &comment); - pps.passphrase = passphrase; - pps.comment = comment; + 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, @@ -667,22 +684,20 @@ void load_key_file(HWND hwnd, struct MainDlgState *state, ret = -2; break; } + assert(passphrase != NULL); } else - *passphrase = '\0'; + passphrase = dupstr(""); if (type == SSH_KEYTYPE_SSH1) { if (realtype == type) - ret = loadrsakey(&filename, &newkey1, - passphrase, &errmsg); + ret = loadrsakey(filename, &newkey1, passphrase, &errmsg); else - ret = import_ssh1(&filename, realtype, - &newkey1, passphrase, &errmsg); + ret = import_ssh1(filename, realtype, &newkey1, + passphrase, &errmsg); } else { if (realtype == type) - newkey2 = ssh2_load_userkey(&filename, - passphrase, &errmsg); + newkey2 = ssh2_load_userkey(filename, passphrase, &errmsg); else - newkey2 = import_ssh2(&filename, realtype, - passphrase, &errmsg); + newkey2 = import_ssh2(filename, realtype, passphrase, &errmsg); if (newkey2 == SSH2_WRONG_PASSPHRASE) ret = -1; else if (!newkey2) @@ -784,6 +799,7 @@ void load_key_file(HWND hwnd, struct MainDlgState *state, MB_OK | MB_ICONINFORMATION); } } + burnstr(passphrase); } /* @@ -800,16 +816,16 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, switch (msg) { case WM_INITDIALOG: - if (help_path) - SetWindowLong(hwnd, GWL_EXSTYLE, - GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP); + if (has_help()) + SetWindowLongPtr(hwnd, GWL_EXSTYLE, + GetWindowLongPtr(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; SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200))); @@ -818,7 +834,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, state->collecting_entropy = FALSE; state->entropy = NULL; state->key_exists = FALSE; - SetWindowLong(hwnd, GWL_USERDATA, (LONG) state); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) state); { HMENU menu, menu1; @@ -855,7 +871,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, menu1 = CreateMenu(); AppendMenu(menu1, MF_ENABLED, IDC_ABOUT, "&About"); - if (help_path) + if (has_help()) AppendMenu(menu1, MF_ENABLED, IDC_GIVEHELP, "&Help"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Help"); @@ -938,12 +954,15 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, /* * Load a key file if one was provided on the command line. */ - if (cmdline_keyfile) - load_key_file(hwnd, state, filename_from_str(cmdline_keyfile), 0); + if (cmdline_keyfile) { + Filename *fn = filename_from_str(cmdline_keyfile); + load_key_file(hwnd, state, fn, 0); + filename_free(fn); + } return 1; case WM_MOUSEMOVE: - state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->collecting_entropy && state->entropy && state->entropy_got < state->entropy_required) { state->entropy[state->entropy_got++] = lParam; @@ -958,7 +977,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, * Seed the entropy pool */ random_add_heavynoise(state->entropy, state->entropy_size); - memset(state->entropy, 0, state->entropy_size); + smemclr(state->entropy, state->entropy_size); sfree(state->entropy); state->collecting_entropy = FALSE; @@ -994,7 +1013,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, case IDC_KEYSSH2DSA: { state = (struct MainDlgState *) - GetWindowLong(hwnd, GWL_USERDATA); + GetWindowLongPtr(hwnd, GWLP_USERDATA); if (!IsDlgButtonChecked(hwnd, LOWORD(wParam))) CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, LOWORD(wParam)); @@ -1008,7 +1027,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, case IDC_COMMENTEDIT: if (HIWORD(wParam) == EN_CHANGE) { state = (struct MainDlgState *) - GetWindowLong(hwnd, GWL_USERDATA); + GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->key_exists) { HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT); int len = GetWindowTextLength(editctl); @@ -1035,11 +1054,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, case IDC_GIVEHELP: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { - if (help_path) { - WinHelp(hwnd, help_path, HELP_COMMAND, - (DWORD)"JI(`',`puttygen.general')"); - requested_help = TRUE; - } + launch_help(hwnd, WINHELP_CTX_puttygen_general); } return 0; case IDC_GENERATE: @@ -1047,7 +1062,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, HIWORD(wParam) != BN_DOUBLECLICKED) break; state = - (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (!state->generation_thread_exists) { BOOL ok; state->keysize = GetDlgItemInt(hwnd, IDC_BITS, &ok, FALSE); @@ -1103,11 +1118,10 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, if (HIWORD(wParam) != BN_CLICKED) break; state = - (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->key_exists) { char filename[FILENAME_MAX]; - char passphrase[PASSPHRASE_MAXLEN]; - char passphrase2[PASSPHRASE_MAXLEN]; + char *passphrase, *passphrase2; int type, realtype; if (state->ssh2) @@ -1133,16 +1147,17 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, break; } - GetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, - passphrase, sizeof(passphrase)); - GetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, - passphrase2, sizeof(passphrase2)); + passphrase = GetDlgItemText_alloc(hwnd, IDC_PASSPHRASE1EDIT); + passphrase2 = GetDlgItemText_alloc(hwnd, IDC_PASSPHRASE2EDIT); if (strcmp(passphrase, passphrase2)) { MessageBox(hwnd, "The two passphrases given do not match.", "PuTTYgen Error", MB_OK | MB_ICONERROR); + burnstr(passphrase); + burnstr(passphrase2); break; } + burnstr(passphrase2); if (!*passphrase) { int ret; ret = MessageBox(hwnd, @@ -1150,8 +1165,10 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, "without a passphrase to protect it?", "PuTTYgen Warning", MB_YESNO | MB_ICONWARNING); - if (ret != IDYES) - break; + if (ret != IDYES) { + burnstr(passphrase); + break; + } } if (prompt_keyfile(hwnd, "Save private key as:", filename, 1, (type == realtype))) { @@ -1165,40 +1182,45 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, ret = MessageBox(hwnd, buffer, "PuTTYgen Warning", MB_YESNO | MB_ICONWARNING); sfree(buffer); - if (ret != IDYES) + if (ret != IDYES) { + burnstr(passphrase); break; + } } if (state->ssh2) { - Filename fn = filename_from_str(filename); + Filename *fn = filename_from_str(filename); if (type != realtype) - ret = export_ssh2(&fn, type, &state->ssh2key, + ret = export_ssh2(fn, type, &state->ssh2key, *passphrase ? passphrase : NULL); else - ret = ssh2_save_userkey(&fn, &state->ssh2key, + ret = ssh2_save_userkey(fn, &state->ssh2key, *passphrase ? passphrase : NULL); + filename_free(fn); } else { - Filename fn = filename_from_str(filename); + Filename *fn = filename_from_str(filename); if (type != realtype) - ret = export_ssh1(&fn, type, &state->key, + ret = export_ssh1(fn, type, &state->key, *passphrase ? passphrase : NULL); else - ret = saversakey(&fn, &state->key, + ret = saversakey(fn, &state->key, *passphrase ? passphrase : NULL); + filename_free(fn); } if (ret <= 0) { MessageBox(hwnd, "Unable to save key file", "PuTTYgen Error", MB_OK | MB_ICONERROR); } } + burnstr(passphrase); } break; case IDC_SAVEPUB: if (HIWORD(wParam) != BN_CLICKED) break; state = - (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->key_exists) { char filename[FILENAME_MAX]; if (prompt_keyfile(hwnd, "Save public key as:", @@ -1233,19 +1255,21 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, if (HIWORD(wParam) != BN_CLICKED) break; state = - (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (!state->generation_thread_exists) { char filename[FILENAME_MAX]; if (prompt_keyfile(hwnd, "Load private key:", - filename, 0, LOWORD(wParam)==IDC_LOAD)) - load_key_file(hwnd, state, filename_from_str(filename), - LOWORD(wParam) != IDC_LOAD); + filename, 0, LOWORD(wParam)==IDC_LOAD)) { + Filename *fn = filename_from_str(filename); + load_key_file(hwnd, state, fn, LOWORD(wParam) != IDC_LOAD); + filename_free(fn); + } } break; } return 0; case WM_DONEKEY: - state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); state->generation_thread_exists = FALSE; state->key_exists = TRUE; SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, @@ -1330,7 +1354,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, ui_set_state(hwnd, state, 2); break; case WM_HELP: - if (help_path) { + { int id = ((LPHELPINFO)lParam)->iCtrlId; char *topic = NULL; switch (id) { @@ -1338,81 +1362,70 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, case IDC_PROGRESS: case IDC_GENSTATIC: case IDC_GENERATE: - topic = "puttygen.generate"; break; + topic = WINHELP_CTX_puttygen_generate; break; case IDC_PKSTATIC: case IDC_KEYDISPLAY: - topic = "puttygen.pastekey"; break; + topic = WINHELP_CTX_puttygen_pastekey; break; case IDC_FPSTATIC: case IDC_FINGERPRINT: - topic = "puttygen.fingerprint"; break; + topic = WINHELP_CTX_puttygen_fingerprint; break; case IDC_COMMENTSTATIC: case IDC_COMMENTEDIT: - topic = "puttygen.comment"; break; + topic = WINHELP_CTX_puttygen_comment; break; case IDC_PASSPHRASE1STATIC: case IDC_PASSPHRASE1EDIT: case IDC_PASSPHRASE2STATIC: case IDC_PASSPHRASE2EDIT: - topic = "puttygen.passphrase"; break; + topic = WINHELP_CTX_puttygen_passphrase; break; case IDC_LOADSTATIC: case IDC_LOAD: - topic = "puttygen.load"; break; + topic = WINHELP_CTX_puttygen_load; break; case IDC_SAVESTATIC: case IDC_SAVE: - topic = "puttygen.savepriv"; break; + topic = WINHELP_CTX_puttygen_savepriv; break; case IDC_SAVEPUB: - topic = "puttygen.savepub"; break; + topic = WINHELP_CTX_puttygen_savepub; break; case IDC_TYPESTATIC: case IDC_KEYSSH1: case IDC_KEYSSH2RSA: case IDC_KEYSSH2DSA: - topic = "puttygen.keytype"; break; + topic = WINHELP_CTX_puttygen_keytype; break; case IDC_BITSSTATIC: case IDC_BITS: - topic = "puttygen.bits"; break; + topic = WINHELP_CTX_puttygen_bits; break; case IDC_IMPORT: case IDC_EXPORT_OPENSSH: case IDC_EXPORT_SSHCOM: - topic = "puttygen.conversions"; break; + topic = WINHELP_CTX_puttygen_conversions; break; } if (topic) { - char *cmd = dupprintf("JI(`',`%s')", topic); - WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd); - sfree(cmd); - requested_help = TRUE; + launch_help(hwnd, topic); } else { MessageBeep(0); } } break; case WM_CLOSE: - state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA); + state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); sfree(state); - if (requested_help) { - WinHelp(hwnd, help_path, HELP_QUIT, 0); - requested_help = FALSE; - } + quit_help(hwnd); EndDialog(hwnd, 1); return 0; } return 0; } -void cleanup_exit(int code) { exit(code); } +void cleanup_exit(int code) +{ + shutdown_help(); + exit(code); +} int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { int argc; char **argv; - - split_into_argv(cmdline, &argc, &argv, NULL); - - if (argc > 0) { - /* - * Assume the first argument to be a private key file, and - * attempt to load it. - */ - cmdline_keyfile = argv[0]; - } + int ret; InitCommonControls(); hinst = inst; @@ -1421,24 +1434,26 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * See if we can find our Help file. */ - { - char b[2048], *p, *q, *r; - FILE *fp; - GetModuleFileName(NULL, b, sizeof(b) - 1); - r = b; - p = strrchr(b, '\\'); - if (p && p >= r) r = p+1; - q = strrchr(b, ':'); - if (q && q >= r) r = q+1; - strcpy(r, PUTTY_HELP_FILE); - if ( (fp = fopen(b, "r")) != NULL) { - help_path = dupstr(b); - fclose(fp); - } else - help_path = NULL; + init_help(); + + split_into_argv(cmdline, &argc, &argv, NULL); + + if (argc > 0) { + if (!strcmp(argv[0], "-pgpfp")) { + pgp_fingerprints(); + exit(1); + } else { + /* + * Assume the first argument to be a private key file, and + * attempt to load it. + */ + cmdline_keyfile = argv[0]; + } } random_ref(); - return DialogBox(hinst, MAKEINTRESOURCE(201), NULL, - MainDlgProc) != IDOK; + ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK; + + cleanup_exit(ret); + return ret; /* just in case optimiser complains */ }