data, sizeof(data));
data, sizeof(data), cfg.x11_auth);
static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt){    crBegin(ssh->ssh1_protocol_crstate);    random_init();    while (!do_ssh1_login(ssh, in, inlen, ispkt)) {	crReturnV;    }    if (ssh->state == SSH_STATE_CLOSED)	crReturnV;    if (cfg.agentfwd && agent_exists()) {	logevent("Requesting agent forwarding");	send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);	do {	    crReturnV;	} while (!ispkt);	if (ssh->pktin.type != SSH1_SMSG_SUCCESS	    && ssh->pktin.type != SSH1_SMSG_FAILURE) {	    bombout((ssh,"Protocol confusion"));	    crReturnV;	} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {	    logevent("Agent forwarding refused");	} else {	    logevent("Agent forwarding enabled");	    ssh->agentfwd_enabled = TRUE;	}    }    if (cfg.x11_forward) {	char proto[20], data[64];	logevent("Requesting X11 forwarding");	ssh->x11auth = x11_invent_auth(proto, sizeof(proto),				       data, sizeof(data));        x11_get_real_auth(ssh->x11auth, cfg.x11_display);	if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {	    send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,			PKT_STR, proto, PKT_STR, data,			PKT_INT, x11_get_screen_number(cfg.x11_display),			PKT_END);	} else {	    send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,			PKT_STR, proto, PKT_STR, data, PKT_END);	}	do {	    crReturnV;	} while (!ispkt);	if (ssh->pktin.type != SSH1_SMSG_SUCCESS	    && ssh->pktin.type != SSH1_SMSG_FAILURE) {	    bombout((ssh,"Protocol confusion"));	    crReturnV;	} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {	    logevent("X11 forwarding refused");	} else {	    logevent("X11 forwarding enabled");	    ssh->X11_fwd_enabled = TRUE;	}    }    {	char type;	int n;	int sport,dport,sserv,dserv;	char sports[256], dports[256], saddr[256], host[256];	ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);        /* Add port forwardings. */	ssh->portfwd_strptr = cfg.portfwd;	while (*ssh->portfwd_strptr) {	    type = *ssh->portfwd_strptr++;	    saddr[0] = '\0';	    n = 0;	    while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != '\t') {		if (*ssh->portfwd_strptr == ':') {		    /*		     * We've seen a colon in the middle of the		     * source port number. This means that		     * everything we've seen until now is the		     * source _address_, so we'll move it into		     * saddr and start sports from the beginning		     * again.		     */		    ssh->portfwd_strptr++;		    sports[n] = '\0';		    strcpy(saddr, sports);		    n = 0;		}		if (n < 255) sports[n++] = *ssh->portfwd_strptr++;	    }	    sports[n] = 0;	    if (*ssh->portfwd_strptr == '\t')		ssh->portfwd_strptr++;	    n = 0;	    while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') {		if (n < 255) host[n++] = *ssh->portfwd_strptr++;	    }	    host[n] = 0;	    if (*ssh->portfwd_strptr == ':')		ssh->portfwd_strptr++;	    n = 0;	    while (*ssh->portfwd_strptr) {		if (n < 255) dports[n++] = *ssh->portfwd_strptr++;	    }	    dports[n] = 0;	    ssh->portfwd_strptr++;	    dport = atoi(dports);	    dserv = 0;	    if (dport == 0) {		dserv = 1;		dport = net_service_lookup(dports);		if (!dport) {		    logeventf(ssh, "Service lookup failed for"			      " destination port \"%s\"", dports);		}	    }	    sport = atoi(sports);	    sserv = 0;	    if (sport == 0) {		sserv = 1;		sport = net_service_lookup(sports);		if (!sport) {		    logeventf(ssh, "Service lookup failed for source"			      " port \"%s\"", sports);		}	    }	    if (sport && dport) {		if (type == 'L') {		    pfd_addforward(host, dport, *saddr ? saddr : NULL,				   sport, ssh);		    logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s"			      " forwarding to %s:%.*s%.*s%d%.*s",			      (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL,			      (int)(*saddr?1:0), ":",			      (int)(sserv ? strlen(sports) : 0), sports,			      sserv, "(", sport, sserv, ")",			      host,			      (int)(dserv ? strlen(dports) : 0), dports,			      dserv, "(", dport, dserv, ")");		} else {		    struct ssh_rportfwd *pf;		    pf = smalloc(sizeof(*pf));		    strcpy(pf->dhost, host);		    pf->dport = dport;		    if (saddr) {			logeventf(ssh,				  "SSH1 cannot handle source address spec \"%s:%d\"; ignoring",				  saddr, sport);		    }		    if (add234(ssh->rportfwds, pf) != pf) {			logeventf(ssh, 				  "Duplicate remote port forwarding to %s:%d",				  host, dport);			sfree(pf);		    } else {			logeventf(ssh, "Requesting remote port %.*s%.*s%d%.*s"				  " forward to %s:%.*s%.*s%d%.*s",				  (int)(sserv ? strlen(sports) : 0), sports,				  sserv, "(", sport, sserv, ")",				  host,				  (int)(dserv ? strlen(dports) : 0), dports,				  dserv, "(", dport, dserv, ")");			send_packet(ssh, SSH1_CMSG_PORT_FORWARD_REQUEST,				    PKT_INT, sport,				    PKT_STR, host,				    PKT_INT, dport,				    PKT_END);			do {			    crReturnV;			} while (!ispkt);			if (ssh->pktin.type != SSH1_SMSG_SUCCESS			    && ssh->pktin.type != SSH1_SMSG_FAILURE) {			    bombout((ssh,"Protocol confusion"));			    crReturnV;			} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {			    c_write_str(ssh, "Server refused port"					" forwarding\r\n");			}			logevent("Remote port forwarding enabled");		    }		}	    }	}    }    if (!cfg.nopty) {	send_packet(ssh, SSH1_CMSG_REQUEST_PTY,		    PKT_STR, cfg.termtype,		    PKT_INT, ssh->term_height,		    PKT_INT, ssh->term_width,		    PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END);	ssh->state = SSH_STATE_INTERMED;	do {	    crReturnV;	} while (!ispkt);	if (ssh->pktin.type != SSH1_SMSG_SUCCESS	    && ssh->pktin.type != SSH1_SMSG_FAILURE) {	    bombout((ssh,"Protocol confusion"));	    crReturnV;	} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {	    c_write_str(ssh, "Server refused to allocate pty\r\n");	    ssh->editing = ssh->echoing = 1;	}	logevent("Allocated pty");    } else {	ssh->editing = ssh->echoing = 1;    }    if (cfg.compression) {	send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);	do {	    crReturnV;	} while (!ispkt);	if (ssh->pktin.type != SSH1_SMSG_SUCCESS	    && ssh->pktin.type != SSH1_SMSG_FAILURE) {	    bombout((ssh,"Protocol confusion"));	    crReturnV;	} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {	    c_write_str(ssh, "Server refused to compress\r\n");	}	logevent("Started compression");	ssh->v1_compressing = TRUE;	ssh->cs_comp_ctx = zlib_compress_init();	logevent("Initialised zlib (RFC1950) compression");	ssh->sc_comp_ctx = zlib_decompress_init();	logevent("Initialised zlib (RFC1950) decompression");    }    /*     * Start the shell or command.     *      * Special case: if the first-choice command is an SSH2     * subsystem (hence not usable here) and the second choice     * exists, we fall straight back to that.     */    {	char *cmd = cfg.remote_cmd_ptr;		if (cfg.ssh_subsys && cfg.remote_cmd_ptr2) {	    cmd = cfg.remote_cmd_ptr2;	    ssh->fallback_cmd = TRUE;	}	if (*cmd)	    send_packet(ssh, SSH1_CMSG_EXEC_CMD, PKT_STR, cmd, PKT_END);	else	    send_packet(ssh, SSH1_CMSG_EXEC_SHELL, PKT_END);	logevent("Started session");    }    ssh->state = SSH_STATE_SESSION;    if (ssh->size_needed)	ssh_size(ssh, ssh->term_width, ssh->term_height);    if (ssh->eof_needed)	ssh_special(ssh, TS_EOF);    if (ssh->ldisc)	ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */    ssh->send_ok = 1;    ssh->channels = newtree234(ssh_channelcmp);    while (1) {	crReturnV;	if (ispkt) {	    if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA ||		ssh->pktin.type == SSH1_SMSG_STDERR_DATA) {		long len = GET_32BIT(ssh->pktin.body);		int bufsize =		    from_backend(ssh->frontend,				 ssh->pktin.type == SSH1_SMSG_STDERR_DATA,				 (char *)(ssh->pktin.body) + 4, len);		if (!ssh->v1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {		    ssh->v1_stdout_throttling = 1;		    ssh1_throttle(ssh, +1);		}	    } else if (ssh->pktin.type == SSH1_MSG_DISCONNECT) {		ssh->state = SSH_STATE_CLOSED;		logevent("Received disconnect request");		crReturnV;	    } else if (ssh->pktin.type == SSH1_SMSG_X11_OPEN) {		/* Remote side is trying to open a channel to talk to our		 * X-Server. Give them back a local channel number. */		struct ssh_channel *c;		logevent("Received X11 connect request");		/* Refuse if X11 forwarding is disabled. */		if (!ssh->X11_fwd_enabled) {		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);		    logevent("Rejected X11 connect request");		} else {		    c = smalloc(sizeof(struct ssh_channel));		    c->ssh = ssh;		    if (x11_init(&c->u.x11.s, cfg.x11_display, c,				 ssh->x11auth) != NULL) {			logevent("opening X11 forward connection failed");			sfree(c);			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,				    PKT_INT, GET_32BIT(ssh->pktin.body),				    PKT_END);		    } else {			logevent			    ("opening X11 forward connection succeeded");			c->remoteid = GET_32BIT(ssh->pktin.body);			c->localid = alloc_channel_id(ssh);			c->closes = 0;			c->v.v1.throttling = 0;			c->type = CHAN_X11;	/* identify channel type */			add234(ssh->channels, c);			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,				    PKT_INT, c->remoteid, PKT_INT,				    c->localid, PKT_END);			logevent("Opened X11 forward channel");		    }		}	    } else if (ssh->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. */		struct ssh_channel *c;		/* Refuse if agent forwarding is disabled. */		if (!ssh->agentfwd_enabled) {		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);		} else {		    c = smalloc(sizeof(struct ssh_channel));		    c->ssh = ssh;		    c->remoteid = GET_32BIT(ssh->pktin.body);		    c->localid = alloc_channel_id(ssh);		    c->closes = 0;		    c->v.v1.throttling = 0;		    c->type = CHAN_AGENT;	/* identify channel type */		    c->u.a.lensofar = 0;		    add234(ssh->channels, c);		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,				PKT_INT, c->remoteid, PKT_INT, c->localid,				PKT_END);		}	    } else if (ssh->pktin.type == SSH1_MSG_PORT_OPEN) {   		/* Remote side is trying to open a channel to talk to a		 * forwarded port. Give them back a local channel number. */		struct ssh_channel *c;		struct ssh_rportfwd pf;		int hostsize, port;		char host[256], buf[1024];		char *p, *h, *e;		c = smalloc(sizeof(struct ssh_channel));		c->ssh = ssh;		hostsize = GET_32BIT(ssh->pktin.body+4);		for (h = host, p = (char *)(ssh->pktin.body+8);		     hostsize != 0; hostsize--) {		    if (h+1 < host+sizeof(host))			*h++ = *p;		    p++;		}		*h = 0;		port = GET_32BIT(p);		strcpy(pf.dhost, host);		pf.dport = port;		if (find234(ssh->rportfwds, &pf, NULL) == NULL) {		    sprintf(buf, "Rejected remote port open request for %s:%d",			    host, port);		    logevent(buf);                    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,                                PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);		} else {		    sprintf(buf, "Received remote port open request for %s:%d",			    host, port);		    logevent(buf);		    e = pfd_newconnect(&c->u.pfd.s, host, port, c);		    if (e != NULL) {			char buf[256];			sprintf(buf, "Port open failed: %s", e);			logevent(buf);			sfree(c);			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,				    PKT_INT, GET_32BIT(ssh->pktin.body),				    PKT_END);		    } else {			c->remoteid = GET_32BIT(ssh->pktin.body);			c->localid = alloc_channel_id(ssh);			c->closes = 0;			c->v.v1.throttling = 0;			c->type = CHAN_SOCKDATA;	/* identify channel type */			add234(ssh->channels, c);			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,				    PKT_INT, c->remoteid, PKT_INT,				    c->localid, PKT_END);			logevent("Forwarded port opened successfully");		    }		}	    } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_OPEN_CONFIRMATION) {		unsigned int remoteid = GET_32BIT(ssh->pktin.body);		unsigned int localid = GET_32BIT(ssh->pktin.body+4);		struct ssh_channel *c;		c = find234(ssh->channels, &remoteid, ssh_channelfind);		if (c && c->type == CHAN_SOCKDATA_DORMANT) {		    c->remoteid = localid;		    c->type = CHAN_SOCKDATA;		    c->v.v1.throttling = 0;		    pfd_confirm(c->u.pfd.s);		}		if (c && c->closes) {		    /*		     * We have a pending close on this channel,		     * which we decided on before the server acked		     * the channel open. So now we know the		     * remoteid, we can close it again.		     */		    send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE,				PKT_INT, c->remoteid, PKT_END);		}	    } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_OPEN_FAILURE) {		unsigned int remoteid = GET_32BIT(ssh->pktin.body);		struct ssh_channel *c;		c = find234(ssh->channels, &remoteid, ssh_channelfind);		if (c && c->type == CHAN_SOCKDATA_DORMANT) {		    logevent("Forwarded connection refused by server");		    pfd_close(c->u.pfd.s);		    del234(ssh->channels, c);		    sfree(c);		}	    } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE ||		       ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION) {		/* Remote side closes a channel. */		unsigned i = GET_32BIT(ssh->pktin.body);		struct ssh_channel *c;		c = find234(ssh->channels, &i, ssh_channelfind);		if (c && ((int)c->remoteid) != -1) {		    int closetype;		    closetype =			(ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);		    if ((c->closes == 0) && (c->type == CHAN_X11)) {			logevent("Forwarded X11 connection terminated");			assert(c->u.x11.s != NULL);			x11_close(c->u.x11.s);			c->u.x11.s = NULL;		    }		    if ((c->closes == 0) && (c->type == CHAN_SOCKDATA)) {			logevent("Forwarded port closed");			assert(c->u.pfd.s != NULL);			pfd_close(c->u.pfd.s);			c->u.pfd.s = NULL;		    }		    c->closes |= (closetype << 2);   /* seen this message */		    if (!(c->closes & closetype)) {			send_packet(ssh, ssh->pktin.type, PKT_INT, c->remoteid,				    PKT_END);			c->closes |= closetype;      /* sent it too */		    }		    if (c->closes == 15) {			del234(ssh->channels, c);			sfree(c);		    }		} else {		    bombout((ssh,"Received CHANNEL_CLOSE%s for %s channel %d\n",			     ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE ? "" :			     "_CONFIRMATION", c ? "half-open" : "nonexistent",			     i));		}	    } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_DATA) {		/* Data sent down one of our channels. */		int i = GET_32BIT(ssh->pktin.body);		int len = GET_32BIT(ssh->pktin.body + 4);		unsigned char *p = ssh->pktin.body + 8;		struct ssh_channel *c;		c = find234(ssh->channels, &i, ssh_channelfind);		if (c) {		    int bufsize;		    switch (c->type) {		      case CHAN_X11:			bufsize = x11_send(c->u.x11.s, (char *)p, len);			break;		      case CHAN_SOCKDATA:			bufsize = pfd_send(c->u.pfd.s, (char *)p, len);			break;		      case CHAN_AGENT:			/* 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 = smalloc(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(ssh, SSH1_MSG_CHANNEL_DATA,					    PKT_INT, c->remoteid,					    PKT_INT, replylen,					    PKT_DATA, sentreply, replylen,					    PKT_END);				if (reply)				    sfree(reply);				sfree(c->u.a.message);				c->u.a.lensofar = 0;			    }			}			bufsize = 0;   /* agent channels never back up */			break;		    }		    if (!c->v.v1.throttling && bufsize > SSH1_BUFFER_LIMIT) {			c->v.v1.throttling = 1;			ssh1_throttle(ssh, +1);		    }		}	    } else if (ssh->pktin.type == SSH1_SMSG_SUCCESS) {		/* may be from EXEC_SHELL on some servers */	    } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {		/* may be from EXEC_SHELL on some servers		 * if no pty is available or in other odd cases. Ignore */	    } else if (ssh->pktin.type == SSH1_SMSG_EXIT_STATUS) {		char buf[100];		ssh->exitcode = GET_32BIT(ssh->pktin.body);		sprintf(buf, "Server sent command exit status %d",			ssh->exitcode);		logevent(buf);		send_packet(ssh, SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);                /*                 * In case `helpful' firewalls or proxies tack                 * extra human-readable text on the end of the                 * session which we might mistake for another                 * encrypted packet, we close the session once                 * we've sent EXIT_CONFIRMATION.                 */                ssh->state = SSH_STATE_CLOSED;                crReturnV;	    } else {		bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));		crReturnV;	    }	} else {	    while (inlen > 0) {		int len = min(inlen, 512);		send_packet(ssh, SSH1_CMSG_STDIN_DATA,			    PKT_INT, len, PKT_DATA, in, len, PKT_END);		in += len;		inlen -= len;	    }	}    }    crFinishV;}