Pageant now accepts an initial key list on the command line
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 15 Sep 2000 10:48:42 +0000 (10:48 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 15 Sep 2000 10:48:42 +0000 (10:48 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@592 cda61777-01e9-0310-a592-d414129be87e

Makefile
pageant.c
ssh.c

index 38d9ff5..37d881e 100644 (file)
--- 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
index d7bd94c..6639275 100644 (file)
--- 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 dd8ffd5..613b23e 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -5,6 +5,7 @@
 #include <winsock.h>
 
 #include "putty.h"
+#include "tree234.h"
 #include "ssh.h"
 #include "scp.h"
 
 #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) {