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

📄 channels.c

📁 C++编写
💻 C
📖 第 1 页 / 共 5 页
字号:
		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;	}	if (c == NULL) {		xfree(originator_string);		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 success, sock, on = 1;	struct addrinfo hints, *ai, *aitop;	const char *host;	char ntop[NI_MAXHOST], strport[NI_MAXSERV];	success = 0;	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?	    listen_addr : host_to_connect;	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;	}	/*	 * 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 = gateway_ports ? AI_PASSIVE : 0;	hints.ai_socktype = SOCK_STREAM;	snprintf(strport, sizeof strport, "%d", listen_port);	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)		packet_disconnect("getaddrinfo: fatal error");	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, SOCK_STREAM, 0);		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 */			verbose("bind: %.100s", strerror(errno));			close(sock);			continue;		}		/* Start listening for connections on the socket. */		if (listen(sock, 5) < 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, xstrdup("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;}/* protocol local port fwd, used by ssh (and sshd in v1) */intchannel_setup_local_fwd_listener(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,	    NULL, 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(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 = "0.0.0.0";		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:			log("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++;	}}/* * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates * listening for the port, and sends back a success reply (or disconnect * message if there was an error).  This never returns if there was an error. */voidchannel_input_port_forward_request(int is_root, int gateway_ports){	u_short port, host_port;	char *hostname;	/* Get arguments from the packet. */	port = packet_get_int();	hostname = packet_get_string(NULL);	host_port = packet_get_int();	/*	 * Check that an unprivileged user is not trying to forward a	 * privileged port.	 */	if (port < IPPORT_RESERVED && !is_root)		packet_disconnect("Requested forwarding of port %d but user is not root.",				  port);	/* Initiate forwarding */	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);	/* Free the argument string. */	xfree(hostname);}/* * Permits opening to any host/port if permitted_opens[] is empty.  This is * usually called by the server, because the user could connect to any port * anyway, and the server has no way to know but to trust the client anyway. */voidchannel_permit_all_opens(void){	if (num_permitted_opens == 0)		all_opens_permitted = 1;}voidchannel_add_permitted_opens(char *host, int port){	if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)		fatal("channel_request_remote_forwarding: too many forwards");	debug("allow port forwarding to host %s port %d", host, port);	permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);	permitted_opens[num_permitted_opens].port_to_connect = port;	num_permitted_opens++;	all_opens_permitted = 0;}voidchannel_clear_permitted_opens(void){	int i;	for (i = 0; i < num_permitted_opens; i++)		xfree(permitted_opens[i].host_to_connect);	num_permitted_opens = 0;}/* return socket to remote host, port */static intconnect_to(const char *host, u_short port){	struct addrinfo hints, *ai, *aitop;	char ntop[NI_MAXHOST], strport[NI_MAXSERV];	int gaierr;	int sock = -1;	memset(&hints, 0, sizeof(hints));	hints.ai_family = IPv4or6;	hints.ai_socktype = SOCK_STREAM;	snprintf(strport, sizeof strport, "%d", port);	if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {		error("connect_to %.100s: unknown host (%s)", host,		    gai_strerror(gaierr));		return -1;	}	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("connect_to: getnameinfo failed");			continue;		}		sock = socket(ai->ai_family, SOCK_STREAM, 0);		if (sock < 0) {			if (ai->ai_next == NULL)				error("socket: %.100s", strerror(errno));			else				verbose("socket: %.100s", strerror(errno));			continue;		}		if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)			fatal("connect_to: F_SETFL: %s", strerror(errno));		if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&		    errno != EINPROGRESS) {			error("connect_to %.100s port %s: %.100s", ntop, strport,			    strerror(errno));			close(sock);			continue;	/* fail -- try next */		}		break; /* success */	}	freeaddrinfo(aitop);	if (!ai) {		error("connect_to %.100s port %d: failed.", host, port);		return -1;	}	/* success */	set_nodelay(sock);	return sock;}intchannel_connect_by_listen_address(u_short listen_port){	int i;	for (i = 0; i < num_permitted_opens; i++)		if (permitted_opens[i].listen_port == listen_port)			return connect_to(			    permitted_opens[i].host_to_connect,			    permitted_opens[i].port_to_connect);	error("WARNING: Server requests forwarding for unknown listen_port %d",	    listen_port);	return -1;}/* Check if connecting to that port is permitted and connect. */intchannel_connect_to(const char *host, u_short port){	int i, permit;	permit = all_opens_permitted;	if (!permit) {		for (i = 0; i < num_permitted_opens; i++)			if (permitted_opens[i].port_to_connect == port &&			    strcmp(permitted_opens[i].host_to_connect, host) == 0)				permit = 1;	}	if (!permit) {		log("Received request to connect to host %.100s port %d, "		    "but the request was denied.", host, port);		return -1;	}	return connect_to(host, port);}/* -- X11 forwarding *//* * Creates an internet domain socket for listening for X11 connections. * Returns 0 and a suitable display number for the DISPLAY variable * stored in display_numberp , or -1 if an error occurs. */intx11_create_display_inet(int x11_display_offset, int x11_use_localhost,    int single_connection, u_int *display_numberp){	Channel *nc = NULL;	int display_number, sock;	u_short port;	struct addrinfo hints, *ai, *aitop;	char strport[NI_MAXSERV];	int gaierr, n, num_socks = 0, socks[NUM_SOCKS];	for (display_number = x11_display_offset;	    display_number < MAX_DISPLAYS;	    display_number++) {		port = 6000 + display_number;		memset(&hints, 0, sizeof(hints));		hints.ai_family = IPv4or6;		hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;		hints.ai_socktype = SOCK_STREAM;		snprintf(strport, sizeof strport, "%d", port);		if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {			error("getaddrinfo: %.100s", gai_strerror(gaierr));			return -1;		}		for (ai = aitop; ai; ai = ai->ai_next) {			if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)				continue;			sock = socket(ai->ai_family, SOCK_STREAM, 0);			if (sock < 0) {				error("socket: %.100s", strerror(errno));				return -1;			}			if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {				debug("bind port %d: %.100s", port, strerror(errno));				close(sock);				if (ai->ai_next)					continue;				for (n = 0; n < num_socks; n++) {					close(socks[n]);				}				num_socks = 0;				break;			}			socks[num_socks++] = sock;			if (num_socks == NUM_SOCKS)				break;		}		freeaddrinfo(aitop);		if (num_socks > 0)			break;	}	if (display_number >= MAX_DISPLAYS) {		error("Failed to allocate internet-domain X11 display socket.");		return -1;	}	/* Start listening for connections on the socket. */	for (n = 0; n < num_socks; n++) {		sock = socks[n];		if (listen(sock, 5) < 0) {			error("listen: %.100s", strerror(errno));			close(sock);			return -1;		}	}	/* Allocate a channel for each socket. */	for (n = 0; n < num_socks; n++) {		sock = socks[n];		nc = channel_new("x11 listener",		    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,		    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,		    0, xstrdup("X11 inet listener"), 1);		nc->single_connection = single_connection;	}	/* Return the display number for the DISPLAY environment variable. */	*display_numberp = display_number;	return (0);}static intconnect_local_xsocket(u_int dnr){	int sock;	struct sockaddr_un addr;	sock = socket(AF_UNIX, SOCK_STREAM, 0);	if (sock < 0)		error("socket: %.100s", strerror(errno));	memset(&addr, 0, sizeof(addr));	addr.sun_family = AF_UNIX;	snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, dnr);	if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0)		return sock;	close(sock);	error("connect %.100s: %.100s", addr.sun_path, strerror(errno));	return -1;}intx11_connect_display(void){	int display_number, sock = 0;	const char *display;	char buf[1024], *cp;	struct addrinfo hints, *ai, *aitop;	char strport[NI_MAXSERV];	int gaierr;	/* Try to open a socket for the local X server. */	display = getenv("DISPLAY");	if (!display) {		error("DISPLAY not set.");		return -1;	}	/*	 * Now we decode the value of the DISPLAY variable and make a	 * connection to the real X server.	 */	/*	 * Check if it is a unix domain socket.  Unix domain displays are in	 * one of the following formats: unix:d[.s], :d[.s], ::d[.s]	 */	if (strncmp(display, "unix:", 5) == 0 ||	    display[0] == ':') {		/* Connect to the unix domain socket. */		if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {			error("Could not parse display number from DISPLAY: %

⌨️ 快捷键说明

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