зеркало из https://github.com/github/putty.git
Improved means of IPC between agent and PuTTY
[originally from svn r601]
This commit is contained in:
Родитель
9119c6e02f
Коммит
0e67e1b291
173
pageant.c
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);
|
||||
|
|
136
pageantc.c
136
pageantc.c
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче