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

📄 session.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef HAVE_CYGWIN	if (is_winnt)		cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);#endif	if (pid < 0)		packet_disconnect("fork failed: %.100s", strerror(errno));	s->pid = pid;	/* Parent.  Close the slave side of the pseudo tty. */	close(ttyfd);	/*	 * Create another descriptor of the pty master side for use as the	 * standard input.  We could use the original descriptor, but this	 * simplifies code in server_loop.  The descriptor is bidirectional.	 */	fdout = dup(ptyfd);	if (fdout < 0)		packet_disconnect("dup #1 failed: %.100s", strerror(errno));	/* we keep a reference to the pty master */	ptymaster = dup(ptyfd);	if (ptymaster < 0)		packet_disconnect("dup #2 failed: %.100s", strerror(errno));	s->ptymaster = ptymaster;	/* Enter interactive session. */	packet_set_interactive(1);	if (compat20) {		session_set_fds(s, ptyfd, fdout, -1);	} else {		server_loop(pid, ptyfd, fdout, -1);		/* server_loop _has_ closed ptyfd and fdout. */	}}#ifdef LOGIN_NEEDS_UTMPXstatic voiddo_pre_login(Session *s){	socklen_t fromlen;	struct sockaddr_storage from;	pid_t pid = getpid();	/*	 * Get IP address of client. If the connection is not a socket, let	 * the address be 0.0.0.0.	 */	memset(&from, 0, sizeof(from));	fromlen = sizeof(from);	if (packet_connection_is_on_socket()) {		if (getpeername(packet_get_connection_in(),		    (struct sockaddr *) & from, &fromlen) < 0) {			debug("getpeername: %.100s", strerror(errno));			cleanup_exit(255);		}	}	record_utmp_only(pid, s->tty, s->pw->pw_name,	    get_remote_name_or_ip(utmp_len, options.use_dns),	    (struct sockaddr *)&from, fromlen);}#endif/* * This is called to fork and execute a command.  If another command is * to be forced, execute that instead. */voiddo_exec(Session *s, const char *command){	if (forced_command) {		original_command = command;		command = forced_command;		debug("Forced command '%.900s'", command);	}#ifdef SSH_AUDIT_EVENTS	if (command != NULL)		PRIVSEP(audit_run_command(command));	else if (s->ttyfd == -1) {		char *shell = s->pw->pw_shell;		if (shell[0] == '\0')	/* empty shell means /bin/sh */			shell =_PATH_BSHELL;		PRIVSEP(audit_run_command(shell));	}#endif	if (s->ttyfd != -1)		do_exec_pty(s, command);	else		do_exec_no_pty(s, command);	original_command = NULL;	/*	 * Clear loginmsg: it's the child's responsibility to display	 * it to the user, otherwise multiple sessions may accumulate	 * multiple copies of the login messages.	 */	buffer_clear(&loginmsg);}/* administrative, login(1)-like work */voiddo_login(Session *s, const char *command){	socklen_t fromlen;	struct sockaddr_storage from;	struct passwd * pw = s->pw;	pid_t pid = getpid();	/*	 * Get IP address of client. If the connection is not a socket, let	 * the address be 0.0.0.0.	 */	memset(&from, 0, sizeof(from));	fromlen = sizeof(from);	if (packet_connection_is_on_socket()) {		if (getpeername(packet_get_connection_in(),		    (struct sockaddr *) & from, &fromlen) < 0) {			debug("getpeername: %.100s", strerror(errno));			cleanup_exit(255);		}	}	/* Record that there was a login on that tty from the remote host. */	if (!use_privsep)		record_login(pid, s->tty, pw->pw_name, pw->pw_uid,		    get_remote_name_or_ip(utmp_len,		    options.use_dns),		    (struct sockaddr *)&from, fromlen);#ifdef USE_PAM	/*	 * If password change is needed, do it now.	 * This needs to occur before the ~/.hushlogin check.	 */	if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {		display_loginmsg();		do_pam_chauthtok();		s->authctxt->force_pwchange = 0;		/* XXX - signal [net] parent to enable forwardings */	}#endif	if (check_quietlogin(s, command))		return;	display_loginmsg();	do_motd();}/* * Display the message of the day. */voiddo_motd(void){	FILE *f;	char buf[256];	if (options.print_motd) {#ifdef HAVE_LOGIN_CAP		f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",		    "/etc/motd"), "r");#else		f = fopen("/etc/motd", "r");#endif		if (f) {			while (fgets(buf, sizeof(buf), f))				fputs(buf, stdout);			fclose(f);		}	}}/* * Check for quiet login, either .hushlogin or command given. */intcheck_quietlogin(Session *s, const char *command){	char buf[256];	struct passwd *pw = s->pw;	struct stat st;	/* Return 1 if .hushlogin exists or a command given. */	if (command != NULL)		return 1;	snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);#ifdef HAVE_LOGIN_CAP	if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)		return 1;#else	if (stat(buf, &st) >= 0)		return 1;#endif	return 0;}/* * Sets the value of the given variable in the environment.  If the variable * already exists, its value is overriden. */voidchild_set_env(char ***envp, u_int *envsizep, const char *name,	const char *value){	char **env;	u_int envsize;	u_int i, namelen;	/*	 * If we're passed an uninitialized list, allocate a single null	 * entry before continuing.	 */	if (*envp == NULL && *envsizep == 0) {		*envp = xmalloc(sizeof(char *));		*envp[0] = NULL;		*envsizep = 1;	}	/*	 * Find the slot where the value should be stored.  If the variable	 * already exists, we reuse the slot; otherwise we append a new slot	 * at the end of the array, expanding if necessary.	 */	env = *envp;	namelen = strlen(name);	for (i = 0; env[i]; i++)		if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')			break;	if (env[i]) {		/* Reuse the slot. */		xfree(env[i]);	} else {		/* New variable.  Expand if necessary. */		envsize = *envsizep;		if (i >= envsize - 1) {			if (envsize >= 1000)				fatal("child_set_env: too many env vars");			envsize += 50;			env = (*envp) = xrealloc(env, envsize * sizeof(char *));			*envsizep = envsize;		}		/* Need to set the NULL pointer at end of array beyond the new slot. */		env[i + 1] = NULL;	}	/* Allocate space and format the variable in the appropriate slot. */	env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);	snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);}/* * Reads environment variables from the given file and adds/overrides them * into the environment.  If the file does not exist, this does nothing. * Otherwise, it must consist of empty lines, comments (line starts with '#') * and assignments of the form name=value.  No other forms are allowed. */static voidread_environment_file(char ***env, u_int *envsize,	const char *filename){	FILE *f;	char buf[4096];	char *cp, *value;	u_int lineno = 0;	f = fopen(filename, "r");	if (!f)		return;	while (fgets(buf, sizeof(buf), f)) {		if (++lineno > 1000)			fatal("Too many lines in environment file %s", filename);		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)			;		if (!*cp || *cp == '#' || *cp == '\n')			continue;		if (strchr(cp, '\n'))			*strchr(cp, '\n') = '\0';		value = strchr(cp, '=');		if (value == NULL) {			fprintf(stderr, "Bad line %u in %.100s\n", lineno,			    filename);			continue;		}		/*		 * Replace the equals sign by nul, and advance value to		 * the value string.		 */		*value = '\0';		value++;		child_set_env(env, envsize, cp, value);	}	fclose(f);}#ifdef HAVE_ETC_DEFAULT_LOGIN/* * Return named variable from specified environment, or NULL if not present. */static char *child_get_env(char **env, const char *name){	int i;	size_t len;	len = strlen(name);	for (i=0; env[i] != NULL; i++)		if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')			return(env[i] + len + 1);	return NULL;}/* * Read /etc/default/login. * We pick up the PATH (or SUPATH for root) and UMASK. */static voidread_etc_default_login(char ***env, u_int *envsize, uid_t uid){	char **tmpenv = NULL, *var;	u_int i, tmpenvsize = 0;	u_long mask;	/*	 * We don't want to copy the whole file to the child's environment,	 * so we use a temporary environment and copy the variables we're	 * interested in.	 */	read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");	if (tmpenv == NULL)		return;	if (uid == 0)		var = child_get_env(tmpenv, "SUPATH");	else		var = child_get_env(tmpenv, "PATH");	if (var != NULL)		child_set_env(env, envsize, "PATH", var);	if ((var = child_get_env(tmpenv, "UMASK")) != NULL)		if (sscanf(var, "%5lo", &mask) == 1)			umask((mode_t)mask);	for (i = 0; tmpenv[i] != NULL; i++)		xfree(tmpenv[i]);	xfree(tmpenv);}#endif /* HAVE_ETC_DEFAULT_LOGIN */void copy_environment(char **source, char ***env, u_int *envsize){	char *var_name, *var_val;	int i;	if (source == NULL)		return;	for(i = 0; source[i] != NULL; i++) {		var_name = xstrdup(source[i]);		if ((var_val = strstr(var_name, "=")) == NULL) {			xfree(var_name);			continue;		}		*var_val++ = '\0';		debug3("Copy environment: %s=%s", var_name, var_val);		child_set_env(env, envsize, var_name, var_val);		xfree(var_name);	}}static char **do_setup_env(Session *s, const char *shell){	char buf[256];	u_int i, envsize;	char **env, *laddr, *path = NULL;	struct passwd *pw = s->pw;	/* Initialize the environment. */	envsize = 100;	env = xmalloc(envsize * sizeof(char *));	env[0] = NULL;#ifdef HAVE_CYGWIN	/*	 * The Windows environment contains some setting which are	 * important for a running system. They must not be dropped.	 */	{		char **p;		p = fetch_windows_environment();		copy_environment(p, &env, &envsize);		free_windows_environment(p);	}#endif#ifdef GSSAPI	/* Allow any GSSAPI methods that we've used to alter	 * the childs environment as they see fit	 */	ssh_gssapi_do_child(&env, &envsize);#endif	if (!options.use_login) {		/* Set basic environment. */		for (i = 0; i < s->num_env; i++)			child_set_env(&env, &envsize, s->env[i].name,			    s->env[i].val);		child_set_env(&env, &envsize, "USER", pw->pw_name);		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);#ifdef _AIX		child_set_env(&env, &envsize, "LOGIN", pw->pw_name);#endif		child_set_env(&env, &envsize, "HOME", pw->pw_dir);#ifdef HAVE_LOGIN_CAP		if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)			child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);		else			child_set_env(&env, &envsize, "PATH", getenv("PATH"));#else /* HAVE_LOGIN_CAP */# ifndef HAVE_CYGWIN		/*		 * There's no standard path on Windows. The path contains		 * important components pointing to the system directories,		 * needed for loading shared libraries. So the path better		 * remains intact here.		 */#  ifdef HAVE_ETC_DEFAULT_LOGIN		read_etc_default_login(&env, &envsize, pw->pw_uid);		path = child_get_env(env, "PATH");#  endif /* HAVE_ETC_DEFAULT_LOGIN */		if (path == NULL || *path == '\0') {			child_set_env(&env, &envsize, "PATH",			    s->pw->pw_uid == 0 ?				SUPERUSER_PATH : _PATH_STDPATH);		}# endif /* HAVE_CYGWIN */#endif /* HAVE_LOGIN_CAP */		snprintf(buf, sizeof buf, "%.200s/%.50s",			 _PATH_MAILDIR, pw->pw_name);		child_set_env(&env, &envsize, "MAIL", buf);		/* Normal systems set SHELL by default. */		child_set_env(&env, &envsize, "SHELL", shell);	}	if (getenv("TZ"))		child_set_env(&env, &envsize, "TZ", getenv("TZ"));	/* Set custom environment options from RSA authentication. */	if (!options.use_login) {		while (custom_environment) {			struct envstring *ce = custom_environment;			char *str = ce->s;			for (i = 0; str[i] != '=' && str[i]; i++)				;			if (str[i] == '=') {				str[i] = 0;				child_set_env(&env, &envsize, str, str + i + 1);			}			custom_environment = ce->next;			xfree(ce->s);			xfree(ce);		}	}	/* SSH_CLIENT deprecated */	snprintf(buf, sizeof buf, "%.50s %d %d",	    get_remote_ipaddr(), get_remote_port(), get_local_port());	child_set_env(&env, &envsize, "SSH_CLIENT", buf);	laddr = get_local_ipaddr(packet_get_connection_in());	snprintf(buf, sizeof buf, "%.50s %d %.50s %d",	    get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());	xfree(laddr);	child_set_env(&env, &envsize, "SSH_CONNECTION", buf);	if (s->ttyfd != -1)		child_set_env(&env, &envsize, "SSH_TTY", s->tty);	if (s->term)		child_set_env(&env, &envsize, "TERM", s->term);	if (s->display)		child_set_env(&env, &envsize, "DISPLAY", s->display);	if (original_command)		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",		    original_command);#ifdef _UNICOS	if (cray_tmpdir[0] != '\0')		child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);#endif /* _UNICOS */	/*	 * Since we clear KRB5CCNAME at startup, if it's set now then it	 * must have been set by a native authentication method (eg AIX or	 * SIA), so copy it to the child.	 */	{		char *cp;		if ((cp = getenv("KRB5CCNAME")) != NULL)			child_set_env(&env, &envsize, "KRB5CCNAME", cp);	}#ifdef _AIX	{		char *cp;		if ((cp = getenv("AUTHSTATE")) != NULL)			child_set_env(&env, &envsize, "AUTHSTATE", cp);		read_environment_file(&env, &envsize, "/etc/environment");	}#endif#ifdef KRB5	if (s->authctxt->krb5_ccname)		child_set_env(&env, &envsize, "KRB5CCNAME",		    s->authctxt->krb5_ccname);#endif#ifdef USE_PAM	/*	 * Pull in any environment variables that may have	 * been set by PAM.	 */	if (options.use_pam) {		char **p;		p = fetch_pam_child_environment();		copy_environment(p, &env, &envsize);		free_pam_environment(p);		p = fetch_pam_environment();		copy_environment(p, &env, &envsize);		free_pam_environment(p);	}#endif /* USE_PAM */	if (auth_sock_name != NULL)		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,		    auth_sock_name);	/* read $HOME/.ssh/environment. */	if (options.permit_user_env && !options.use_login) {		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",		    strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");		read_environment_file(&env, &envsize, buf);	}	if (debug_flag) {		/* dump the environment */		fprintf(stderr, "Environment:\n");		for (i = 0; env[i]; i++)			fprintf(stderr, "  %.200s\n", env[i]);	}	return env;}/* * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found * first in this order). */static voiddo_rc_files(Session *s, const char *shell){	FILE *f = NULL;	char cmd[1024];	int do_xauth;	struct stat st;	do_xauth =	    s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;	/* ignore _PATH_SSH_USER_RC for subsystems */	if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {		snprintf(cmd, sizeof cmd, "%s -c '%s %s'",		    shell, _PATH_BSHELL, _PATH_SSH_USER_RC);		if (debug_flag)			fprintf(stderr, "Running %s\n", cmd);

⌨️ 快捷键说明

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