From dacbd0e88298088e0506eb653ae3d1f596085f67 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 15 Sep 2000 10:48:42 +0000 Subject: [PATCH] Pageant now accepts an initial key list on the command line git-svn-id: svn://svn.tartarus.org/sgt/putty@592 cda61777-01e9-0310-a592-d414129be87e --- Makefile | 4 +- pageant.c | 30 +++++++------ ssh.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 161 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 38d9ff5e..37d881e7 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ MOBJS = misc.$(OBJ) version.$(OBJ) ##-- objects putty pscp plink OBJS1 = sshcrc.$(OBJ) sshdes.$(OBJ) sshmd5.$(OBJ) sshrsa.$(OBJ) sshrand.$(OBJ) OBJS2 = sshsha.$(OBJ) sshblowf.$(OBJ) noise.$(OBJ) sshdh.$(OBJ) sshdss.$(OBJ) -OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ) +OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ) tree234.$(OBJ) ##-- objects pageant PAGE1 = pageant.$(OBJ) sshrsa.$(OBJ) sshpubk.$(OBJ) sshdes.$(OBJ) sshbn.$(OBJ) PAGE2 = sshmd5.$(OBJ) version.$(OBJ) tree234.$(OBJ) @@ -183,7 +183,7 @@ xlat.$(OBJ): xlat.c putty.h ldisc.$(OBJ): ldisc.c putty.h misc.$(OBJ): misc.c putty.h noise.$(OBJ): noise.c putty.h ssh.h -ssh.$(OBJ): ssh.c ssh.h putty.h +ssh.$(OBJ): ssh.c ssh.h putty.h tree234.h sshcrc.$(OBJ): sshcrc.c ssh.h sshdes.$(OBJ): sshdes.c ssh.h sshmd5.$(OBJ): sshmd5.c ssh.h diff --git a/pageant.c b/pageant.c index d7bd94cf..66392753 100644 --- a/pageant.c +++ b/pageant.c @@ -21,8 +21,6 @@ #define APPNAME "Pageant" -#define MAILSLOTNAME "\\\\.\\mailslot\\pageant_listener" - #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENTC_RSA_CHALLENGE 3 @@ -513,7 +511,6 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { WNDCLASS wndclass; - HANDLE mailslot; MSG msg; instance = inst; @@ -573,21 +570,30 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { ShowWindow (hwnd, SW_HIDE); /* - * Create the mailslot. + * Initialise storage for RSA keys. + */ + rsakeys = newtree234(cmpkeys); + + /* + * Process the command line and add RSA keys as listed on it. + * FIXME: we don't support spaces in filenames here. We should. */ { - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - mailslot = CreateMailslot(MAILSLOTNAME, 0, 0, &sa); + char *p = cmdline; + while (*p) { + while (*p && isspace(*p)) p++; + if (*p && !isspace(*p)) { + char *q = p; + while (*p && !isspace(*p)) p++; + if (*p) *p++ = '\0'; + add_keyfile(q); + } + } } /* - * Initialise storage for RSA keys. + * Main message loop. */ - rsakeys = newtree234(cmpkeys); - while (GetMessage(&msg, NULL, 0, 0) == 1) { TranslateMessage(&msg); DispatchMessage(&msg); diff --git a/ssh.c b/ssh.c index dd8ffd57..613b23e3 100644 --- a/ssh.c +++ b/ssh.c @@ -5,6 +5,7 @@ #include #include "putty.h" +#include "tree234.h" #include "ssh.h" #include "scp.h" @@ -38,6 +39,13 @@ #define SSH1_SMSG_STDERR_DATA 18 #define SSH1_CMSG_EOF 19 #define SSH1_SMSG_EXIT_STATUS 20 +#define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION 21 +#define SSH1_MSG_CHANNEL_OPEN_FAILURE 22 +#define SSH1_MSG_CHANNEL_DATA 23 +#define SSH1_MSG_CHANNEL_CLOSE 24 +#define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION 25 +#define SSH1_CMSG_AGENT_REQUEST_FORWARDING 30 +#define SSH1_SMSG_AGENT_OPEN 31 #define SSH1_CMSG_EXIT_CONFIRMATION 33 #define SSH1_MSG_IGNORE 32 #define SSH1_MSG_DEBUG 36 @@ -146,7 +154,7 @@ struct ssh_hostkey *hostkey_algs[] = { &ssh_dss }; extern struct ssh_mac ssh_sha1; -SHA_State exhash; +static SHA_State exhash; static void nullmac_key(unsigned char *key) { } static void nullmac_generate(unsigned char *blk, int len, unsigned long seq) { } @@ -178,6 +186,37 @@ int (*ssh_get_password)(const char *prompt, char *str, int maxlen) = NULL; static char *savedhost; static int ssh_send_ok; +/* + * 2-3-4 tree storing channels. + */ +struct ssh_channel { + int remoteid, localid; + int type; + int closes; + union { + struct ssh_agent_channel { + unsigned char *message; + unsigned char msglen[4]; + int lensofar, totallen; + } a; + } u; +}; +static tree234 *ssh_channels; /* indexed by local id */ +static int ssh_channelcmp(void *av, void *bv) { + struct ssh_channel *a = (struct ssh_channel *)av; + struct ssh_channel *b = (struct ssh_channel *)bv; + if (a->localid < b->localid) return -1; + if (a->localid > b->localid) return +1; + return 0; +} +static int ssh_channelfind(void *av, void *bv) { + int *a = (int *)av; + struct ssh_channel *b = (struct ssh_channel *)bv; + if (*a < b->localid) return -1; + if (*a > b->localid) return +1; + return 0; +} + static enum { SSH_STATE_BEFORE_SIZE, SSH_STATE_INTERMED, @@ -1497,6 +1536,18 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { if (ssh_state == SSH_STATE_CLOSED) crReturnV; + if (1 /* FIXME: agent exists && agent forwarding configured */ ) { + logevent("Requesting agent forwarding"); + send_packet(SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END); + do { crReturnV; } while (!ispkt); + if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) { + fatalbox("Protocol confusion"); + } else if (pktin.type == SSH1_SMSG_FAILURE) { + logevent("Agent forwarding refused"); + } else + logevent("Agent forwarding enabled"); + } + if (!cfg.nopty) { send_packet(SSH1_CMSG_REQUEST_PTY, PKT_STR, cfg.termtype, @@ -1525,6 +1576,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { ssh_size(); ssh_send_ok = 1; + ssh_channels = newtree234(ssh_channelcmp); while (1) { crReturnV; if (ispkt) { @@ -1535,6 +1587,94 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { } else if (pktin.type == SSH1_MSG_DISCONNECT) { ssh_state = SSH_STATE_CLOSED; logevent("Received disconnect request"); + } else if (pktin.type == SSH1_SMSG_AGENT_OPEN) { + /* Remote side is trying to open a channel to talk to our + * agent. Give them back a local channel number. */ + int i = 1; + struct ssh_channel *c; + enum234 e; + for (c = first234(ssh_channels, &e); c; c = next234(&e)) { + if (c->localid > i) + break; /* found a free number */ + i = c->localid + 1; + } + c = malloc(sizeof(struct ssh_channel)); + c->remoteid = GET_32BIT(pktin.body); + c->localid = i; + c->type = SSH1_SMSG_AGENT_OPEN; /* identify channel type */ + add234(ssh_channels, c); + send_packet(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION, + PKT_INT, c->remoteid, PKT_INT, c->localid, + PKT_END); + } else if (pktin.type == SSH1_MSG_CHANNEL_CLOSE || + pktin.type == SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION) { + /* Remote side closes a channel. */ + int i = GET_32BIT(pktin.body); + struct ssh_channel *c; + c = find234(ssh_channels, &i, ssh_channelfind); + if (c) { + int closetype; + closetype = (pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2); + send_packet(pktin.type, PKT_INT, c->remoteid, PKT_END); + c->closes |= closetype; + if (c->closes == 3) { + del234(ssh_channels, c); + free(c); + } + } + } else if (pktin.type == SSH1_MSG_CHANNEL_DATA) { + /* Data sent down one of our channels. */ + int i = GET_32BIT(pktin.body); + int len = GET_32BIT(pktin.body+4); + unsigned char *p = pktin.body+8; + struct ssh_channel *c; + c = find234(ssh_channels, &i, ssh_channelfind); + if (c) { + switch(c->type) { + case SSH1_SMSG_AGENT_OPEN: + /* Data for an agent message. Buffer it. */ + while (len > 0) { + if (c->u.a.lensofar < 4) { + int l = min(4 - c->u.a.lensofar, len); + memcpy(c->u.a.msglen + c->u.a.lensofar, p, l); + p += l; len -= l; c->u.a.lensofar += l; + } + if (c->u.a.lensofar == 4) { + c->u.a.totallen = 4 + GET_32BIT(c->u.a.msglen); + c->u.a.message = malloc(c->u.a.totallen); + memcpy(c->u.a.message, c->u.a.msglen, 4); + } + if (c->u.a.lensofar >= 4 && len > 0) { + int l = min(c->u.a.totallen - c->u.a.lensofar, len); + memcpy(c->u.a.message + c->u.a.lensofar, p, l); + p += l; len -= l; c->u.a.lensofar += l; + } + if (c->u.a.lensofar == c->u.a.totallen) { + void *reply, *sentreply; + int replylen; + agent_query(c->u.a.message, c->u.a.totallen, + &reply, &replylen); + if (reply) + sentreply = reply; + else { + /* Fake SSH_AGENT_FAILURE. */ + sentreply = "\0\0\0\1\5"; + replylen = 5; + } + send_packet(SSH1_MSG_CHANNEL_DATA, + PKT_INT, c->remoteid, + PKT_INT, replylen, + PKT_DATA, sentreply, replylen, + PKT_END); + if (reply) + free(reply); + free(c->u.a.message); + c->u.a.lensofar = 0; + } + } + break; + } + } } else if (pktin.type == SSH1_SMSG_SUCCESS) { /* may be from EXEC_SHELL on some servers */ } else if (pktin.type == SSH1_SMSG_FAILURE) { -- 2.11.0