Preliminary support for RSA user authentication in SSH2! Most of the
[u/mdw/putty] / pageant.c
index 62f60db..f4d5aa5 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -3,8 +3,12 @@
  */
 
 #include <windows.h>
+#ifndef NO_SECURITY
 #include <aclapi.h>
+#endif
 #include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
 #include "ssh.h"
 #include "tree234.h"
 
@@ -24,7 +28,8 @@
 
 #define IDM_CLOSE    0x0010
 #define IDM_VIEWKEYS 0x0020
-#define IDM_ABOUT    0x0030
+#define IDM_ADDKEY   0x0030
+#define IDM_ABOUT    0x0040
 
 #define APPNAME "Pageant"
 
 
 extern char ver[];
 
-HINSTANCE instance;
-HWND hwnd;
-HWND keylist;
-HWND aboutbox;
-HMENU systray_menu;
+static HINSTANCE instance;
+static HWND hwnd;
+static HWND keylist;
+static HWND aboutbox;
+static HMENU systray_menu;
 
-tree234 *rsakeys;
+static tree234 *rsakeys;
 
-int has_security;
+static int has_security;
+#ifndef NO_SECURITY
 typedef DWORD (WINAPI *gsi_fn_t)
     (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
                                  PSID *, PSID *, PACL *, PACL *,
                                  PSECURITY_DESCRIPTOR *);
-gsi_fn_t getsecurityinfo;
+static gsi_fn_t getsecurityinfo;
+#endif
 
 /*
  * We need this to link with the RSA code, because rsaencrypt()
@@ -157,6 +164,9 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
 
     switch (msg) {
       case WM_INITDIALOG:
+        SetForegroundWindow(hwnd);
+        SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
+                      SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
         p = (struct PassphraseProcStruct *)lParam;
         passphrase = p->passphrase;
         if (p->comment)
@@ -192,7 +202,7 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
 /*
  * Update the visible key list.
  */
-void keylist_update(void) {
+static void keylist_update(void) {
     struct RSAKey *key;
     enum234 e;
 
@@ -217,7 +227,7 @@ void keylist_update(void) {
 /*
  * This function loads a key from a file and adds it.
  */
-void add_keyfile(char *filename) {
+static void add_keyfile(char *filename) {
     char passphrase[PASSPHRASE_MAXLEN];
     struct RSAKey *key;
     int needs_pass;
@@ -228,7 +238,7 @@ void add_keyfile(char *filename) {
 
     needs_pass = rsakey_encrypted(filename, &comment);
     attempts = 0;
-    key = malloc(sizeof(*key));
+    key = smalloc(sizeof(*key));
     pps.passphrase = passphrase;
     pps.comment = comment;
     do {
@@ -238,8 +248,8 @@ void add_keyfile(char *filename) {
                                     NULL, PassphraseProc,
                                     (LPARAM)&pps);
             if (!dlgret) {
-                if (comment) free(comment);
-                free(key);
+                if (comment) sfree(comment);
+                sfree(key);
                 return;                /* operation cancelled */
             }
         } else
@@ -247,21 +257,21 @@ void add_keyfile(char *filename) {
         ret = loadrsakey(filename, key, passphrase);
         attempts++;
     } while (ret == -1);
-    if (comment) free(comment);
+    if (comment) sfree(comment);
     if (ret == 0) {
         MessageBox(NULL, "Couldn't load private key.", APPNAME,
                    MB_OK | MB_ICONERROR);
-        free(key);
+        sfree(key);
         return;
     }
     if (add234(rsakeys, key) != key)
-        free(key);                     /* already present, don't waste RAM */
+        sfree(key);                     /* already present, don't waste RAM */
 }
 
 /*
  * This is the main agent function that answers messages.
  */
-void answer_msg(void *msg) {
+static void answer_msg(void *msg) {
     unsigned char *p = msg;
     unsigned char *ret = msg;
     int type;
@@ -372,14 +382,14 @@ void answer_msg(void *msg) {
         {
             struct RSAKey *key;
             char *comment;
-            key = malloc(sizeof(struct RSAKey));
+            key = smalloc(sizeof(struct RSAKey));
             memset(key, 0, sizeof(key));
             p += makekey(p, key, NULL, 1);
             p += makeprivate(p, key);
             p += ssh1_read_bignum(p, NULL);    /* p^-1 mod q */
             p += ssh1_read_bignum(p, NULL);    /* p */
             p += ssh1_read_bignum(p, NULL);    /* q */
-            comment = malloc(GET_32BIT(p));
+            comment = smalloc(GET_32BIT(p));
             if (comment) {
                 memcpy(comment, p+4, GET_32BIT(p));
                 key->comment = comment;
@@ -391,7 +401,7 @@ void answer_msg(void *msg) {
                 ret[4] = SSH_AGENT_SUCCESS;
             } else {
                 freersakey(key);
-                free(key);
+                sfree(key);
             }
         }
         break;
@@ -432,7 +442,7 @@ void answer_msg(void *msg) {
 /*
  * Key comparison function for the 2-3-4 tree of RSA keys.
  */
-int cmpkeys(void *av, void *bv) {
+static int cmpkeys(void *av, void *bv) {
     struct RSAKey *a = (struct RSAKey *)av;
     struct RSAKey *b = (struct RSAKey *)bv;
     Bignum am, bm;
@@ -467,14 +477,40 @@ static void error(char *s) {
 }
 
 /*
+ * Prompt for a key file to add, and add it.
+ */
+static void prompt_add_keyfile(void) {
+    OPENFILENAME of;
+    char filename[FILENAME_MAX];
+    memset(&of, 0, sizeof(of));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+    of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#else
+    of.lStructSize = sizeof(of);
+#endif
+    of.hwndOwner = hwnd;
+    of.lpstrFilter = "All Files\0*\0\0\0";
+    of.lpstrCustomFilter = NULL;
+    of.nFilterIndex = 1;
+    of.lpstrFile = filename; *filename = '\0';
+    of.nMaxFile = sizeof(filename);
+    of.lpstrFileTitle = NULL;
+    of.lpstrInitialDir = NULL;
+    of.lpstrTitle = "Select Private Key File";
+    of.Flags = 0;
+    if (GetOpenFileName(&of)) {
+        add_keyfile(filename);
+        keylist_update();
+    }
+}
+
+/*
  * Dialog-box function for the key list box.
  */
 static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
                                 WPARAM wParam, LPARAM lParam) {
     enum234 e;
     struct RSAKey *key;
-    OPENFILENAME of;
-    char filename[FILENAME_MAX];
 
     switch (msg) {
       case WM_INITDIALOG:
@@ -496,26 +532,7 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
           case 101:                    /* add key */
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
-                memset(&of, 0, sizeof(of));
-#ifdef OPENFILENAME_SIZE_VERSION_400
-                of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
-                of.lStructSize = sizeof(of);
-#endif
-                of.hwndOwner = hwnd;
-                of.lpstrFilter = "All Files\0*\0\0\0";
-                of.lpstrCustomFilter = NULL;
-                of.nFilterIndex = 1;
-                of.lpstrFile = filename; *filename = '\0';
-                of.nMaxFile = sizeof(filename);
-                of.lpstrFileTitle = NULL;
-                of.lpstrInitialDir = NULL;
-                of.lpstrTitle = "Select Private Key File";
-                of.Flags = 0;
-                if (GetOpenFileName(&of)) {
-                    add_keyfile(filename);
-                    keylist_update();
-                }
+                prompt_add_keyfile();
             }
             return 0;
           case 102:                    /* remove key */
@@ -591,6 +608,9 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
                               SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
             }
             break;
+          case IDM_ADDKEY:
+            prompt_add_keyfile();
+            break;
           case IDM_ABOUT:
             if (!aboutbox) {
                 aboutbox = CreateDialog (instance, MAKEINTRESOURCE(213),
@@ -635,6 +655,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
 #endif
             if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) {
                 int rc;
+#ifndef NO_SECURITY
                 if (has_security) {
                     if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
                                             GetCurrentProcessId())) == NULL) {
@@ -678,6 +699,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
                     debug(("security APIs not present\r\n"));
 #endif
                 }
+#endif
                 p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
 #ifdef DEBUG_IPC
                 debug(("p is %p\r\n", p));
@@ -713,6 +735,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
         has_security = FALSE;
 
     if (has_security) {
+#ifndef NO_SECURITY
         /*
          * Attempt to ge the security API we need.
          */
@@ -725,6 +748,13 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
                        "Pageant Fatal Error", MB_ICONERROR | MB_OK);
             return 1;
         }
+#else
+       MessageBox(NULL,
+                  "This program has been compiled for Win9X and will\n"
+                  "not run on NT, in case it causes a security breach.",
+                  "Pageant Fatal Error", MB_ICONERROR | MB_OK);
+       return 1;
+#endif
     } else
         advapi = NULL;
 
@@ -788,8 +818,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
             DestroyIcon(hicon); 
 
         systray_menu = CreatePopupMenu();
-        /* accelerators used: vxa */
+        /* 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");
     }