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

📄 session.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
		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);	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();	logit("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)		logit("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_break_req(Session *s){	packet_get_int();	/* ignored */	packet_check_eom();	if (s->ttyfd == -1 ||	    tcsendbreak(s->ttyfd, 0) < 0)		return 0;	return 1;}static intsession_env_req(Session *s){	char *name, *val;	u_int name_len, val_len, i;	name = packet_get_string(&name_len);	val = packet_get_string(&val_len);	packet_check_eom();	/* Don't set too many environment variables */	if (s->num_env > 128) {		debug2("Ignoring env request %s: too many env vars", name);		goto fail;	}	for (i = 0; i < options.num_accept_env; i++) {		if (match_pattern(name, options.accept_env[i])) {			debug2("Setting env %d: %s=%s", s->num_env, name, val);			s->env = xrealloc(s->env, sizeof(*s->env) *			    (s->num_env + 1));			s->env[s->num_env].name = name;			s->env[s->num_env].val = val;			s->num_env++;			return (1);		}	}	debug2("Ignoring env request %s: disallowed name", name); fail:	xfree(name);	xfree(val);	return (0);}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) {		logit("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);		} else if (strcmp(rtype, "env") == 0) {			success = session_env_req(s);		}	}	if (strcmp(rtype, "window-change") == 0) {		success = session_window_change_req(s);	} else if (strcmp(rtype, "break") == 0) {		success = session_break_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(Session *s){	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(Session *s){	PRIVSEP(session_pty_cleanup2(s));}static char *sig2name(int sig){#define SSH_SIG(x) if (sig == SIG ## x) return #x	SSH_SIG(ABRT);	SSH_SIG(ALRM);	SSH_SIG(FPE);	SSH_SIG(HUP);	SSH_SIG(ILL);	SSH_SIG(INT);	SSH_SIG(KILL);	SSH_SIG(PIPE);	SSH_SIG(QUIT);	SSH_SIG(SEGV);	SSH_SIG(TERM);	SSH_SIG(USR1);	SSH_SIG(USR2);#undef	SSH_SIG	return "SIG@openssh.com";}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_cstring(sig2name(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){	int i;	debug("session_close: session %d pid %ld", s->self, (long)s->pid);	if (s->ttyfd != -1)		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;	for (i = 0; i < s->num_env; i++) {		xfree(s->env[i].name);		xfree(s->env[i].val);	}	if (s->env != NULL)		xfree(s->env);	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)			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;	char *cp;	buf[0] = '\0';	for (i = 0; i < MAX_SESSIONS; i++) {		Session *s = &sessions[i];		if (s->used && s->ttyfd != -1) {			if (strncmp(s->tty, "/dev/", 5) != 0) {				cp = strrchr(s->tty, '/');				cp = (cp == NULL) ? s->tty : cp + 1;			} else				cp = s->tty + 5;			if (buf[0] != '\0')				strlcat(buf, ",", sizeof buf);			strlcat(buf, cp, 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;	}	if (x11_create_display_inet(options.x11_display_offset,	    options.x11_use_localhost, s->single_connection,	    &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:%u.%u",		    s->display_number, s->screen);		snprintf(auth_display, sizeof auth_display, "unix:%u.%u",		    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:%u.%u", inet_ntoa(my_addr),		    s->display_number, s->screen);#else		snprintf(display, sizeof display, "%.400s:%u.%u", 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);}voiddo_cleanup(Authctxt *authctxt){	static int called = 0;	debug("do_cleanup");	/* no cleanup if we're in the child for login shell */	if (is_child)		return;	/* avoid double cleanup */	if (called)		return;	called = 1;	if (authctxt == NULL)		return;#ifdef KRB5	if (options.kerberos_ticket_cleanup &&	    authctxt->krb5_ctx)		krb5_cleanup_proc(authctxt);#endif#ifdef GSSAPI	if (compat20 && options.gss_cleanup_creds)		ssh_gssapi_cleanup_creds();#endif#ifdef USE_PAM	if (options.use_pam) {		sshpam_cleanup();		sshpam_thread_cleanup();	}#endif	/* remove agent socket */	auth_sock_cleanup_proc(authctxt->pw);	/*	 * Cleanup ptys/utmp only if privsep is disabled,	 * or if running in monitor.	 */	if (!use_privsep || mm_is_monitor())		session_destroy_all(session_pty_cleanup2);}

⌨️ 快捷键说明

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