Improved means of IPC between agent and PuTTY
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 19 Sep 2000 16:29:28 +0000 (16:29 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 19 Sep 2000 16:29:28 +0000 (16:29 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@601 cda61777-01e9-0310-a592-d414129be87e

pageant.c
pageantc.c

index 6639275..7133c8d 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -3,6 +3,7 @@
  */
 
 #include <windows.h>
+#include <aclapi.h>
 #include <stdio.h> /* FIXME */
 #include "putty.h" /* FIXME */
 #include "ssh.h"
 #define WM_XUSER     (WM_USER + 0x2000)
 #define WM_SYSTRAY   (WM_XUSER + 6)
 #define WM_SYSTRAY2  (WM_XUSER + 7)
-#define WM_CLOSEMEM  (WM_XUSER + 10)
+
+#define AGENT_COPYDATA_ID 0x804e50ba   /* random goop */
+
+/*
+ * FIXME: maybe some day we can sort this out ...
+ */
+#define AGENT_MAX_MSGLEN  8192
 
 #define IDM_CLOSE    0x0010
 #define IDM_VIEWKEYS 0x0020
@@ -151,26 +158,17 @@ void add_keyfile(char *filename) {
 /*
  * This is the main agent function that answers messages.
  */
-void answer_msg(void *in, int inlen, void **out, int *outlen) {
-    unsigned char *ret;
-    unsigned char *p = in;
+void answer_msg(void *msg) {
+    unsigned char *p = msg;
+    unsigned char *ret = msg;
     int type;
 
-    *out = NULL;                       /* default `no go' response */
-
-    /*
-     * Basic sanity checks. len >= 5, and len[0:4] holds len-4.
-     */
-    if (inlen < 5 || GET_32BIT(p) != (unsigned long)(inlen-4))
-        return;
-
     /*
      * Get the message type.
      */
     type = p[4];
 
     p += 5;
-
     switch (type) {
       case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
         /*
@@ -198,20 +196,20 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
              * bytes for the key count.
              */
             len += 5 + 4;
-            if ((ret = malloc(len)) != NULL) {
-                PUT_32BIT(ret, len-4);
-                ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER;
-                PUT_32BIT(ret+5, nkeys);
-                p = ret + 5 + 4;
-                for (key = first234(rsakeys, &e); key; key = next234(&e)) {
-                    PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus));
-                    p += 4;
-                    p += ssh1_write_bignum(p, key->exponent);
-                    p += ssh1_write_bignum(p, key->modulus);
-                    PUT_32BIT(p, strlen(key->comment));
-                    memcpy(p+4, key->comment, strlen(key->comment));
-                    p += 4 + strlen(key->comment);
-                }
+            if (len > AGENT_MAX_MSGLEN)
+                goto failure;          /* aaargh! too much stuff! */
+            PUT_32BIT(ret, len-4);
+            ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER;
+            PUT_32BIT(ret+5, nkeys);
+            p = ret + 5 + 4;
+            for (key = first234(rsakeys, &e); key; key = next234(&e)) {
+                PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus));
+                p += 4;
+                p += ssh1_write_bignum(p, key->exponent);
+                p += ssh1_write_bignum(p, key->modulus);
+                PUT_32BIT(p, strlen(key->comment));
+                memcpy(p+4, key->comment, strlen(key->comment));
+                p += 4 + strlen(key->comment);
             }
         }
         break;
@@ -258,11 +256,9 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
              * bytes of MD5.
              */
             len = 5 + 16;
-            if ((ret = malloc(len)) != NULL) {
-                PUT_32BIT(ret, len-4);
-                ret[4] = SSH_AGENT_RSA_RESPONSE;
-                memcpy(ret+5, response_md5, 16);
-            }
+            PUT_32BIT(ret, len-4);
+            ret[4] = SSH_AGENT_RSA_RESPONSE;
+            memcpy(ret+5, response_md5, 16);
         }
         break;
 #if 0 /* FIXME: implement these */
@@ -285,17 +281,10 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
         /*
          * Unrecognised message. Return SSH_AGENT_FAILURE.
          */
-        if ((ret = malloc(5)) != NULL) {
-            PUT_32BIT(ret, 1);
-            ret[4] = SSH_AGENT_FAILURE;
-        }
+        PUT_32BIT(ret, 1);
+        ret[4] = SSH_AGENT_FAILURE;
         break;
     }
-
-    if (ret) {
-        *out = ret;
-        *outlen = 4 + GET_32BIT(ret);
-    }
 }
 
 /*
@@ -465,45 +454,77 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
       case WM_COPYDATA:
         {
             COPYDATASTRUCT *cds;
-            void *in, *out, *ret;
-            int inlen, outlen;
-            HANDLE filemap;
-            char mapname[64];
-            int id;
+            char *mapname;
+            void *p;
+            HANDLE filemap, proc;
+            PSID mapowner, procowner;
+            PSECURITY_DESCRIPTOR psd1 = NULL, psd2 = NULL;
+            int ret = 0;
 
             cds = (COPYDATASTRUCT *)lParam;
-            /*
-             * FIXME: use dwData somehow.
-             */
-            in = cds->lpData;
-            inlen = cds->cbData;
-            answer_msg(in, inlen, &out, &outlen);
-            if (out) {
-                id = 0;
-                do {
-                    sprintf(mapname, "PageantReply%08x", ++id);
-                   filemap = CreateFileMapping(INVALID_HANDLE_VALUE,
-                                                NULL, PAGE_READWRITE,
-                                               0, outlen+sizeof(int),
-                                                mapname);
-                } while (filemap == INVALID_HANDLE_VALUE);
-                ret = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0,
-                                    outlen+sizeof(int));
-                if (ret) {
-                    *((int *)ret) = outlen;
-                    memcpy(((int *)ret)+1, out, outlen);
-                    UnmapViewOfFile(ret);
-                    return id;
+            if (cds->dwData != AGENT_COPYDATA_ID)
+                return 0;              /* not our message, mate */
+            mapname = (char *)cds->lpData;
+            if (mapname[cds->cbData - 1] != '\0')
+                return 0;              /* failure to be ASCIZ! */
+#ifdef DEBUG_IPC
+            debug(("mapname is :%s:\r\n", mapname));
+#endif
+            filemap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, mapname);
+#ifdef DEBUG_IPC
+            debug(("filemap is %p\r\n", filemap));
+#endif
+            if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) {
+                int rc;
+                if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
+                                        GetCurrentProcessId())) == NULL) {
+#ifdef DEBUG_IPC
+                    debug(("couldn't get handle for process\r\n"));
+#endif
+                    return 0;
+                }
+                if (GetSecurityInfo(proc, SE_KERNEL_OBJECT,
+                                    OWNER_SECURITY_INFORMATION,
+                                    &procowner, NULL, NULL, NULL,
+                                    &psd2) != ERROR_SUCCESS) {
+#ifdef DEBUG_IPC
+                    debug(("couldn't get owner info for process\r\n"));
+#endif
+                    CloseHandle(proc);
+                    return 0;          /* unable to get security info */
+                }
+                CloseHandle(proc);
+                if ((rc = GetSecurityInfo(filemap, SE_KERNEL_OBJECT,
+                                          OWNER_SECURITY_INFORMATION,
+                                          &mapowner, NULL, NULL, NULL,
+                                          &psd1) != ERROR_SUCCESS)) {
+#ifdef DEBUG_IPC
+                    debug(("couldn't get owner info for filemap: %d\r\n", rc));
+#endif
+                    return 0;
                 }
-            } else
-                return 0;              /* invalid request */
+#ifdef DEBUG_IPC
+                debug(("got security stuff\r\n"));
+#endif
+                if (!EqualSid(mapowner, procowner))
+                    return 0;          /* security ID mismatch! */
+#ifdef DEBUG_IPC
+                debug(("security stuff matched\r\n"));
+#endif
+                LocalFree(psd1);
+                LocalFree(psd2);
+                p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
+#ifdef DEBUG_IPC
+                debug(("p is %p\r\n", p));
+                {int i; for(i=0;i<5;i++)debug(("p[%d]=%02x\r\n", i, ((unsigned char *)p)[i]));}
+#endif
+                answer_msg(p);
+                ret = 1;
+                UnmapViewOfFile(p);
+            }
+            CloseHandle(filemap);
+            return ret;
         }
-        break;
-      case WM_CLOSEMEM:
-        /*
-         * FIXME!
-         */
-        break;
     }
 
     return DefWindowProc (hwnd, message, wParam, lParam);
index e718313..49b588e 100644 (file)
@@ -6,12 +6,21 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#define AGENT_COPYDATA_ID 0x804e50ba   /* random goop */
+#define AGENT_MAX_MSGLEN  8192
+
 #ifdef TESTMODE
 #define debug(x) (printf x)
 #else
 #define debug(x)
 #endif
 
+#define GET_32BIT(cp) \
+    (((unsigned long)(unsigned char)(cp)[0] << 24) | \
+    ((unsigned long)(unsigned char)(cp)[1] << 16) | \
+    ((unsigned long)(unsigned char)(cp)[2] << 8) | \
+    ((unsigned long)(unsigned char)(cp)[3]))
+
 int agent_exists(void) {
     HWND hwnd;
     hwnd = FindWindow("Pageant", "Pageant");
@@ -22,93 +31,10 @@ int agent_exists(void) {
 }
 
 void agent_query(void *in, int inlen, void **out, int *outlen) {
-#if 0
-#define MAILSLOTNAME "\\\\.\\mailslot\\pageant_listener"
-    SECURITY_ATTRIBUTES sa;
-    HANDLE my_mailslot, agent_mailslot;
-    char name[64];
-    char *p;
-    DWORD msglen, byteswritten, bytesread, inid;
-
-    *out = NULL;
-    *outlen = 0;
-
-    agent_mailslot = CreateFile(MAILSLOTNAME, GENERIC_WRITE,
-                                FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
-                                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
-                                (HANDLE)NULL);
-    debug(("opened %s: %p\n", MAILSLOTNAME, agent_mailslot));
-    if (agent_mailslot == INVALID_HANDLE_VALUE)
-        return;
-
-    inid = GetCurrentThreadId();
-    inid--;
-
-    sa.nLength = sizeof(sa);
-    sa.lpSecurityDescriptor = NULL;
-    sa.bInheritHandle = TRUE;
-
-    do {
-        sprintf(name, "\\\\.\\mailslot\\pclient_request_%08x", ++inid);
-        /*
-         * Five-minute timeout.
-         */
-        my_mailslot = CreateMailslot(name, 0, 0, &sa);
-        debug(("mailslot %s: %p\n", name, my_mailslot));
-    } while (my_mailslot == INVALID_HANDLE_VALUE);
-    Sleep(3000);
-
-    msglen = strlen(name) + 1 + inlen;
-    p = malloc(msglen);
-    if (!p) {
-        CloseHandle(my_mailslot);
-        CloseHandle(agent_mailslot);
-        return;
-    }
-
-    strcpy(p, name);
-    memcpy(p+strlen(p)+1, in, inlen);
-
-    debug(("ooh\n"));
-    if (WriteFile(agent_mailslot, p, msglen, &byteswritten, NULL) == 0) {
-        debug(("eek!\n"));
-        free(p);
-        CloseHandle(my_mailslot);
-        CloseHandle(agent_mailslot);
-        return;
-    }
-    debug(("aah\n"));
-    free(p);
-    CloseHandle(agent_mailslot);
-
-    WaitForSingleObject(my_mailslot, 3000000);
-    debug(("waited\n"));
-    if (!GetMailslotInfo(my_mailslot, NULL, &msglen, NULL, NULL)) {
-        CloseHandle(my_mailslot);
-        return;
-    }
-    if (msglen == MAILSLOT_NO_MESSAGE) {
-        debug(("no message\n"));
-        CloseHandle(my_mailslot);
-        return;
-    }
-    debug(("msglen=%d\n", msglen));
-    p = malloc(msglen);
-    if (!p) {
-        CloseHandle(my_mailslot);
-        return;
-    }
-    if (ReadFile(my_mailslot, p, msglen, &bytesread, NULL) == 0 &&
-        bytesread == msglen) {
-        *out = p;
-        *outlen = msglen;
-    }
-    CloseHandle(my_mailslot);
-#endif
     HWND hwnd;
     char mapname[64];
     HANDLE filemap;
-    void *p, *ret;
+    unsigned char *p, *ret;
     int id, retlen;
     COPYDATASTRUCT cds;
 
@@ -119,34 +45,30 @@ void agent_query(void *in, int inlen, void **out, int *outlen) {
     debug(("hwnd is %p\n", hwnd));
     if (!hwnd)
         return;
-    cds.dwData = 0;                    /* FIXME */
-    cds.cbData = inlen;
-    cds.lpData = in;
+    sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId());
+    filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                0, AGENT_MAX_MSGLEN, mapname);
+    if (!filemap)
+        return;
+    p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
+    memcpy(p, in, inlen);
+    cds.dwData = AGENT_COPYDATA_ID;
+    cds.cbData = 1+strlen(mapname);
+    cds.lpData = mapname;
     id = SendMessage(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
     debug(("return is %d\n", id));
     if (id > 0) {
-        sprintf(mapname, "PageantReply%08x", id);
-        filemap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname);
-        debug(("name is `%s', filemap is %p\n", mapname, filemap));
-        debug(("error is %d\n", GetLastError()));
-        if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) {
-            p = MapViewOfFile(filemap, FILE_MAP_READ, 0, 0, 0);
-            debug(("p is %p\n", p));
-            if (p) {
-                retlen = *(int *)p;
-                debug(("len is %d\n", retlen));
-                ret = malloc(retlen);
-                if (ret) {
-                    memcpy(ret, ((int *)p) + 1, retlen);
-                    *out = ret;
-                    *outlen = retlen;
-                }
-                UnmapViewOfFile(p);
-            }
-            CloseHandle(filemap);
+        retlen = 4 + GET_32BIT(p);
+        debug(("len is %d\n", retlen));
+        ret = malloc(retlen);
+        if (ret) {
+            memcpy(ret, p, retlen);
+            *out = ret;
+            *outlen = retlen;
         }
-        /* FIXME: tell agent to close its handle too */
     }
+    UnmapViewOfFile(p);
+    CloseHandle(filemap);
 }
 
 #ifdef TESTMODE