Ensure our network layer is properly cleaned up before PuTTY exits.
[u/mdw/putty] / puttygen.c
index 7c3ef0d..6116e0f 100644 (file)
@@ -18,6 +18,8 @@
 
 #define DEFAULT_KEYSIZE 1024
 
+static int requested_help;
+
 /* ----------------------------------------------------------------------
  * Progress report code. This is really horrible :-)
  */
@@ -44,6 +46,9 @@ static void progress_update(void *param, int action, int phase, int iprogress)
     if (action < PROGFN_READY && p->nphases < phase)
        p->nphases = phase;
     switch (action) {
+      case PROGFN_INITIALISE:
+       p->nphases = 0;
+       break;
       case PROGFN_LIN_PHASE:
        p->phases[phase-1].exponential = 0;
        p->phases[phase-1].mult = p->phases[phase].total / progress;
@@ -302,6 +307,8 @@ static DWORD WINAPI generate_rsa_key_thread(void *param)
     struct progress prog;
     prog.progbar = params->progressbar;
 
+    progress_update(&prog, PROGFN_INITIALISE, 0, 0);
+
     if (params->is_dsa)
        dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
     else
@@ -401,6 +408,26 @@ static int save_ssh1_pubkey(char *filename, struct RSAKey *key)
     return 1;
 }
 
+/*
+ * Warn about the obsolescent key file format.
+ */
+void old_keyfile_warning(void)
+{
+    static const char mbtitle[] = "PuTTY Key File Warning";
+    static const char message[] =
+       "You are loading an SSH 2 private key which has an\n"
+       "old version of the file format. This means your key\n"
+       "file is not fully tamperproof. Future versions of\n"
+       "PuTTY may stop supporting this private key format,\n"
+       "so we recommend you convert your key to the new\n"
+       "format.\n"
+       "\n"
+       "Once the key is loaded into PuTTYgen, you can perform\n"
+       "this conversion simply by saving it again.";
+
+    MessageBox(NULL, message, mbtitle, MB_OK);
+}
+
 static int save_ssh2_pubkey(char *filename, struct ssh2_userkey *key)
 {
     unsigned char *pub_blob;
@@ -493,6 +520,17 @@ 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);
+        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.
         */
@@ -519,7 +557,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
 
            /* Accelerators used: acglops1rbd */
 
-           ctlposinit(&cp, hwnd, 10, 10, 10);
+           ctlposinit(&cp, hwnd, 4, 4, 4);
            bartitle(&cp, "Public and private key generation for PuTTY",
                     IDC_TITLE);
            beginbox(&cp, "Key", IDC_BOX_KEY);
@@ -530,7 +568,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
            progressbar(&cp2, IDC_PROGRESS);
            bigeditctrl(&cp,
                        "&Public key for pasting into authorized_keys file:",
-                       IDC_PKSTATIC, IDC_KEYDISPLAY, 7);
+                       IDC_PKSTATIC, IDC_KEYDISPLAY, 5);
            SendDlgItemMessage(hwnd, IDC_KEYDISPLAY, EM_SETREADONLY, 1, 0);
            staticedit(&cp, "Key fingerprint:", IDC_FPSTATIC,
                       IDC_FINGERPRINT, 75);
@@ -561,7 +599,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                       IDC_BITSSTATIC, IDC_BITS, 20);
            endbox(&cp);
        }
-       CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH1);
+       CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, IDC_KEYSSH1);
        SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);
 
        /*
@@ -683,6 +721,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                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);
@@ -868,6 +907,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                        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
@@ -956,6 +996,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
        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) {
@@ -1039,19 +1080,95 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
        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;
 }
 
+void cleanup_exit(int code) { exit(code); }
+
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     InitCommonControls();
     hinst = inst;
+
+    /*
+     * 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.hlp");
+        if ( (fp = fopen(b, "r")) != NULL) {
+            help_path = dupstr(b);
+            fclose(fp);
+        } else
+            help_path = NULL;
+    }
+
     random_init();
     return DialogBox(hinst, MAKEINTRESOURCE(201), NULL,
                     MainDlgProc) != IDOK;