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

📄 clientloop.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Read input from the server, and add any such data to the buffer of	 * the packet subsystem.	 */	if (FD_ISSET(connection_in, readset)) {		/* Read as much as possible. */		len = read(connection_in, buf, sizeof(buf));		if (len == 0) {			/* Received EOF.  The remote host has closed the connection. */			snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",				 host);			buffer_append(&stderr_buffer, buf, strlen(buf));			quit_pending = 1;			return;		}		/*		 * There is a kernel bug on Solaris that causes select to		 * sometimes wake up even though there is no data available.		 */		if (len < 0 && (errno == EAGAIN || errno == EINTR))			len = 0;		if (len < 0) {			/* An error has encountered.  Perhaps there is a network problem. */			snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",				 host, strerror(errno));			buffer_append(&stderr_buffer, buf, strlen(buf));			quit_pending = 1;			return;		}		packet_process_incoming(buf, len);	}}static voidclient_subsystem_reply(int type, u_int32_t seq, void *ctxt){	int id;	Channel *c;	id = packet_get_int();	packet_check_eom();	if ((c = channel_lookup(id)) == NULL) {		error("%s: no channel for id %d", __func__, id);		return;	}	if (type == SSH2_MSG_CHANNEL_SUCCESS)		debug2("Request suceeded on channel %d", id);	else if (type == SSH2_MSG_CHANNEL_FAILURE) {		error("Request failed on channel %d", id);		channel_free(c);	}}static voidclient_extra_session2_setup(int id, void *arg){	struct confirm_ctx *cctx = arg;	Channel *c;	int i;	if (cctx == NULL)		fatal("%s: cctx == NULL", __func__);	if ((c = channel_lookup(id)) == NULL)		fatal("%s: no channel for id %d", __func__, id);	client_session2_setup(id, cctx->want_tty, cctx->want_subsys,	    cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,	    client_subsystem_reply);	c->confirm_ctx = NULL;	buffer_free(&cctx->cmd);	xfree(cctx->term);	if (cctx->env != NULL) {		for (i = 0; cctx->env[i] != NULL; i++)			xfree(cctx->env[i]);		xfree(cctx->env);	}	xfree(cctx);}static voidclient_process_control(fd_set * readset){	Buffer m;	Channel *c;	int client_fd, new_fd[3], ver, i, allowed;	socklen_t addrlen;	struct sockaddr_storage addr;	struct confirm_ctx *cctx;	char *cmd;	u_int len, env_len, command, flags;	uid_t euid;	gid_t egid;	/*	 * Accept connection on control socket	 */	if (control_fd == -1 || !FD_ISSET(control_fd, readset))		return;	memset(&addr, 0, sizeof(addr));	addrlen = sizeof(addr);	if ((client_fd = accept(control_fd,	    (struct sockaddr*)&addr, &addrlen)) == -1) {		error("%s accept: %s", __func__, strerror(errno));		return;	}	if (getpeereid(client_fd, &euid, &egid) < 0) {		error("%s getpeereid failed: %s", __func__, strerror(errno));		close(client_fd);		return;	}	if ((euid != 0) && (getuid() != euid)) {		error("control mode uid mismatch: peer euid %u != uid %u",		    (u_int) euid, (u_int) getuid());		close(client_fd);		return;	}	unset_nonblock(client_fd);	/* Read command */	buffer_init(&m);	if (ssh_msg_recv(client_fd, &m) == -1) {		error("%s: client msg_recv failed", __func__);		close(client_fd);		buffer_free(&m);		return;	}	if ((ver = buffer_get_char(&m)) != 1) {		error("%s: wrong client version %d", __func__, ver);		buffer_free(&m);		close(client_fd);		return;	}	allowed = 1;	command = buffer_get_int(&m);	flags = buffer_get_int(&m);	buffer_clear(&m);	switch (command) {	case SSHMUX_COMMAND_OPEN:		if (options.control_master == 2)			allowed = ask_permission("Allow shared connection "			    "to %s? ", host);		/* continue below */		break;	case SSHMUX_COMMAND_TERMINATE:		if (options.control_master == 2)			allowed = ask_permission("Terminate shared connection "			    "to %s? ", host);		if (allowed)			quit_pending = 1;		/* FALLTHROUGH */		case SSHMUX_COMMAND_ALIVE_CHECK:		/* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */		buffer_clear(&m);		buffer_put_int(&m, allowed);		buffer_put_int(&m, getpid());		if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {			error("%s: client msg_send failed", __func__);			close(client_fd);			buffer_free(&m);			return;		}		buffer_free(&m);		close(client_fd);		return;	default:		error("Unsupported command %d", command);		buffer_free(&m);		close(client_fd);		return;	}	/* Reply for SSHMUX_COMMAND_OPEN */	buffer_clear(&m);	buffer_put_int(&m, allowed);	buffer_put_int(&m, getpid());	if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {		error("%s: client msg_send failed", __func__);		close(client_fd);		buffer_free(&m);		return;	}	if (!allowed) {		error("Refused control connection");		close(client_fd);		buffer_free(&m);		return;	}	buffer_clear(&m);	if (ssh_msg_recv(client_fd, &m) == -1) {		error("%s: client msg_recv failed", __func__);		close(client_fd);		buffer_free(&m);		return;	}	if ((ver = buffer_get_char(&m)) != 1) {		error("%s: wrong client version %d", __func__, ver);		buffer_free(&m);		close(client_fd);		return;	}	cctx = xmalloc(sizeof(*cctx));	memset(cctx, 0, sizeof(*cctx));	cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;	cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;	cctx->term = buffer_get_string(&m, &len);	cmd = buffer_get_string(&m, &len);	buffer_init(&cctx->cmd);	buffer_append(&cctx->cmd, cmd, strlen(cmd));	env_len = buffer_get_int(&m);	env_len = MIN(env_len, 4096);	debug3("%s: receiving %d env vars", __func__, env_len);	if (env_len != 0) {		cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1));		for (i = 0; i < env_len; i++)			cctx->env[i] = buffer_get_string(&m, &len);		cctx->env[i] = NULL;	}	debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,	    cctx->want_tty, cctx->want_subsys, cmd);	/* Gather fds from client */	new_fd[0] = mm_receive_fd(client_fd);	new_fd[1] = mm_receive_fd(client_fd);	new_fd[2] = mm_receive_fd(client_fd);	debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,	    new_fd[0], new_fd[1], new_fd[2]);	/* Try to pick up ttymodes from client before it goes raw */	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)		error("%s: tcgetattr: %s", __func__, strerror(errno));	/* This roundtrip is just for synchronisation of ttymodes */	buffer_clear(&m);	if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {		error("%s: client msg_send failed", __func__);		close(client_fd);		close(new_fd[0]);		close(new_fd[1]);		close(new_fd[2]);		buffer_free(&m);		xfree(cctx->term);		if (env_len != 0) {			for (i = 0; i < env_len; i++)				xfree(cctx->env[i]);			xfree(cctx->env);		}		return;	}	buffer_free(&m);	/* enable nonblocking unless tty */	if (!isatty(new_fd[0]))		set_nonblock(new_fd[0]);	if (!isatty(new_fd[1]))		set_nonblock(new_fd[1]);	if (!isatty(new_fd[2]))		set_nonblock(new_fd[2]);	set_nonblock(client_fd);	c = channel_new("session", SSH_CHANNEL_OPENING,	    new_fd[0], new_fd[1], new_fd[2],	    CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT,	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);	/* XXX */	c->ctl_fd = client_fd;	debug3("%s: channel_new: %d", __func__, c->self);	channel_send_open(c->self);	channel_register_confirm(c->self, client_extra_session2_setup, cctx);}static voidprocess_cmdline(void){	void (*handler)(int);	char *s, *cmd, *cancel_host;	int delete = 0;	int local = 0;	u_short cancel_port;	Forward fwd;	leave_raw_mode();	handler = signal(SIGINT, SIG_IGN);	cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);	if (s == NULL)		goto out;	while (*s && isspace(*s))		s++;	if (*s == '-')		s++;	/* Skip cmdline '-', if any */	if (*s == '\0')		goto out;	if (*s == 'h' || *s == 'H' || *s == '?') {		logit("Commands:");		logit("      -Lport:host:hostport    Request local forward");		logit("      -Rport:host:hostport    Request remote forward");		logit("      -KRhostport             Cancel remote forward");		goto out;	}	if (*s == 'K') {		delete = 1;		s++;	}	if (*s != 'L' && *s != 'R') {		logit("Invalid command.");		goto out;	}	if (*s == 'L')		local = 1;	if (local && delete) {		logit("Not supported.");		goto out;	}	if ((!local || delete) && !compat20) {		logit("Not supported for SSH protocol version 1.");		goto out;	}	s++;	while (*s && isspace(*s))		s++;	if (delete) {		cancel_port = 0;		cancel_host = hpdelim(&s);	/* may be NULL */		if (s != NULL) {			cancel_port = a2port(s);			cancel_host = cleanhostname(cancel_host);		} else {			cancel_port = a2port(cancel_host);			cancel_host = NULL;		}		if (cancel_port == 0) {			logit("Bad forwarding close port");			goto out;		}		channel_request_rforward_cancel(cancel_host, cancel_port);	} else {		if (!parse_forward(&fwd, s)) {			logit("Bad forwarding specification.");			goto out;		}		if (local) {			if (channel_setup_local_fwd_listener(fwd.listen_host,			    fwd.listen_port, fwd.connect_host,			    fwd.connect_port, options.gateway_ports) < 0) {				logit("Port forwarding failed.");				goto out;			}		} else {			channel_request_remote_forwarding(fwd.listen_host,			    fwd.listen_port, fwd.connect_host,			    fwd.connect_port);		}		logit("Forwarding port.");	}out:	signal(SIGINT, handler);	enter_raw_mode();	if (cmd)		xfree(cmd);}/* process the characters one by one */static intprocess_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len){	char string[1024];	pid_t pid;	int bytes = 0;	u_int i;	u_char ch;	char *s;	for (i = 0; i < len; i++) {		/* Get one character at a time. */		ch = buf[i];		if (escape_pending) {			/* We have previously seen an escape character. */			/* Clear the flag now. */			escape_pending = 0;			/* Process the escaped character. */			switch (ch) {			case '.':				/* Terminate the connection. */				snprintf(string, sizeof string, "%c.\r\n", escape_char);				buffer_append(berr, string, strlen(string));				quit_pending = 1;				return -1;			case 'Z' - 64:				/* Suspend the program. */				/* Print a message to that effect to the user. */				snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);				buffer_append(berr, string, strlen(string));				/* Restore terminal modes and suspend. */				client_suspend_self(bin, bout, berr);				/* We have been continued. */				continue;			case 'B':				if (compat20) {					snprintf(string, sizeof string,					    "%cB\r\n", escape_char);					buffer_append(berr, string,					    strlen(string));					channel_request_start(session_ident,					    "break", 0);					packet_put_int(1000);					packet_send();				}				continue;			case 'R':				if (compat20) {					if (datafellows & SSH_BUG_NOREKEY)						logit("Server does not support re-keying");					else						need_rekeying = 1;				}				continue;			case '&':				/*				 * Detach the program (continue to serve connections,				 * but put in background and no more new connections).				 */				/* Restore tty modes. */				leave_raw_mode();				/* Stop listening for new connections. */				channel_stop_listening();				snprintf(string, sizeof string,				    "%c& [backgrounded]\n", escape_char);				buffer_append(berr, string, strlen(string));				/* Fork into background. */				pid = fork();

⌨️ 快捷键说明

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