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

📄 channels.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 5 页
字号:
	}}voidchannel_input_close(int type, u_int32_t seq, void *ctxt){	int id;	Channel *c;	id = packet_get_int();	packet_check_eom();	c = channel_lookup(id);	if (c == NULL)		packet_disconnect("Received close for nonexistent channel %d.", id);	/*	 * Send a confirmation that we have closed the channel and no more	 * data is coming for it.	 */	packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);	packet_put_int(c->remote_id);	packet_send();	/*	 * If the channel is in closed state, we have sent a close request,	 * and the other side will eventually respond with a confirmation.	 * Thus, we cannot free the channel here, because then there would be	 * no-one to receive the confirmation.  The channel gets freed when	 * the confirmation arrives.	 */	if (c->type != SSH_CHANNEL_CLOSED) {		/*		 * Not a closed channel - mark it as draining, which will		 * cause it to be freed later.		 */		buffer_clear(&c->input);		c->type = SSH_CHANNEL_OUTPUT_DRAINING;	}}/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */voidchannel_input_oclose(int type, u_int32_t seq, void *ctxt){	int id = packet_get_int();	Channel *c = channel_lookup(id);	packet_check_eom();	if (c == NULL)		packet_disconnect("Received oclose for nonexistent channel %d.", id);	chan_rcvd_oclose(c);}voidchannel_input_close_confirmation(int type, u_int32_t seq, void *ctxt){	int id = packet_get_int();	Channel *c = channel_lookup(id);	packet_check_eom();	if (c == NULL)		packet_disconnect("Received close confirmation for "		    "out-of-range channel %d.", id);	if (c->type != SSH_CHANNEL_CLOSED)		packet_disconnect("Received close confirmation for "		    "non-closed channel %d (type %d).", id, c->type);	channel_free(c);}voidchannel_input_open_confirmation(int type, u_int32_t seq, void *ctxt){	int id, remote_id;	Channel *c;	id = packet_get_int();	c = channel_lookup(id);	if (c==NULL || c->type != SSH_CHANNEL_OPENING)		packet_disconnect("Received open confirmation for "		    "non-opening channel %d.", id);	remote_id = packet_get_int();	/* Record the remote channel number and mark that the channel is now open. */	c->remote_id = remote_id;	c->type = SSH_CHANNEL_OPEN;	if (compat20) {		c->remote_window = packet_get_int();		c->remote_maxpacket = packet_get_int();		if (c->confirm) {			debug2("callback start");			c->confirm(c->self, c->confirm_ctx);			debug2("callback done");		}		debug2("channel %d: open confirm rwindow %u rmax %u", c->self,		    c->remote_window, c->remote_maxpacket);	}	packet_check_eom();}static char *reason2txt(int reason){	switch (reason) {	case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:		return "administratively prohibited";	case SSH2_OPEN_CONNECT_FAILED:		return "connect failed";	case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE:		return "unknown channel type";	case SSH2_OPEN_RESOURCE_SHORTAGE:		return "resource shortage";	}	return "unknown reason";}voidchannel_input_open_failure(int type, u_int32_t seq, void *ctxt){	int id, reason;	char *msg = NULL, *lang = NULL;	Channel *c;	id = packet_get_int();	c = channel_lookup(id);	if (c==NULL || c->type != SSH_CHANNEL_OPENING)		packet_disconnect("Received open failure for "		    "non-opening channel %d.", id);	if (compat20) {		reason = packet_get_int();		if (!(datafellows & SSH_BUG_OPENFAILURE)) {			msg  = packet_get_string(NULL);			lang = packet_get_string(NULL);		}		logit("channel %d: open failed: %s%s%s", id,		    reason2txt(reason), msg ? ": ": "", msg ? msg : "");		if (msg != NULL)			xfree(msg);		if (lang != NULL)			xfree(lang);	}	packet_check_eom();	/* Free the channel.  This will also close the socket. */	channel_free(c);}voidchannel_input_window_adjust(int type, u_int32_t seq, void *ctxt){	Channel *c;	int id;	u_int adjust;	if (!compat20)		return;	/* Get the channel number and verify it. */	id = packet_get_int();	c = channel_lookup(id);	if (c == NULL || c->type != SSH_CHANNEL_OPEN) {		logit("Received window adjust for "		    "non-open channel %d.", id);		return;	}	adjust = packet_get_int();	packet_check_eom();	debug2("channel %d: rcvd adjust %u", id, adjust);	c->remote_window += adjust;}voidchannel_input_port_open(int type, u_int32_t seq, void *ctxt){	Channel *c = NULL;	u_short host_port;	char *host, *originator_string;	int remote_id, sock = -1;	remote_id = packet_get_int();	host = packet_get_string(NULL);	host_port = packet_get_int();	if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {		originator_string = packet_get_string(NULL);	} else {		originator_string = xstrdup("unknown (remote did not supply name)");	}	packet_check_eom();	sock = channel_connect_to(host, host_port);	if (sock != -1) {		c = channel_new("connected socket",		    SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,		    originator_string, 1);		c->remote_id = remote_id;	}	xfree(originator_string);	if (c == NULL) {		packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);		packet_put_int(remote_id);		packet_send();	}	xfree(host);}/* -- tcp forwarding */voidchannel_set_af(int af){	IPv4or6 = af;}static intchannel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port,    const char *host_to_connect, u_short port_to_connect, int gateway_ports){	Channel *c;	int sock, r, success = 0, on = 1, wildcard = 0, is_client;	struct addrinfo hints, *ai, *aitop;	const char *host, *addr;	char ntop[NI_MAXHOST], strport[NI_MAXSERV];	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?	    listen_addr : host_to_connect;	is_client = (type == SSH_CHANNEL_PORT_LISTENER);	if (host == NULL) {		error("No forward host name.");		return success;	}	if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) {		error("Forward host name too long.");		return success;	}	/*	 * Determine whether or not a port forward listens to loopback,	 * specified address or wildcard. On the client, a specified bind 	 * address will always override gateway_ports. On the server, a 	 * gateway_ports of 1 (``yes'') will override the client's 	 * specification and force a wildcard bind, whereas a value of 2 	 * (``clientspecified'') will bind to whatever address the client 	 * asked for.	 *	 * Special-case listen_addrs are:	 *	 * "0.0.0.0"               -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR	 * "" (empty string), "*"  -> wildcard v4/v6	 * "localhost"             -> loopback v4/v6	 */	addr = NULL;	if (listen_addr == NULL) {		/* No address specified: default to gateway_ports setting */		if (gateway_ports)			wildcard = 1;	} else if (gateway_ports || is_client) {		if (((datafellows & SSH_OLD_FORWARD_ADDR) &&		    strcmp(listen_addr, "0.0.0.0") == 0) ||		    *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||		    (!is_client && gateway_ports == 1))			wildcard = 1;		else if (strcmp(listen_addr, "localhost") != 0)			addr = listen_addr;	}	debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",	    type, wildcard, (addr == NULL) ? "NULL" : addr);	/*	 * getaddrinfo returns a loopback address if the hostname is	 * set to NULL and hints.ai_flags is not AI_PASSIVE	 */	memset(&hints, 0, sizeof(hints));	hints.ai_family = IPv4or6;	hints.ai_flags = wildcard ? AI_PASSIVE : 0;	hints.ai_socktype = SOCK_STREAM;	snprintf(strport, sizeof strport, "%d", listen_port);	if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {		if (addr == NULL) {			/* This really shouldn't happen */			packet_disconnect("getaddrinfo: fatal error: %s",			    gai_strerror(r));		} else {			verbose("channel_setup_fwd_listener: "			    "getaddrinfo(%.64s): %s", addr, gai_strerror(r));			packet_send_debug("channel_setup_fwd_listener: "			    "getaddrinfo(%.64s): %s", addr, gai_strerror(r));		}		aitop = NULL;	}	for (ai = aitop; ai; ai = ai->ai_next) {		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)			continue;		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),		    strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {			error("channel_setup_fwd_listener: getnameinfo failed");			continue;		}		/* Create a port to listen for the host. */		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);		if (sock < 0) {			/* this is no error since kernel may not support ipv6 */			verbose("socket: %.100s", strerror(errno));			continue;		}		/*		 * Set socket options.		 * Allow local port reuse in TIME_WAIT.		 */		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,		    sizeof(on)) == -1)			error("setsockopt SO_REUSEADDR: %s", strerror(errno));		debug("Local forwarding listening on %s port %s.", ntop, strport);		/* Bind the socket to the address. */		if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {			/* address can be in use ipv6 address is already bound */			if (!ai->ai_next)				error("bind: %.100s", strerror(errno));			else				verbose("bind: %.100s", strerror(errno));			close(sock);			continue;		}		/* Start listening for connections on the socket. */		if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {			error("listen: %.100s", strerror(errno));			close(sock);			continue;		}		/* Allocate a channel number for the socket. */		c = channel_new("port listener", type, sock, sock, -1,		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,		    0, "port listener", 1);		strlcpy(c->path, host, sizeof(c->path));		c->host_port = port_to_connect;		c->listening_port = listen_port;		success = 1;	}	if (success == 0)		error("channel_setup_fwd_listener: cannot listen to port: %d",		    listen_port);	freeaddrinfo(aitop);	return success;}intchannel_cancel_rport_listener(const char *host, u_short port){	u_int i;	int found = 0;	for(i = 0; i < channels_alloc; i++) {		Channel *c = channels[i];		if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&		    strncmp(c->path, host, sizeof(c->path)) == 0 &&		    c->listening_port == port) {			debug2("%s: close channel %d", __func__, i);			channel_free(c);			found = 1;		}	}	return (found);}/* protocol local port fwd, used by ssh (and sshd in v1) */intchannel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,    const char *host_to_connect, u_short port_to_connect, int gateway_ports){	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,	    listen_host, listen_port, host_to_connect, port_to_connect,	    gateway_ports);}/* protocol v2 remote port fwd, used by sshd */intchannel_setup_remote_fwd_listener(const char *listen_address,    u_short listen_port, int gateway_ports){	return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,	    listen_address, listen_port, NULL, 0, gateway_ports);}/* * Initiate forwarding of connections to port "port" on remote host through * the secure channel to host:port from local side. */voidchannel_request_remote_forwarding(const char *listen_host, u_short listen_port,    const char *host_to_connect, u_short port_to_connect){	int type, success = 0;	/* Record locally that connection to this host/port is permitted. */	if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)		fatal("channel_request_remote_forwarding: too many forwards");	/* Send the forward request to the remote side. */	if (compat20) {		const char *address_to_bind;		if (listen_host == NULL)			address_to_bind = "localhost";		else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0)			address_to_bind = "";		else			address_to_bind = listen_host;		packet_start(SSH2_MSG_GLOBAL_REQUEST);		packet_put_cstring("tcpip-forward");		packet_put_char(1);			/* boolean: want reply */		packet_put_cstring(address_to_bind);		packet_put_int(listen_port);		packet_send();		packet_write_wait();		/* Assume that server accepts the request */		success = 1;	} else {		packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);		packet_put_int(listen_port);		packet_put_cstring(host_to_connect);		packet_put_int(port_to_connect);		packet_send();		packet_write_wait();		/* Wait for response from the remote side. */		type = packet_read();		switch (type) {		case SSH_SMSG_SUCCESS:			success = 1;			break;		case SSH_SMSG_FAILURE:			logit("Warning: Server denied remote port forwarding.");			break;		default:			/* Unknown packet */			packet_disconnect("Protocol error for port forward request:"			    "received packet type %d.", type);		}	}	if (success) {		permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);		permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;		permitted_opens[num_permitted_opens].listen_port = listen_port;		num_permitted_opens++;	}}/* * Request cancellation of remote forwarding of connection host:port from * local side. */voidchannel_request_rforward_cancel(const char *host, u_short port){	int i;	if (!compat20)		return;	for (i = 0; i < num_permitted_opens; i++) {		if (permitted_opens[i].host_to_connect != NULL &&		    permitted_opens[i].listen_port == port)			break;	}	if (i >= num_permitted_opens) {		debug("%s: requested forward not found", __func__);		return;	}	packet_start(SSH2_MSG_GLOBAL_REQUEST);	packet_put_cstring("cancel-tcpip-forward");	packet_put_char(0);	packet_put_cstring(host == NULL ? "" : host);	packet_put_int(port);	packet_send();	permitted_opens[i].listen_port = 0;	permitted_opens[i].por

⌨️ 快捷键说明

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