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

📄 sshd.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* Demote private to public keys for network child */voiddemote_sensitive_data(void){	Key *tmp;	int i;	if (sensitive_data.server_key) {		tmp = key_demote(sensitive_data.server_key);		key_free(sensitive_data.server_key);		sensitive_data.server_key = tmp;	}	for (i = 0; i < options.num_host_key_files; i++) {		if (sensitive_data.host_keys[i]) {			tmp = key_demote(sensitive_data.host_keys[i]);			key_free(sensitive_data.host_keys[i]);			sensitive_data.host_keys[i] = tmp;			if (tmp->type == KEY_RSA1)				sensitive_data.ssh1_host_key = tmp;		}	}	/* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */}static voidprivsep_preauth_child(void){	u_int32_t rnd[256];	gid_t gidset[1];	struct passwd *pw;	int i;	/* Enable challenge-response authentication for privilege separation */	privsep_challenge_enable();	for (i = 0; i < 256; i++)		rnd[i] = arc4random();	RAND_seed(rnd, sizeof(rnd));	/* Demote the private keys to public keys. */	demote_sensitive_data();	if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)		fatal("Privilege separation user %s does not exist",		    SSH_PRIVSEP_USER);	memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));	endpwent();	/* Change our root directory */	if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)		fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,		    strerror(errno));	if (chdir("/") == -1)		fatal("chdir(\"/\"): %s", strerror(errno));	/* Drop our privileges */	debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,	    (u_int)pw->pw_gid);#if 0	/* XXX not ready, too heavy after chroot */	do_setusercontext(pw);#else	gidset[0] = pw->pw_gid;	if (setgroups(1, gidset) < 0)		fatal("setgroups: %.100s", strerror(errno));	permanently_set_uid(pw);#endif}static intprivsep_preauth(Authctxt *authctxt){	int status;	pid_t pid;	/* Set up unprivileged child process to deal with network data */	pmonitor = monitor_init();	/* Store a pointer to the kex for later rekeying */	pmonitor->m_pkex = &xxx_kex;	pid = fork();	if (pid == -1) {		fatal("fork of unprivileged child failed");	} else if (pid != 0) {		debug2("Network child is on pid %ld", (long)pid);		close(pmonitor->m_recvfd);		pmonitor->m_pid = pid;		monitor_child_preauth(authctxt, pmonitor);		close(pmonitor->m_sendfd);		/* Sync memory */		monitor_sync(pmonitor);		/* Wait for the child's exit status */		while (waitpid(pid, &status, 0) < 0)			if (errno != EINTR)				break;		return (1);	} else {		/* child */		close(pmonitor->m_sendfd);		/* Demote the child */		if (getuid() == 0 || geteuid() == 0)			privsep_preauth_child();		setproctitle("%s", "[net]");	}	return (0);}static voidprivsep_postauth(Authctxt *authctxt){#ifdef DISABLE_FD_PASSING	if (1) {#else	if (authctxt->pw->pw_uid == 0 || options.use_login) {#endif		/* File descriptor passing is broken or root login */		monitor_apply_keystate(pmonitor);		use_privsep = 0;		return;	}	/* Authentication complete */	alarm(0);	if (startup_pipe != -1) {		close(startup_pipe);		startup_pipe = -1;	}	/* New socket pair */	monitor_reinit(pmonitor);	pmonitor->m_pid = fork();	if (pmonitor->m_pid == -1)		fatal("fork of unprivileged child failed");	else if (pmonitor->m_pid != 0) {		debug2("User child is on pid %ld", (long)pmonitor->m_pid);		close(pmonitor->m_recvfd);		buffer_clear(&loginmsg);		monitor_child_postauth(pmonitor);		/* NEVERREACHED */		exit(0);	}	close(pmonitor->m_sendfd);	/* Demote the private keys to public keys. */	demote_sensitive_data();	/* Drop privileges */	do_setusercontext(authctxt->pw);	/* It is safe now to apply the key state */	monitor_apply_keystate(pmonitor);}static char *list_hostkey_types(void){	Buffer b;	const char *p;	char *ret;	int i;	buffer_init(&b);	for (i = 0; i < options.num_host_key_files; i++) {		Key *key = sensitive_data.host_keys[i];		if (key == NULL)			continue;		switch (key->type) {		case KEY_RSA:		case KEY_DSA:			if (buffer_len(&b) > 0)				buffer_append(&b, ",", 1);			p = key_ssh_name(key);			buffer_append(&b, p, strlen(p));			break;		}	}	buffer_append(&b, "\0", 1);	ret = xstrdup(buffer_ptr(&b));	buffer_free(&b);	debug("list_hostkey_types: %s", ret);	return ret;}Key *get_hostkey_by_type(int type){	int i;	for (i = 0; i < options.num_host_key_files; i++) {		Key *key = sensitive_data.host_keys[i];		if (key != NULL && key->type == type)			return key;	}	return NULL;}Key *get_hostkey_by_index(int ind){	if (ind < 0 || ind >= options.num_host_key_files)		return (NULL);	return (sensitive_data.host_keys[ind]);}intget_hostkey_index(Key *key){	int i;	for (i = 0; i < options.num_host_key_files; i++) {		if (key == sensitive_data.host_keys[i])			return (i);	}	return (-1);}/* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability * of (max_startups_rate/100). the probability increases linearly until * all connections are dropped for startups > max_startups */static intdrop_connection(int startups){	int p, r;	if (startups < options.max_startups_begin)		return 0;	if (startups >= options.max_startups)		return 1;	if (options.max_startups_rate == 100)		return 1;	p  = 100 - options.max_startups_rate;	p *= startups - options.max_startups_begin;	p /= options.max_startups - options.max_startups_begin;	p += options.max_startups_rate;	r = arc4random() % 100;	debug("drop_connection: p %d, r %d", p, r);	return (r < p) ? 1 : 0;}static voidusage(void){	fprintf(stderr, "%s, %s\n",	    SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));	fprintf(stderr,"usage: sshd [-46Ddeiqt] [-b bits] [-f config_file] [-g login_grace_time]\n""            [-h host_key_file] [-k key_gen_time] [-o option] [-p port] [-u len]\n"	);	exit(1);}static voidsend_rexec_state(int fd, Buffer *conf){	Buffer m;	debug3("%s: entering fd = %d config len %d", __func__, fd,	    buffer_len(conf));	/*	 * Protocol from reexec master to child:	 *	string	configuration	 *	u_int	ephemeral_key_follows	 *	bignum	e		(only if ephemeral_key_follows == 1)	 *	bignum	n			"	 *	bignum	d			"	 *	bignum	iqmp			"	 *	bignum	p			"	 *	bignum	q			"	 */	buffer_init(&m);	buffer_put_cstring(&m, buffer_ptr(conf));	if (sensitive_data.server_key != NULL &&	    sensitive_data.server_key->type == KEY_RSA1) {		buffer_put_int(&m, 1);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);		buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);	} else		buffer_put_int(&m, 0);	if (ssh_msg_send(fd, 0, &m) == -1)		fatal("%s: ssh_msg_send failed", __func__);	buffer_free(&m);	debug3("%s: done", __func__);}static voidrecv_rexec_state(int fd, Buffer *conf){	Buffer m;	char *cp;	u_int len;	debug3("%s: entering fd = %d", __func__, fd);	buffer_init(&m);	if (ssh_msg_recv(fd, &m) == -1)		fatal("%s: ssh_msg_recv failed", __func__);	if (buffer_get_char(&m) != 0)		fatal("%s: rexec version mismatch", __func__);	cp = buffer_get_string(&m, &len);	if (conf != NULL)		buffer_append(conf, cp, len + 1);	xfree(cp);	if (buffer_get_int(&m)) {		if (sensitive_data.server_key != NULL)			key_free(sensitive_data.server_key);		sensitive_data.server_key = key_new_private(KEY_RSA1);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);		buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);		rsa_generate_additional_parameters(		    sensitive_data.server_key->rsa);	}	buffer_free(&m);	debug3("%s: done", __func__);}/* * Main program for the daemon. */intmain(int ac, char **av){	extern char *optarg;	extern int optind;	int opt, j, i, fdsetsz, on = 1;	int sock_in = -1, sock_out = -1, newsock = -1;	pid_t pid;	socklen_t fromlen;	fd_set *fdset;	struct sockaddr_storage from;	const char *remote_ip;	int remote_port;	FILE *f;	struct addrinfo *ai;	char ntop[NI_MAXHOST], strport[NI_MAXSERV];	char *line;	int listen_sock, maxfd;	int startup_p[2] = { -1 , -1 }, config_s[2] = { -1 , -1 };	int startups = 0;	Key *key;	Authctxt *authctxt;	int ret, key_used = 0;	Buffer cfg;#ifdef HAVE_SECUREWARE	(void)set_auth_parameters(ac, av);#endif	__progname = ssh_get_progname(av[0]);	init_rng();	/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */	saved_argc = ac;	rexec_argc = ac;	saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1));	for (i = 0; i < ac; i++)		saved_argv[i] = xstrdup(av[i]);	saved_argv[i] = NULL;#ifndef HAVE_SETPROCTITLE	/* Prepare for later setproctitle emulation */	compat_init_setproctitle(ac, av);	av = saved_argv;#endif	if (geteuid() == 0 && setgroups(0, NULL) == -1)		debug("setgroups(): %.200s", strerror(errno));	/* Initialize configuration options to their default values. */	initialize_server_options(&options);	/* Parse command-line arguments. */	while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) {		switch (opt) {		case '4':			options.address_family = AF_INET;			break;		case '6':			options.address_family = AF_INET6;			break;		case 'f':			config_file_name = optarg;			break;		case 'd':			if (debug_flag == 0) {				debug_flag = 1;				options.log_level = SYSLOG_LEVEL_DEBUG1;			} else if (options.log_level < SYSLOG_LEVEL_DEBUG3)				options.log_level++;			break;		case 'D':			no_daemon_flag = 1;			break;		case 'e':			log_stderr = 1;			break;		case 'i':			inetd_flag = 1;			break;		case 'r':			rexec_flag = 0;			break;		case 'R':			rexeced_flag = 1;			inetd_flag = 1;			break;		case 'Q':			/* ignored */			break;		case 'q':			options.log_level = SYSLOG_LEVEL_QUIET;			break;		case 'b':			options.server_key_bits = atoi(optarg);			break;		case 'p':			options.ports_from_cmdline = 1;			if (options.num_ports >= MAX_PORTS) {				fprintf(stderr, "too many ports.\n");				exit(1);			}			options.ports[options.num_ports++] = a2port(optarg);			if (options.ports[options.num_ports-1] == 0) {				fprintf(stderr, "Bad port number.\n");				exit(1);			}			break;		case 'g':			if ((options.login_grace_time = convtime(optarg)) == -1) {				fprintf(stderr, "Invalid login grace time.\n");				exit(1);			}			break;		case 'k':			if ((options.key_regeneration_time = convtime(optarg)) == -1) {				fprintf(stderr, "Invalid key regeneration interval.\n");				exit(1);			}			break;		case 'h':			if (options.num_host_key_files >= MAX_HOSTKEYS) {				fprintf(stderr, "too many host keys.\n");				exit(1);			}			options.host_key_files[options.num_host_key_files++] = optarg;			break;		case 't':			test_flag = 1;			break;		case 'u':			utmp_len = atoi(optarg);			if (utmp_len > MAXHOSTNAMELEN) {				fprintf(stderr, "Invalid utmp length.\n");				exit(1);			}			break;		case 'o':			line = xstrdup(optarg);			if (process_server_config_line(&options, line,			    "command-line", 0) != 0)				exit(1);			xfree(line);			break;		case '?':		default:			usage();			break;		}	}	if (rexeced_flag || inetd_flag)		rexec_flag = 0;	if (rexec_flag && (av[0] == NULL || *av[0] != '/'))		fatal("sshd re-exec requires execution with an absolute path");	if (rexeced_flag)		closefrom(REEXEC_MIN_FREE_FD);	else		closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);

⌨️ 快捷键说明

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