INCOMPATIBLE CHANGE to the SSH2 private key file format. There is
[u/mdw/putty] / pageant.c
index 853341a..0114804 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -65,7 +65,7 @@ int agent_exists(void);
  * pads its data with random bytes. Since we only use rsadecrypt()
  * and the signing functions, which are deterministic, this should
  * never be called.
- * 
+ *
  * If it _is_ called, there is a _serious_ problem, because it
  * won't generate true random numbers. So we must scream, panic,
  * and exit immediately if that should happen.
@@ -74,6 +74,8 @@ int random_byte(void)
 {
     MessageBox(hwnd, "Internal Error", APPNAME, MB_OK | MB_ICONERROR);
     exit(0);
+    /* this line can't be reached but it placates MSVC's warnings :-) */
+    return 0;
 }
 
 /*
@@ -168,6 +170,8 @@ static int CALLBACK AboutProc(HWND hwnd, UINT msg,
     return 0;
 }
 
+static HWND passphrase_box;
+
 /*
  * Dialog-box function for the passphrase box.
  */
@@ -179,6 +183,7 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
 
     switch (msg) {
       case WM_INITDIALOG:
+       passphrase_box = hwnd;
        /*
         * Centre the window.
         */
@@ -232,6 +237,26 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
 }
 
 /*
+ * 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"
+       "You can perform this conversion by loading the key\n"
+       "into PuTTYgen and then saving it again.";
+
+    MessageBox(NULL, message, mbtitle, MB_OK);
+}
+
+/*
  * Update the visible key list.
  */
 static void keylist_update(void)
@@ -324,6 +349,7 @@ static void add_keyfile(char *filename)
            int dlgret;
            dlgret = DialogBoxParam(instance, MAKEINTRESOURCE(210),
                                    NULL, PassphraseProc, (LPARAM) & pps);
+           passphrase_box = NULL;
            if (!dlgret) {
                if (comment)
                    sfree(comment);
@@ -607,7 +633,7 @@ static void answer_msg(void *msg)
        break;
       case SSH2_AGENTC_SIGN_REQUEST:
        /*
-        * Reply with either SSH2_AGENT_RSA_RESPONSE or
+        * Reply with either SSH2_AGENT_SIGN_RESPONSE or
         * SSH_AGENT_FAILURE, depending on whether we have that key
         * or not.
         */
@@ -644,16 +670,19 @@ static void answer_msg(void *msg)
        {
            struct RSAKey *key;
            char *comment;
+            int commentlen;
            key = smalloc(sizeof(struct RSAKey));
-           memset(key, 0, sizeof(key));
+           memset(key, 0, sizeof(struct RSAKey));
            p += makekey(p, key, NULL, 1);
            p += makeprivate(p, key);
-           p += ssh1_read_bignum(p, key->iqmp);        /* p^-1 mod q */
-           p += ssh1_read_bignum(p, key->p);   /* p */
-           p += ssh1_read_bignum(p, key->q);   /* q */
-           comment = smalloc(GET_32BIT(p));
+           p += ssh1_read_bignum(p, &key->iqmp);       /* p^-1 mod q */
+           p += ssh1_read_bignum(p, &key->p);  /* p */
+           p += ssh1_read_bignum(p, &key->q);  /* q */
+            commentlen = GET_32BIT(p);
+           comment = smalloc(commentlen+1);
            if (comment) {
-               memcpy(comment, p + 4, GET_32BIT(p));
+               memcpy(comment, p + 4, commentlen);
+                comment[commentlen] = '\0';
                key->comment = comment;
            }
            PUT_32BIT(ret, 1);
@@ -687,6 +716,8 @@ static void answer_msg(void *msg)
            /* Add further algorithm names here. */
            if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
                key->alg = &ssh_rsa;
+           else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7))
+               key->alg = &ssh_dss;
            else {
                sfree(key);
                goto failure;
@@ -1017,6 +1048,11 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
          case 101:                    /* add key */
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
+               if (passphrase_box) {
+                   MessageBeep(MB_ICONERROR);
+                   SetForegroundWindow(passphrase_box);
+                   break;
+               }
                prompt_add_keyfile();
            }
            return 0;
@@ -1059,13 +1095,54 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
     return 0;
 }
 
+/* Set up a system tray icon */
+static BOOL AddTrayIcon(HWND hwnd)
+{
+    BOOL res;
+    NOTIFYICONDATA tnid;
+    HICON hicon;
+
+#ifdef NIM_SETVERSION
+    tnid.uVersion = 0;
+    res = Shell_NotifyIcon(NIM_SETVERSION, &tnid);
+#endif
+
+    tnid.cbSize = sizeof(NOTIFYICONDATA);
+    tnid.hWnd = hwnd;
+    tnid.uID = 1;             /* unique within this systray use */
+    tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+    tnid.uCallbackMessage = WM_SYSTRAY;
+    tnid.hIcon = hicon = LoadIcon(instance, MAKEINTRESOURCE(201));
+    strcpy(tnid.szTip, "Pageant (PuTTY authentication agent)");
+
+    res = Shell_NotifyIcon(NIM_ADD, &tnid);
+
+    if (hicon) DestroyIcon(hicon);
+    
+    return res;
+}
+
 static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                                WPARAM wParam, LPARAM lParam)
 {
     int ret;
     static int menuinprogress;
+    static UINT msgTaskbarCreated = 0;
 
     switch (message) {
+      case WM_CREATE:
+        msgTaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated"));
+        break;
+      default:
+        if (message==msgTaskbarCreated) {
+            /*
+            * Explorer has been restarted, so the tray icon will
+            * have been lost.
+            */
+           AddTrayIcon(hwnd);
+        }
+        break;
+        
       case WM_SYSTRAY:
        if (lParam == WM_RBUTTONUP) {
            POINT cursorpos;
@@ -1091,6 +1168,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
       case WM_SYSCOMMAND:
        switch (wParam & ~0xF) {       /* low 4 bits reserved to Windows */
          case IDM_CLOSE:
+           if (passphrase_box)
+               SendMessage(passphrase_box, WM_CLOSE, 0, 0);
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            break;
          case IDM_VIEWKEYS:
@@ -1108,6 +1187,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            }
            break;
          case IDM_ADDKEY:
+           if (passphrase_box) {
+               MessageBeep(MB_ICONERROR);
+               SetForegroundWindow(passphrase_box);
+               break;
+           }
            prompt_add_keyfile();
            break;
          case IDM_ABOUT:
@@ -1319,37 +1403,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
                            100, 100, NULL, NULL, inst, NULL);
 
        /* Set up a system tray icon */
-       {
-           BOOL res;
-           NOTIFYICONDATA tnid;
-           HICON hicon;
-
-#ifdef NIM_SETVERSION
-           tnid.uVersion = 0;
-           res = Shell_NotifyIcon(NIM_SETVERSION, &tnid);
-#endif
-
-           tnid.cbSize = sizeof(NOTIFYICONDATA);
-           tnid.hWnd = hwnd;
-           tnid.uID = 1;              /* unique within this systray use */
-           tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
-           tnid.uCallbackMessage = WM_SYSTRAY;
-           tnid.hIcon = hicon = LoadIcon(instance, MAKEINTRESOURCE(201));
-           strcpy(tnid.szTip, "Pageant (PuTTY authentication agent)");
-
-           res = Shell_NotifyIcon(NIM_ADD, &tnid);
-
-           if (hicon)
-               DestroyIcon(hicon);
-
-           systray_menu = CreatePopupMenu();
-           /* accelerators used: vkxa */
-           AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS,
-                      "&View Keys");
-           AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key");
-           AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About");
-           AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit");
-       }
+       AddTrayIcon(hwnd);
+
+        systray_menu = CreatePopupMenu();
+        /* accelerators used: vkxa */
+        AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS,
+               "&View Keys");
+        AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key");
+        AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About");
+        AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit");
 
        ShowWindow(hwnd, SW_HIDE);