Improved means of IPC between agent and PuTTY

[originally from svn r601]
This commit is contained in:
Simon Tatham 2000-09-19 16:29:28 +00:00
Родитель 9119c6e02f
Коммит 0e67e1b291
2 изменённых файлов: 126 добавлений и 183 удалений

173
pageant.c
Просмотреть файл

@ -3,6 +3,7 @@
*/
#include <windows.h>
#include <aclapi.h>
#include <stdio.h> /* FIXME */
#include "putty.h" /* FIXME */
#include "ssh.h"
@ -14,7 +15,13 @@
#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;
}
} else
return 0; /* invalid request */
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;
}
#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);

Просмотреть файл

@ -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