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

📄 channels.c

📁 C++编写
💻 C
📖 第 1 页 / 共 5 页
字号:
		case SSH_CHANNEL_LARVAL:		case SSH_CHANNEL_AUTH_SOCKET:		case SSH_CHANNEL_OPEN:		case SSH_CHANNEL_X11_OPEN:			return i;		case SSH_CHANNEL_INPUT_DRAINING:		case SSH_CHANNEL_OUTPUT_DRAINING:			if (!compat13)				fatal("cannot happen: OUT_DRAIN");			return i;		default:			fatal("channel_find_open: bad channel type %d", c->type);			/* NOTREACHED */		}	}	return -1;}/* * Returns a message describing the currently open forwarded connections, * suitable for sending to the client.  The message contains crlf pairs for * newlines. */char *channel_open_message(void){	Buffer buffer;	Channel *c;	char buf[1024], *cp;	int i;	buffer_init(&buffer);	snprintf(buf, sizeof buf, "The following connections are open:\r\n");	buffer_append(&buffer, buf, strlen(buf));	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c == NULL)			continue;		switch (c->type) {		case SSH_CHANNEL_X11_LISTENER:		case SSH_CHANNEL_PORT_LISTENER:		case SSH_CHANNEL_RPORT_LISTENER:		case SSH_CHANNEL_CLOSED:		case SSH_CHANNEL_AUTH_SOCKET:		case SSH_CHANNEL_ZOMBIE:			continue;		case SSH_CHANNEL_LARVAL:		case SSH_CHANNEL_OPENING:		case SSH_CHANNEL_CONNECTING:		case SSH_CHANNEL_DYNAMIC:		case SSH_CHANNEL_OPEN:		case SSH_CHANNEL_X11_OPEN:		case SSH_CHANNEL_INPUT_DRAINING:		case SSH_CHANNEL_OUTPUT_DRAINING:			snprintf(buf, sizeof buf, "  #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n",			    c->self, c->remote_name,			    c->type, c->remote_id,			    c->istate, buffer_len(&c->input),			    c->ostate, buffer_len(&c->output),			    c->rfd, c->wfd);			buffer_append(&buffer, buf, strlen(buf));			continue;		default:			fatal("channel_open_message: bad channel type %d", c->type);			/* NOTREACHED */		}	}	buffer_append(&buffer, "\0", 1);	cp = xstrdup(buffer_ptr(&buffer));	buffer_free(&buffer);	return cp;}voidchannel_send_open(int id){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_send_open: %d: bad id", id);		return;	}	debug2("channel %d: send open", id);	packet_start(SSH2_MSG_CHANNEL_OPEN);	packet_put_cstring(c->ctype);	packet_put_int(c->self);	packet_put_int(c->local_window);	packet_put_int(c->local_maxpacket);	packet_send();}voidchannel_request_start(int id, char *service, int wantconfirm){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_request_start: %d: unknown channel id", id);		return;	}	debug("channel %d: request %s", id, service) ;	packet_start(SSH2_MSG_CHANNEL_REQUEST);	packet_put_int(c->remote_id);	packet_put_cstring(service);	packet_put_char(wantconfirm);}voidchannel_register_confirm(int id, channel_callback_fn *fn){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_register_comfirm: %d: bad id", id);		return;	}	c->confirm = fn;}voidchannel_register_cleanup(int id, channel_callback_fn *fn){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_register_cleanup: %d: bad id", id);		return;	}	c->detach_user = fn;}voidchannel_cancel_cleanup(int id){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_cancel_cleanup: %d: bad id", id);		return;	}	c->detach_user = NULL;}voidchannel_register_filter(int id, channel_filter_fn *fn){	Channel *c = channel_lookup(id);	if (c == NULL) {		log("channel_register_filter: %d: bad id", id);		return;	}	c->input_filter = fn;}voidchannel_set_fds(int id, int rfd, int wfd, int efd,    int extusage, int nonblock, u_int window_max){	Channel *c = channel_lookup(id);	if (c == NULL || c->type != SSH_CHANNEL_LARVAL)		fatal("channel_activate for non-larval channel %d.", id);	channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);	c->type = SSH_CHANNEL_OPEN;	c->local_window = c->local_window_max = window_max;	packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);	packet_put_int(c->remote_id);	packet_put_int(c->local_window);	packet_send();}/* * 'channel_pre*' are called just before select() to add any bits relevant to * channels in the select bitmasks. *//* * 'channel_post*': perform any appropriate operations for channels which * have events pending. */typedef void chan_fn(Channel *c, fd_set * readset, fd_set * writeset);chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];static voidchannel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset){	FD_SET(c->sock, readset);}static voidchannel_pre_connecting(Channel *c, fd_set * readset, fd_set * writeset){	debug3("channel %d: waiting for connection", c->self);	FD_SET(c->sock, writeset);}static voidchannel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset){	if (buffer_len(&c->input) < packet_get_maxsize())		FD_SET(c->sock, readset);	if (buffer_len(&c->output) > 0)		FD_SET(c->sock, writeset);}static voidchannel_pre_open(Channel *c, fd_set * readset, fd_set * writeset){	u_int limit = compat20 ? c->remote_window : packet_get_maxsize();	if (c->istate == CHAN_INPUT_OPEN &&	    limit > 0 &&	    buffer_len(&c->input) < limit)		FD_SET(c->rfd, readset);	if (c->ostate == CHAN_OUTPUT_OPEN ||	    c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {		if (buffer_len(&c->output) > 0) {			FD_SET(c->wfd, writeset);		} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {			if (CHANNEL_EFD_OUTPUT_ACTIVE(c))			       debug2("channel %d: obuf_empty delayed efd %d/(%d)",				   c->self, c->efd, buffer_len(&c->extended));			else				chan_obuf_empty(c);		}	}	/** XXX check close conditions, too */	if (compat20 && c->efd != -1) {		if (c->extended_usage == CHAN_EXTENDED_WRITE &&		    buffer_len(&c->extended) > 0)			FD_SET(c->efd, writeset);		else if (!(c->flags & CHAN_EOF_SENT) &&		    c->extended_usage == CHAN_EXTENDED_READ &&		    buffer_len(&c->extended) < c->remote_window)			FD_SET(c->efd, readset);	}}static voidchannel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset){	if (buffer_len(&c->input) == 0) {		packet_start(SSH_MSG_CHANNEL_CLOSE);		packet_put_int(c->remote_id);		packet_send();		c->type = SSH_CHANNEL_CLOSED;		debug("channel %d: closing after input drain.", c->self);	}}static voidchannel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset){	if (buffer_len(&c->output) == 0)		chan_mark_dead(c);	else		FD_SET(c->sock, writeset);}/* * This is a special state for X11 authentication spoofing.  An opened X11 * connection (when authentication spoofing is being done) remains in this * state until the first packet has been completely read.  The authentication * data in that packet is then substituted by the real data if it matches the * fake data, and the channel is put into normal mode. * XXX All this happens at the client side. * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok */static intx11_open_helper(Buffer *b){	u_char *ucp;	u_int proto_len, data_len;	/* Check if the fixed size part of the packet is in buffer. */	if (buffer_len(b) < 12)		return 0;	/* Parse the lengths of variable-length fields. */	ucp = buffer_ptr(b);	if (ucp[0] == 0x42) {	/* Byte order MSB first. */		proto_len = 256 * ucp[6] + ucp[7];		data_len = 256 * ucp[8] + ucp[9];	} else if (ucp[0] == 0x6c) {	/* Byte order LSB first. */		proto_len = ucp[6] + 256 * ucp[7];		data_len = ucp[8] + 256 * ucp[9];	} else {		debug("Initial X11 packet contains bad byte order byte: 0x%x",		    ucp[0]);		return -1;	}	/* Check if the whole packet is in buffer. */	if (buffer_len(b) <	    12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))		return 0;	/* Check if authentication protocol matches. */	if (proto_len != strlen(x11_saved_proto) ||	    memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {		debug("X11 connection uses different authentication protocol.");		return -1;	}	/* Check if authentication data matches our fake data. */	if (data_len != x11_fake_data_len ||	    memcmp(ucp + 12 + ((proto_len + 3) & ~3),		x11_fake_data, x11_fake_data_len) != 0) {		debug("X11 auth data does not match fake data.");		return -1;	}	/* Check fake data length */	if (x11_fake_data_len != x11_saved_data_len) {		error("X11 fake_data_len %d != saved_data_len %d",		    x11_fake_data_len, x11_saved_data_len);		return -1;	}	/*	 * Received authentication protocol and data match	 * our fake data. Substitute the fake data with real	 * data.	 */	memcpy(ucp + 12 + ((proto_len + 3) & ~3),	    x11_saved_data, x11_saved_data_len);	return 1;}static voidchannel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset){	int ret = x11_open_helper(&c->output);	if (ret == 1) {		/* Start normal processing for the channel. */		c->type = SSH_CHANNEL_OPEN;		channel_pre_open_13(c, readset, writeset);	} else if (ret == -1) {		/*		 * We have received an X11 connection that has bad		 * authentication information.		 */		log("X11 connection rejected because of wrong authentication.");		buffer_clear(&c->input);		buffer_clear(&c->output);		channel_close_fd(&c->sock);		c->sock = -1;		c->type = SSH_CHANNEL_CLOSED;		packet_start(SSH_MSG_CHANNEL_CLOSE);		packet_put_int(c->remote_id);		packet_send();	}}static voidchannel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset){	int ret = x11_open_helper(&c->output);	/* c->force_drain = 1; */	if (ret == 1) {		c->type = SSH_CHANNEL_OPEN;		channel_pre_open(c, readset, writeset);	} else if (ret == -1) {		log("X11 connection rejected because of wrong authentication.");		debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);		chan_read_failed(c);		buffer_clear(&c->input);		chan_ibuf_empty(c);		buffer_clear(&c->output);		/* for proto v1, the peer will send an IEOF */		if (compat20)			chan_write_failed(c);		else			c->type = SSH_CHANNEL_OPEN;		debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);	}}/* try to decode a socks4 header */static intchannel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset){	char *p, *host;	int len, have, i, found;	char username[256];	struct {		u_int8_t version;		u_int8_t command;		u_int16_t dest_port;		struct in_addr dest_addr;	} s4_req, s4_rsp;	debug2("channel %d: decode socks4", c->self);	have = buffer_len(&c->input);	len = sizeof(s4_req);	if (have < len)		return 0;	p = buffer_ptr(&c->input);	for (found = 0, i = len; i < have; i++) {		if (p[i] == '\0') {			found = 1;			break;		}		if (i > 1024) {			/* the peer is probably sending garbage */			debug("channel %d: decode socks4: too long",			    c->self);			return -1;		}	}	if (!found)		return 0;	buffer_get(&c->input, (char *)&s4_req.version, 1);	buffer_get(&c->input, (char *)&s4_req.command, 1);	buffer_get(&c->input, (char *)&s4_req.dest_port, 2);	buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);	have = buffer_len(&c->input);	p = buffer_ptr(&c->input);	len = strlen(p);	debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);	if (len > have)		fatal("channel %d: decode socks4: len %d > have %d",		    c->self, len, have);	strlcpy(username, p, sizeof(username));	buffer_consume(&c->input, len);	buffer_consume(&c->input, 1);		/* trailing '\0' */	host = inet_ntoa(s4_req.dest_addr);	strlcpy(c->path, host, sizeof(c->path));	c->host_port = ntohs(s4_req.dest_port);	debug("channel %d: dynamic request: socks4 host %s port %u command %u",	    c->self, host, c->host_port, s4_req.command);	if (s4_req.command != 1) {		debug("channel %d: cannot handle: socks4 cn %d",		    c->self, s4_req.command);		return -1;	}	s4_rsp.version = 0;			/* vn: 0 for reply */	s4_rsp.command = 90;			/* cd: req granted */	s4_rsp.dest_port = 0;			/* ignored */	s4_rsp.dest_addr.s_addr = INADDR_ANY;	/* ignored */	buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));	return 1;}/* dynamic port forwarding */static voidchannel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset){	u_char *p;	int have, ret;	have = buffer_len(&c->input);	c->delayed = 0;	debug2("channel %d: pre_dynamic: have %d", c->self, have);	/* buffer_dump(&c->input); */	/* check if the fixed size part of the packet is in buffer. */	if (have < 4) {		/* need more */		FD_SET(c->sock, readset);		return;	}	/* try to guess the protocol */	p = buffer_ptr(&c->input);	switch (p[0]) {	case 0x04:		ret = channel_decode_socks4(c, readset, writeset);		break;	default:		ret = -1;		break;	}	if (ret < 0) {		chan_mark_dead(c);	} else if (ret == 0) {		debug2("channel %d: pre_dynamic: need more", c->self);		/* need more */		FD_SET(c->sock, readset);	} else {		/* switch to the next state */		c->type = SSH_CHANNEL_OPENING;		port_open_helper(c, "direct-tcpip");	}}/* This is our fake X11 server socket. */static voidchannel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset){	Channel *nc;	struct sockaddr addr;	int newsock;	socklen_t addrlen;

⌨️ 快捷键说明

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