Report an error if deleting a random seed file fails.
[u/mdw/putty] / windows / winpgen.c
index e35a8c1..aeebb62 100644 (file)
@@ -5,6 +5,7 @@
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
 
 #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;
        }
@@ -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,7 +816,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
 
     switch (msg) {
       case WM_INITDIALOG:
-        if (help_path)
+        if (has_help())
             SetWindowLongPtr(hwnd, GWL_EXSTYLE,
                             GetWindowLongPtr(hwnd, GWL_EXSTYLE) |
                             WS_EX_CONTEXTHELP);
@@ -810,7 +826,6 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
              * if the help file isn't present.
              */
         }
-        requested_help = FALSE;
        SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
                    (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200)));
 
@@ -856,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");
 
@@ -959,7 +974,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;
 
@@ -1036,11 +1051,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:
@@ -1107,8 +1118,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                (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)
@@ -1134,16 +1144,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,
@@ -1151,8 +1162,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))) {
@@ -1166,33 +1179,38 @@ 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:
@@ -1331,7 +1349,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) {
@@ -1339,47 +1357,44 @@ 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);
             }
@@ -1388,22 +1403,24 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
       case WM_CLOSE:
        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;
+    int ret;
 
     InitCommonControls();
     hinst = inst;
@@ -1412,22 +1429,7 @@ 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);
 
@@ -1445,6 +1447,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     }
 
     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 */
 }