+ } 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;
+ }
+ }