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

📄 session.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 4 页
字号:
static intsession_pty_req(Session *s){	u_int len;	int n_bytes;	if (no_pty_flag) {		debug("Allocating a pty not permitted for this authentication.");		return 0;	}	if (s->ttyfd != -1) {		packet_disconnect("Protocol error: you already have a pty.");		return 0;	}	/* Get the time and hostname when the user last logged in. */	if (options.print_lastlog) {		s->hostname[0] = '\0';		s->last_login_time = get_last_login_time(s->pw->pw_uid,		    s->pw->pw_name, s->hostname, sizeof(s->hostname));	}	s->term = packet_get_string(&len);	if (compat20) {		s->col = packet_get_int();		s->row = packet_get_int();	} else {		s->row = packet_get_int();		s->col = packet_get_int();	}	s->xpixel = packet_get_int();	s->ypixel = packet_get_int();	if (strcmp(s->term, "") == 0) {		xfree(s->term);		s->term = NULL;	}	/* Allocate a pty and open it. */	debug("Allocating pty.");	if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {		if (s->term)			xfree(s->term);		s->term = NULL;		s->ptyfd = -1;		s->ttyfd = -1;		error("session_pty_req: session %d alloc failed", s->self);		return 0;	}	debug("session_pty_req: session %d alloc %s", s->self, s->tty);	/* for SSH1 the tty modes length is not given */	if (!compat20)		n_bytes = packet_remaining();	tty_parse_modes(s->ttyfd, &n_bytes);	/*	 * Add a cleanup function to clear the utmp entry and record logout	 * time in case we call fatal() (e.g., the connection gets closed).	 */	fatal_add_cleanup(session_pty_cleanup, (void *)s);	if (!use_privsep)		pty_setowner(s->pw, s->tty);	/* Set window size from the packet. */	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);	packet_check_eom();	session_proctitle(s);	return 1;}static intsession_subsystem_req(Session *s){	struct stat st;	u_int len;	int success = 0;	char *cmd, *subsys = packet_get_string(&len);	int i;	packet_check_eom();	log("subsystem request for %.100s", subsys);	for (i = 0; i < options.num_subsystems; i++) {		if (strcmp(subsys, options.subsystem_name[i]) == 0) {			cmd = options.subsystem_command[i];			if (stat(cmd, &st) < 0) {				error("subsystem: cannot stat %s: %s", cmd,				    strerror(errno));				break;			}			debug("subsystem: exec() %s", cmd);			s->is_subsystem = 1;			do_exec(s, cmd);			success = 1;			break;		}	}	if (!success)		log("subsystem request for %.100s failed, subsystem not found",		    subsys);	xfree(subsys);	return success;}static intsession_x11_req(Session *s){	int success;	s->single_connection = packet_get_char();	s->auth_proto = packet_get_string(NULL);	s->auth_data = packet_get_string(NULL);	s->screen = packet_get_int();	packet_check_eom();	success = session_setup_x11fwd(s);	if (!success) {		xfree(s->auth_proto);		xfree(s->auth_data);		s->auth_proto = NULL;		s->auth_data = NULL;	}	return success;}static intsession_shell_req(Session *s){	packet_check_eom();	do_exec(s, NULL);	return 1;}static intsession_exec_req(Session *s){	u_int len;	char *command = packet_get_string(&len);	packet_check_eom();	do_exec(s, command);	xfree(command);	return 1;}static intsession_auth_agent_req(Session *s){	static int called = 0;	packet_check_eom();	if (no_agent_forwarding_flag) {		debug("session_auth_agent_req: no_agent_forwarding_flag");		return 0;	}	if (called) {		return 0;	} else {		called = 1;		return auth_input_request_forwarding(s->pw);	}}intsession_input_channel_req(Channel *c, const char *rtype){	int success = 0;	Session *s;	if ((s = session_by_channel(c->self)) == NULL) {		log("session_input_channel_req: no session %d req %.100s",		    c->self, rtype);		return 0;	}	debug("session_input_channel_req: session %d req %s", s->self, rtype);	/*	 * a session is in LARVAL state until a shell, a command	 * or a subsystem is executed	 */	if (c->type == SSH_CHANNEL_LARVAL) {		if (strcmp(rtype, "shell") == 0) {			success = session_shell_req(s);		} else if (strcmp(rtype, "exec") == 0) {			success = session_exec_req(s);		} else if (strcmp(rtype, "pty-req") == 0) {			success =  session_pty_req(s);		} else if (strcmp(rtype, "x11-req") == 0) {			success = session_x11_req(s);		} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {			success = session_auth_agent_req(s);		} else if (strcmp(rtype, "subsystem") == 0) {			success = session_subsystem_req(s);		}	}	if (strcmp(rtype, "window-change") == 0) {		success = session_window_change_req(s);	}	return success;}voidsession_set_fds(Session *s, int fdin, int fdout, int fderr){	if (!compat20)		fatal("session_set_fds: called for proto != 2.0");	/*	 * now that have a child and a pipe to the child,	 * we can activate our channel and register the fd's	 */	if (s->chanid == -1)		fatal("no channel for session %d", s->self);	channel_set_fds(s->chanid,	    fdout, fdin, fderr,	    fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,	    1,	    CHAN_SES_WINDOW_DEFAULT);}/* * Function to perform pty cleanup. Also called if we get aborted abnormally * (e.g., due to a dropped connection). */voidsession_pty_cleanup2(void *session){	Session *s = session;	if (s == NULL) {		error("session_pty_cleanup: no session");		return;	}	if (s->ttyfd == -1)		return;	debug("session_pty_cleanup: session %d release %s", s->self, s->tty);	/* Record that the user has logged out. */	if (s->pid != 0)		record_logout(s->pid, s->tty, s->pw->pw_name);	/* Release the pseudo-tty. */	if (getuid() == 0)		pty_release(s->tty);	/*	 * Close the server side of the socket pairs.  We must do this after	 * the pty cleanup, so that another process doesn't get this pty	 * while we're still cleaning up.	 */	if (close(s->ptymaster) < 0)		error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));	/* unlink pty from session */	s->ttyfd = -1;}voidsession_pty_cleanup(void *session){	PRIVSEP(session_pty_cleanup2(session));}static voidsession_exit_message(Session *s, int status){	Channel *c;	if ((c = channel_lookup(s->chanid)) == NULL)		fatal("session_exit_message: session %d: no channel %d",		    s->self, s->chanid);	debug("session_exit_message: session %d channel %d pid %ld",	    s->self, s->chanid, (long)s->pid);	if (WIFEXITED(status)) {		channel_request_start(s->chanid, "exit-status", 0);		packet_put_int(WEXITSTATUS(status));		packet_send();	} else if (WIFSIGNALED(status)) {		channel_request_start(s->chanid, "exit-signal", 0);		packet_put_int(WTERMSIG(status));#ifdef WCOREDUMP		packet_put_char(WCOREDUMP(status));#else /* WCOREDUMP */		packet_put_char(0);#endif /* WCOREDUMP */		packet_put_cstring("");		packet_put_cstring("");		packet_send();	} else {		/* Some weird exit cause.  Just exit. */		packet_disconnect("wait returned status %04x.", status);	}	/* disconnect channel */	debug("session_exit_message: release channel %d", s->chanid);	channel_cancel_cleanup(s->chanid);	/*	 * emulate a write failure with 'chan_write_failed', nobody will be	 * interested in data we write.	 * Note that we must not call 'chan_read_failed', since there could	 * be some more data waiting in the pipe.	 */	if (c->ostate != CHAN_OUTPUT_CLOSED)		chan_write_failed(c);	s->chanid = -1;}voidsession_close(Session *s){	debug("session_close: session %d pid %ld", s->self, (long)s->pid);	if (s->ttyfd != -1) {		fatal_remove_cleanup(session_pty_cleanup, (void *)s);		session_pty_cleanup(s);	}	if (s->term)		xfree(s->term);	if (s->display)		xfree(s->display);	if (s->auth_display)		xfree(s->auth_display);	if (s->auth_data)		xfree(s->auth_data);	if (s->auth_proto)		xfree(s->auth_proto);	s->used = 0;	session_proctitle(s);}voidsession_close_by_pid(pid_t pid, int status){	Session *s = session_by_pid(pid);	if (s == NULL) {		debug("session_close_by_pid: no session for pid %ld",		    (long)pid);		return;	}	if (s->chanid != -1)		session_exit_message(s, status);	session_close(s);}/* * this is called when a channel dies before * the session 'child' itself dies */voidsession_close_by_channel(int id, void *arg){	Session *s = session_by_channel(id);	if (s == NULL) {		debug("session_close_by_channel: no session for id %d", id);		return;	}	debug("session_close_by_channel: channel %d child %ld",	    id, (long)s->pid);	if (s->pid != 0) {		debug("session_close_by_channel: channel %d: has child", id);		/*		 * delay detach of session, but release pty, since		 * the fd's to the child are already closed		 */		if (s->ttyfd != -1) {			fatal_remove_cleanup(session_pty_cleanup, (void *)s);			session_pty_cleanup(s);		}		return;	}	/* detach by removing callback */	channel_cancel_cleanup(s->chanid);	s->chanid = -1;	session_close(s);}voidsession_destroy_all(void (*closefunc)(Session *)){	int i;	for (i = 0; i < MAX_SESSIONS; i++) {		Session *s = &sessions[i];		if (s->used) {			if (closefunc != NULL)				closefunc(s);			else				session_close(s);		}	}}static char *session_tty_list(void){	static char buf[1024];	int i;	buf[0] = '\0';	for (i = 0; i < MAX_SESSIONS; i++) {		Session *s = &sessions[i];		if (s->used && s->ttyfd != -1) {			if (buf[0] != '\0')				strlcat(buf, ",", sizeof buf);			strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);		}	}	if (buf[0] == '\0')		strlcpy(buf, "notty", sizeof buf);	return buf;}voidsession_proctitle(Session *s){	if (s->pw == NULL)		error("no user for session %d", s->self);	else		setproctitle("%s@%s", s->pw->pw_name, session_tty_list());}intsession_setup_x11fwd(Session *s){	struct stat st;	char display[512], auth_display[512];	char hostname[MAXHOSTNAMELEN];	if (no_x11_forwarding_flag) {		packet_send_debug("X11 forwarding disabled in user configuration file.");		return 0;	}	if (!options.x11_forwarding) {		debug("X11 forwarding disabled in server configuration file.");		return 0;	}	if (!options.xauth_location ||	    (stat(options.xauth_location, &st) == -1)) {		packet_send_debug("No xauth program; cannot forward with spoofing.");		return 0;	}	if (options.use_login) {		packet_send_debug("X11 forwarding disabled; "		    "not compatible with UseLogin=yes.");		return 0;	}	if (s->display != NULL) {		debug("X11 display already set.");		return 0;	}	s->display_number = x11_create_display_inet(options.x11_display_offset,	    options.x11_use_localhost, s->single_connection);	if (s->display_number == -1) {		debug("x11_create_display_inet failed.");		return 0;	}	/* Set up a suitable value for the DISPLAY variable. */	if (gethostname(hostname, sizeof(hostname)) < 0)		fatal("gethostname: %.100s", strerror(errno));	/*	 * auth_display must be used as the displayname when the	 * authorization entry is added with xauth(1).  This will be	 * different than the DISPLAY string for localhost displays.	 */	if (options.x11_use_localhost) {		snprintf(display, sizeof display, "localhost:%d.%d",		    s->display_number, s->screen);		snprintf(auth_display, sizeof auth_display, "unix:%d.%d",		    s->display_number, s->screen);		s->display = xstrdup(display);		s->auth_display = xstrdup(auth_display);	} else {#ifdef IPADDR_IN_DISPLAY		struct hostent *he;		struct in_addr my_addr;		he = gethostbyname(hostname);		if (he == NULL) {			error("Can't get IP address for X11 DISPLAY.");			packet_send_debug("Can't get IP address for X11 DISPLAY.");			return 0;		}		memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));		snprintf(display, sizeof display, "%.50s:%d.%d", inet_ntoa(my_addr),		    s->display_number, s->screen);#else		snprintf(display, sizeof display, "%.400s:%d.%d", hostname,		    s->display_number, s->screen);#endif		s->display = xstrdup(display);		s->auth_display = xstrdup(display);	}	return 1;}static voiddo_authenticated2(Authctxt *authctxt){	server_loop2(authctxt);}

⌨️ 快捷键说明

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