Index: pageant.c =================================================================== RCS file: /home/cvs/putty/pageant.c,v retrieving revision 1.70 diff -u -r1.70 pageant.c --- pageant.c 1 Aug 2004 12:07:11 -0000 1.70 +++ pageant.c 2 Aug 2004 10:33:26 -0000 @@ -19,6 +19,8 @@ #include #endif +#include + #define IDI_MAINICON 200 #define IDI_TRAYICON 201 @@ -54,6 +56,8 @@ char *help_path; static char *putty_path; +static FILE* xfer_fp; + #define IDM_PUTTY 0x0060 #define IDM_SESSIONS_BASE 0x1000 #define IDM_SESSIONS_MAX 0x2000 @@ -1262,6 +1266,82 @@ ret[4] = SSH_AGENT_SUCCESS; } break; + case SSH_AGENTC_XFER_REQUEST: + { + int fnamelen; + int pathlen; + char path[MAX_PATH]; + LPMALLOC lpmalloc; + LPITEMIDLIST lpiil; + + if(xfer_fp || msgend < p+4) /* can't have an already open connection */ + goto failure; + + fnamelen = GET_32BIT(p); + if(msgend < p+12+fnamelen) /* expect 3 int32's plus the filename */ + goto failure; + + /* Get the location of the user's desktop, in ASCII. We should probably + * use UNICODE here and convert the ssh-xfer supplied name, instead. + */ + if(SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &lpiil) != S_OK) + goto failure; + if(SHGetPathFromIDList(lpiil, path) != TRUE) + goto failure; + if(SHGetMalloc(&lpmalloc)) { /* free space using the shell COM object's allocator */ + lpmalloc->lpVtbl->Free(lpmalloc, lpiil); + lpmalloc->lpVtbl->Release(lpmalloc); + } + + /* Tack the given filename onto the end of the provided path */ + pathlen = strlen(path); + if(MAX_PATH < pathlen + fnamelen + 2) + goto failure; + path[pathlen] = '\\'; + memcpy(path + pathlen + 1, p+4, fnamelen); + path[pathlen + fnamelen + 1] = '\0'; + + xfer_fp = fopen(path, "wb"); + if(!xfer_fp) + goto failure; + PUT_32BIT(ret, 1); + ret[4] = SSH_AGENT_SUCCESS; + + } + break; + case SSH_AGENTC_XFER_DONE: + { + PUT_32BIT(ret, 1); + + if(xfer_fp) { + fclose(xfer_fp); + xfer_fp = NULL; + ret[4] = SSH_AGENT_SUCCESS; + } else { + ret[4] = SSH_AGENT_FAILURE; + } + + } + break; + case SSH_AGENTC_XFER_DATA: + { + int len; + + if(!xfer_fp || msgend < p+4) + goto failure; + + len = GET_32BIT(p); + + /* + * Make sure we're not going to overrun our buffer, + * and then make sure the write succeeds. + */ + if((msgend < p+len+4) || len != fwrite(p+4, 1, len, xfer_fp)) { + fclose(xfer_fp); + xfer_fp = NULL; + } + } + break; default: failure: /* @@ -2179,6 +2259,11 @@ FreeLibrary(advapi); return 0; } + + /* + * Initialise ssh-xfer + */ + xfer_fp = NULL; /* * Main message loop. Index: pageantc.c =================================================================== RCS file: /home/cvs/putty/pageantc.c,v retrieving revision 1.10 diff -u -r1.10 pageantc.c --- pageantc.c 21 Jan 2004 21:11:03 -0000 1.10 +++ pageantc.c 2 Aug 2004 10:33:26 -0000 @@ -81,16 +81,30 @@ unsigned char *p, *ret; int id, retlen; COPYDATASTRUCT cds; + int maplen; *out = NULL; *outlen = 0; + /* Establish the length of the mapping. As we're allocating the memory, + * we are not constrained by AGENT_MAX_MSGLEN - this is just the minimum + * amount of memory the agent expects to have for data that comes back + * to us. + * + * Round up to the nearest multiple of AGENT_MAX_MSGLEN. That way it's + * the minimum size, and if AGENT_MAX_MSGLEN is a multiple of the + * page size, we will be too. + */ + maplen = inlen + (AGENT_MAX_MSGLEN-1); + if(maplen < 1) maplen = 1; + maplen -= (maplen % AGENT_MAX_MSGLEN); + hwnd = FindWindow("Pageant", "Pageant"); if (!hwnd) return 1; /* *out == NULL, so failure */ mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId()); filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, AGENT_MAX_MSGLEN, mapname); + 0, maplen, mapname); if (!filemap) return 1; /* *out == NULL, so failure */ p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); Index: ssh.h =================================================================== RCS file: /home/cvs/putty/ssh.h,v retrieving revision 1.76 diff -u -r1.76 ssh.h --- ssh.h 1 Aug 2004 12:07:11 -0000 1.76 +++ ssh.h 2 Aug 2004 10:33:29 -0000 @@ -452,6 +452,11 @@ #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 +/* matt's filexfer-over-agent */ +#define SSH_AGENTC_XFER_REQUEST 90 +#define SSH_AGENTC_XFER_DONE 91 +#define SSH_AGENTC_XFER_DATA 92 + /* * Need this to warn about support for the original SSH2 keyfile * format.