⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channels.c

📁 C++编写
💻 C
📖 第 1 页 / 共 5 页
字号:
	char buf[16384], *remote_ipaddr;	int remote_port;	if (FD_ISSET(c->sock, readset)) {		debug("X11 connection requested.");		addrlen = sizeof(addr);		newsock = accept(c->sock, &addr, &addrlen);		if (c->single_connection) {			debug("single_connection: closing X11 listener.");			channel_close_fd(&c->sock);			chan_mark_dead(c);		}		if (newsock < 0) {			error("accept: %.100s", strerror(errno));			return;		}		set_nodelay(newsock);		remote_ipaddr = get_peer_ipaddr(newsock);		remote_port = get_peer_port(newsock);		snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",		    remote_ipaddr, remote_port);		nc = channel_new("accepted x11 socket",		    SSH_CHANNEL_OPENING, newsock, newsock, -1,		    c->local_window_max, c->local_maxpacket,		    0, xstrdup(buf), 1);		if (compat20) {			packet_start(SSH2_MSG_CHANNEL_OPEN);			packet_put_cstring("x11");			packet_put_int(nc->self);			packet_put_int(nc->local_window_max);			packet_put_int(nc->local_maxpacket);			/* originator ipaddr and port */			packet_put_cstring(remote_ipaddr);			if (datafellows & SSH_BUG_X11FWD) {				debug("ssh2 x11 bug compat mode");			} else {				packet_put_int(remote_port);			}			packet_send();		} else {			packet_start(SSH_SMSG_X11_OPEN);			packet_put_int(nc->self);			if (packet_get_protocol_flags() &			    SSH_PROTOFLAG_HOST_IN_FWD_OPEN)				packet_put_cstring(buf);			packet_send();		}		xfree(remote_ipaddr);	}}static voidport_open_helper(Channel *c, char *rtype){	int direct;	char buf[1024];	char *remote_ipaddr = get_peer_ipaddr(c->sock);	u_short remote_port = get_peer_port(c->sock);	direct = (strcmp(rtype, "direct-tcpip") == 0);	snprintf(buf, sizeof buf,	    "%s: listening port %d for %.100s port %d, "	    "connect from %.200s port %d",	    rtype, c->listening_port, c->path, c->host_port,	    remote_ipaddr, remote_port);	xfree(c->remote_name);	c->remote_name = xstrdup(buf);	if (compat20) {		packet_start(SSH2_MSG_CHANNEL_OPEN);		packet_put_cstring(rtype);		packet_put_int(c->self);		packet_put_int(c->local_window_max);		packet_put_int(c->local_maxpacket);		if (direct) {			/* target host, port */			packet_put_cstring(c->path);			packet_put_int(c->host_port);		} else {			/* listen address, port */			packet_put_cstring(c->path);			packet_put_int(c->listening_port);		}		/* originator host and port */		packet_put_cstring(remote_ipaddr);		packet_put_int(remote_port);		packet_send();	} else {		packet_start(SSH_MSG_PORT_OPEN);		packet_put_int(c->self);		packet_put_cstring(c->path);		packet_put_int(c->host_port);		if (packet_get_protocol_flags() &		    SSH_PROTOFLAG_HOST_IN_FWD_OPEN)			packet_put_cstring(c->remote_name);		packet_send();	}	xfree(remote_ipaddr);}/* * This socket is listening for connections to a forwarded TCP/IP port. */static voidchannel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset){	Channel *nc;	struct sockaddr addr;	int newsock, nextstate;	socklen_t addrlen;	char *rtype;	if (FD_ISSET(c->sock, readset)) {		debug("Connection to port %d forwarding "		    "to %.100s port %d requested.",		    c->listening_port, c->path, c->host_port);		if (c->type == SSH_CHANNEL_RPORT_LISTENER) {			nextstate = SSH_CHANNEL_OPENING;			rtype = "forwarded-tcpip";		} else {			if (c->host_port == 0) {				nextstate = SSH_CHANNEL_DYNAMIC;				rtype = "dynamic-tcpip";			} else {				nextstate = SSH_CHANNEL_OPENING;				rtype = "direct-tcpip";			}		}		addrlen = sizeof(addr);		newsock = accept(c->sock, &addr, &addrlen);		if (newsock < 0) {			error("accept: %.100s", strerror(errno));			return;		}		set_nodelay(newsock);		nc = channel_new(rtype,		    nextstate, newsock, newsock, -1,		    c->local_window_max, c->local_maxpacket,		    0, xstrdup(rtype), 1);		nc->listening_port = c->listening_port;		nc->host_port = c->host_port;		strlcpy(nc->path, c->path, sizeof(nc->path));		if (nextstate == SSH_CHANNEL_DYNAMIC) {			/*			 * do not call the channel_post handler until			 * this flag has been reset by a pre-handler.			 * otherwise the FD_ISSET calls might overflow			 */			nc->delayed = 1;		} else {			port_open_helper(nc, rtype);		}	}}/* * This is the authentication agent socket listening for connections from * clients. */static voidchannel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset){	Channel *nc;	char *name;	int newsock;	struct sockaddr addr;	socklen_t addrlen;	if (FD_ISSET(c->sock, readset)) {		addrlen = sizeof(addr);		newsock = accept(c->sock, &addr, &addrlen);		if (newsock < 0) {			error("accept from auth socket: %.100s", strerror(errno));			return;		}		name = xstrdup("accepted auth socket");		nc = channel_new("accepted auth socket",		    SSH_CHANNEL_OPENING, newsock, newsock, -1,		    c->local_window_max, c->local_maxpacket,		    0, name, 1);		if (compat20) {			packet_start(SSH2_MSG_CHANNEL_OPEN);			packet_put_cstring("auth-agent@openssh.com");			packet_put_int(nc->self);			packet_put_int(c->local_window_max);			packet_put_int(c->local_maxpacket);		} else {			packet_start(SSH_SMSG_AGENT_OPEN);			packet_put_int(nc->self);		}		packet_send();	}}static voidchannel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset){	int err = 0;	socklen_t sz = sizeof(err);	if (FD_ISSET(c->sock, writeset)) {		if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {			err = errno;			error("getsockopt SO_ERROR failed");		}		if (err == 0) {			debug("channel %d: connected", c->self);			c->type = SSH_CHANNEL_OPEN;			if (compat20) {				packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);				packet_put_int(c->remote_id);				packet_put_int(c->self);				packet_put_int(c->local_window);				packet_put_int(c->local_maxpacket);			} else {				packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);				packet_put_int(c->remote_id);				packet_put_int(c->self);			}		} else {			debug("channel %d: not connected: %s",			    c->self, strerror(err));			if (compat20) {				packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);				packet_put_int(c->remote_id);				packet_put_int(SSH2_OPEN_CONNECT_FAILED);				if (!(datafellows & SSH_BUG_OPENFAILURE)) {					packet_put_cstring(strerror(err));					packet_put_cstring("");				}			} else {				packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);				packet_put_int(c->remote_id);			}			chan_mark_dead(c);		}		packet_send();	}}static intchannel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset){	char buf[16*1024];	int len;	if (c->rfd != -1 &&	    FD_ISSET(c->rfd, readset)) {		len = read(c->rfd, buf, sizeof(buf));		if (len < 0 && (errno == EINTR || errno == EAGAIN))			return 1;		if (len <= 0) {			debug("channel %d: read<=0 rfd %d len %d",			    c->self, c->rfd, len);			if (c->type != SSH_CHANNEL_OPEN) {				debug("channel %d: not open", c->self);				chan_mark_dead(c);				return -1;			} else if (compat13) {				buffer_clear(&c->output);				c->type = SSH_CHANNEL_INPUT_DRAINING;				debug("channel %d: input draining.", c->self);			} else {				chan_read_failed(c);			}			return -1;		}		if (c->input_filter != NULL) {			if (c->input_filter(c, buf, len) == -1) {				debug("channel %d: filter stops", c->self);				chan_read_failed(c);			}		} else {			buffer_append(&c->input, buf, len);		}	}	return 1;}static intchannel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset){	struct termios tio;	u_char *data;	u_int dlen;	int len;	/* Send buffered output data to the socket. */	if (c->wfd != -1 &&	    FD_ISSET(c->wfd, writeset) &&	    buffer_len(&c->output) > 0) {		data = buffer_ptr(&c->output);		dlen = buffer_len(&c->output);		len = write(c->wfd, data, dlen);		if (len < 0 && (errno == EINTR || errno == EAGAIN))			return 1;		if (len <= 0) {			if (c->type != SSH_CHANNEL_OPEN) {				debug("channel %d: not open", c->self);				chan_mark_dead(c);				return -1;			} else if (compat13) {				buffer_clear(&c->output);				debug("channel %d: input draining.", c->self);				c->type = SSH_CHANNEL_INPUT_DRAINING;			} else {				chan_write_failed(c);			}			return -1;		}		if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') {			if (tcgetattr(c->wfd, &tio) == 0 &&			    !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {				/*				 * Simulate echo to reduce the impact of				 * traffic analysis. We need to match the				 * size of a SSH2_MSG_CHANNEL_DATA message				 * (4 byte channel id + data)				 */				packet_send_ignore(4 + len);				packet_send();			}		}		buffer_consume(&c->output, len);		if (compat20 && len > 0) {			c->local_consumed += len;		}	}	return 1;}static intchannel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset){	char buf[16*1024];	int len;/** XXX handle drain efd, too */	if (c->efd != -1) {		if (c->extended_usage == CHAN_EXTENDED_WRITE &&		    FD_ISSET(c->efd, writeset) &&		    buffer_len(&c->extended) > 0) {			len = write(c->efd, buffer_ptr(&c->extended),			    buffer_len(&c->extended));			debug2("channel %d: written %d to efd %d",			    c->self, len, c->efd);			if (len < 0 && (errno == EINTR || errno == EAGAIN))				return 1;			if (len <= 0) {				debug2("channel %d: closing write-efd %d",				    c->self, c->efd);				channel_close_fd(&c->efd);			} else {				buffer_consume(&c->extended, len);				c->local_consumed += len;			}		} else if (c->extended_usage == CHAN_EXTENDED_READ &&		    FD_ISSET(c->efd, readset)) {			len = read(c->efd, buf, sizeof(buf));			debug2("channel %d: read %d from efd %d",			    c->self, len, c->efd);			if (len < 0 && (errno == EINTR || errno == EAGAIN))				return 1;			if (len <= 0) {				debug2("channel %d: closing read-efd %d",				    c->self, c->efd);				channel_close_fd(&c->efd);			} else {				buffer_append(&c->extended, buf, len);			}		}	}	return 1;}static intchannel_check_window(Channel *c){	if (c->type == SSH_CHANNEL_OPEN &&	    !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&	    c->local_window < c->local_window_max/2 &&	    c->local_consumed > 0) {		packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);		packet_put_int(c->remote_id);		packet_put_int(c->local_consumed);		packet_send();		debug2("channel %d: window %d sent adjust %d",		    c->self, c->local_window,		    c->local_consumed);		c->local_window += c->local_consumed;		c->local_consumed = 0;	}	return 1;}static voidchannel_post_open(Channel *c, fd_set * readset, fd_set * writeset){	if (c->delayed)		return;	channel_handle_rfd(c, readset, writeset);	channel_handle_wfd(c, readset, writeset);	if (!compat20)		return;	channel_handle_efd(c, readset, writeset);	channel_check_window(c);}static voidchannel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset){	int len;	/* Send buffered output data to the socket. */	if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {		len = write(c->sock, buffer_ptr(&c->output),			    buffer_len(&c->output));		if (len <= 0)			buffer_clear(&c->output);		else			buffer_consume(&c->output, len);	}}static voidchannel_handler_init_20(void){	channel_pre[SSH_CHANNEL_OPEN] =			&channel_pre_open;	channel_pre[SSH_CHANNEL_X11_OPEN] =		&channel_pre_x11_open;	channel_pre[SSH_CHANNEL_PORT_LISTENER] =	&channel_pre_listener;	channel_pre[SSH_CHANNEL_RPORT_LISTENER] =	&channel_pre_listener;	channel_pre[SSH_CHANNEL_X11_LISTENER] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_AUTH_SOCKET] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_CONNECTING] =		&channel_pre_connecting;	channel_pre[SSH_CHANNEL_DYNAMIC] =		&channel_pre_dynamic;	channel_post[SSH_CHANNEL_OPEN] =		&channel_post_open;	channel_post[SSH_CHANNEL_PORT_LISTENER] =	&channel_post_port_listener;	channel_post[SSH_CHANNEL_RPORT_LISTENER] =	&channel_post_port_listener;	channel_post[SSH_CHANNEL_X11_LISTENER] =	&channel_post_x11_listener;	channel_post[SSH_CHANNEL_AUTH_SOCKET] =		&channel_post_auth_listener;	channel_post[SSH_CHANNEL_CONNECTING] =		&channel_post_connecting;	channel_post[SSH_CHANNEL_DYNAMIC] =		&channel_post_open;}static voidchannel_handler_init_13(void){	channel_pre[SSH_CHANNEL_OPEN] =			&channel_pre_open_13;	channel_pre[SSH_CHANNEL_X11_OPEN] =		&channel_pre_x11_open_13;	channel_pre[SSH_CHANNEL_X11_LISTENER] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_PORT_LISTENER] =	&channel_pre_listener;	channel_pre[SSH_CHANNEL_AUTH_SOCKET] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_INPUT_DRAINING] =	&channel_pre_input_draining;	channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] =	&channel_pre_output_draining;	channel_pre[SSH_CHANNEL_CONNECTING] =		&channel_pre_connecting;	channel_pre[SSH_CHANNEL_DYNAMIC] =		&channel_pre_dynamic;	channel_post[SSH_CHANNEL_OPEN] =		&channel_post_open;	channel_post[SSH_CHANNEL_X11_LISTENER] =	&channel_post_x11_listener;	channel_post[SSH_CHANNEL_PORT_LISTENER] =	&channel_post_port_listener;	channel_post[SSH_CHANNEL_AUTH_SOCKET] =		&channel_post_auth_listener;	channel_post[SSH_CHANNEL_OUTPUT_DRAINING] =	&channel_post_output_drain_13;	channel_post[SSH_CHANNEL_CONNECTING] =		&channel_post_connecting;	channel_post[SSH_CHANNEL_DYNAMIC] =		&channel_post_open;}static voidchannel_handler_init_15(void){	channel_pre[SSH_CHANNEL_OPEN] =			&channel_pre_open;	channel_pre[SSH_CHANNEL_X11_OPEN] =		&channel_pre_x11_open;	channel_pre[SSH_CHANNEL_X11_LISTENER] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_PORT_LISTENER] =	&channel_pre_listener;	channel_pre[SSH_CHANNEL_AUTH_SOCKET] =		&channel_pre_listener;	channel_pre[SSH_CHANNEL_CONNECTING] =		&channel_pre_connecting;	channel_pre[SSH_CHANNEL_DYNAMIC] =		&channel_pre_dynamic;	channel_post[SSH_CHANNEL_X11_LISTENER] =	&channel_post_x11_listener;	channel_post[SSH_CHANNEL_PORT_LISTENER] =	&channel_post_port_listener;	channel_post[SSH_CHANNEL_AUTH_SOCKET] =		&channel_post_auth_listener;	channel_post[SSH_CHANNEL_OPEN] =		&channel_post_open;	channel_post[SSH_CHANNEL_CONNECTING] =		&channel_post_connecting;	channel_post[SSH_CHANNEL_DYNAMIC] =		&channel_post_open;}static voidchannel_handler_init(void){	int i;	for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -