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

📄 session.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 4 页
字号:
		 * seem to depend on it.		 */		close(inout[1]);		close(err[1]);		if (dup2(inout[0], 0) < 0)	/* stdin */			perror("dup2 stdin");		if (dup2(inout[0], 1) < 0)	/* stdout.  Note: same socket as stdin. */			perror("dup2 stdout");		if (dup2(err[0], 2) < 0)	/* stderr */			perror("dup2 stderr");#endif /* USE_PIPES */		/* Do processing for the child (exec command etc). */		do_child(s, command);		/* NOTREACHED */	}#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;	/* Set interactive/non-interactive mode. */	packet_set_interactive(s->display != NULL);#ifdef USE_PIPES	/* We are the parent.  Close the child sides of the pipes. */	close(pin[0]);	close(pout[1]);	close(perr[1]);	if (compat20) {		session_set_fds(s, pin[1], pout[0], s->is_subsystem ? -1 : perr[0]);	} else {		/* Enter the interactive session. */		server_loop(pid, pin[1], pout[0], perr[0]);		/* server_loop has closed pin[1], pout[0], and perr[0]. */	}#else /* USE_PIPES */	/* We are the parent.  Close the child sides of the socket pairs. */	close(inout[0]);	close(err[0]);	/*	 * Enter the interactive session.  Note: server_loop must be able to	 * handle the case that fdin and fdout are the same.	 */	if (compat20) {		session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);	} else {		server_loop(pid, inout[1], inout[1], err[1]);		/* server_loop has closed inout[1] and err[1]. */	}#endif /* USE_PIPES */}/* * This is called to fork and execute a command when we have a tty.  This * will call do_child from the child, and server_loop from the parent after * setting up file descriptors, controlling tty, updating wtmp, utmp, * lastlog, and other such operations. */voiddo_exec_pty(Session *s, const char *command){	int fdout, ptyfd, ttyfd, ptymaster;	pid_t pid;	if (s == NULL)		fatal("do_exec_pty: no session");	ptyfd = s->ptyfd;	ttyfd = s->ttyfd;#if defined(USE_PAM)	do_pam_session(s->pw->pw_name, s->tty);	do_pam_setcred(1);#endif	/* Fork the child. */	if ((pid = fork()) == 0) {		/* Child.  Reinitialize the log because the pid has changed. */		log_init(__progname, options.log_level, options.log_facility, log_stderr);		/* Close the master side of the pseudo tty. */		close(ptyfd);		/* Make the pseudo tty our controlling tty. */		pty_make_controlling_tty(&ttyfd, s->tty);		/* Redirect stdin/stdout/stderr from the pseudo tty. */		if (dup2(ttyfd, 0) < 0)			error("dup2 stdin: %s", strerror(errno));		if (dup2(ttyfd, 1) < 0)			error("dup2 stdout: %s", strerror(errno));		if (dup2(ttyfd, 2) < 0)			error("dup2 stderr: %s", strerror(errno));		/* Close the extra descriptor for the pseudo tty. */		close(ttyfd);		/* record login, etc. similar to login(1) */#ifndef HAVE_OSF_SIA		if (!(options.use_login && command == NULL))			do_login(s, command);# ifdef LOGIN_NEEDS_UTMPX		else			do_pre_login(s);# endif#endif		/* Do common processing for the child, such as execing the command. */		do_child(s, command);		/* NOTREACHED */	}#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));	if (packet_connection_is_on_socket()) {		fromlen = sizeof(from);		if (getpeername(packet_get_connection_in(),		    (struct sockaddr *) & from, &fromlen) < 0) {			debug("getpeername: %.100s", strerror(errno));			fatal_cleanup();		}	}	record_utmp_only(pid, s->tty, s->pw->pw_name,	    get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),	    (struct sockaddr *)&from);}#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);	}	if (s->ttyfd != -1)		do_exec_pty(s, command);	else		do_exec_no_pty(s, command);	original_command = NULL;}/* administrative, login(1)-like work */voiddo_login(Session *s, const char *command){	char *time_string;	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));	if (packet_connection_is_on_socket()) {		fromlen = sizeof(from);		if (getpeername(packet_get_connection_in(),		    (struct sockaddr *) & from, &fromlen) < 0) {			debug("getpeername: %.100s", strerror(errno));			fatal_cleanup();		}	}	/* 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.verify_reverse_mapping),		    (struct sockaddr *)&from);#ifdef USE_PAM	/*	 * If password change is needed, do it now.	 * This needs to occur before the ~/.hushlogin check.	 */	if (is_pam_password_change_required()) {		print_pam_messages();		do_pam_chauthtok();	}#endif	if (check_quietlogin(s, command))		return;#ifdef USE_PAM	if (!is_pam_password_change_required())		print_pam_messages();#endif /* USE_PAM */#ifdef WITH_AIXAUTHENTICATE	if (aixloginmsg && *aixloginmsg)		printf("%s\n", aixloginmsg);#endif /* WITH_AIXAUTHENTICATE */	if (options.print_lastlog && s->last_login_time != 0) {		time_string = ctime(&s->last_login_time);		if (strchr(time_string, '\n'))			*strchr(time_string, '\n') = 0;		if (strcmp(s->hostname, "") == 0)			printf("Last login: %s\r\n", time_string);		else			printf("Last login: %s from %s\r\n", time_string,			    s->hostname);	}	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. */static voidchild_set_env(char ***envp, u_int *envsizep, const char *name,	const char *value){	u_int i, namelen;	char **env;	/*	 * 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. */		if (i >= (*envsizep) - 1) {			(*envsizep) += 50;			env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));		}		/* 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;	f = fopen(filename, "r");	if (!f)		return;	while (fgets(buf, sizeof(buf), f)) {		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 in %.100s: %.200s\n", filename, buf);			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);}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;	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.	 */	copy_environment(environ, &env, &envsize);#endif	if (!options.use_login) {		/* Set basic environment. */		child_set_env(&env, &envsize, "USER", pw->pw_name);		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);		child_set_env(&env, &envsize, "HOME", pw->pw_dir);#ifdef HAVE_LOGIN_CAP		(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);		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 SUPERUSER_PATH		child_set_env(&env, &envsize, "PATH", 		    s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);#  else 		child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);#  endif /* SUPERUSER_PATH */# 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 *s = ce->s;			for (i = 0; s[i] != '=' && s[i]; i++)				;			if (s[i] == '=') {				s[i] = 0;				child_set_env(&env, &envsize, s, s + i + 1);			}			custom_environment = ce->next;			xfree(ce->s);			xfree(ce);		}	}	snprintf(buf, sizeof buf, "%.50s %d %d",	    get_remote_ipaddr(), get_remote_port(), get_local_port());	child_set_env(&env, &envsize, "SSH_CLIENT", 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);

⌨️ 快捷键说明

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