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

📄 sshd.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
				if ((options.protocol & SSH_PROTO_1) &&				    key_used == 0) {					/* Schedule server key regeneration alarm. */					signal(SIGALRM, key_regeneration_alarm);					alarm(options.key_regeneration_time);					key_used = 1;				}				arc4random_stir();				/* Close the new socket (the child is now taking care of it). */				close(newsock);			}			/* child process check (or debug mode) */			if (num_listen_socks < 0)				break;		}	}	/* This is the child processing a new connection. */	setproctitle("%s", "[accepted]");	/*	 * Create a new session and process group since the 4.4BSD	 * setlogin() affects the entire process group.  We don't	 * want the child to be able to affect the parent.	 */#if !defined(SSHD_ACQUIRES_CTTY)	/*	 * If setsid is called, on some platforms sshd will later acquire a	 * controlling terminal which will result in "could not set	 * controlling tty" errors.	 */	if (!debug_flag && !inetd_flag && setsid() < 0)		error("setsid: %.100s", strerror(errno));#endif	if (rexec_flag) {		int fd;		debug("rexec start in %d out %d newsock %d pipe %d sock %d",		    sock_in, sock_out, newsock, startup_pipe, config_s[0]);		dup2(newsock, STDIN_FILENO);		dup2(STDIN_FILENO, STDOUT_FILENO);		if (startup_pipe == -1)			close(REEXEC_STARTUP_PIPE_FD);		else			dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);		dup2(config_s[1], REEXEC_CONFIG_PASS_FD);		close(config_s[1]);		if (startup_pipe != -1)			close(startup_pipe);		execv(rexec_argv[0], rexec_argv);		/* Reexec has failed, fall back and continue */		error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));		recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);		log_init(__progname, options.log_level,		    options.log_facility, log_stderr);		/* Clean up fds */		startup_pipe = REEXEC_STARTUP_PIPE_FD;		close(config_s[1]);		close(REEXEC_CONFIG_PASS_FD);		newsock = sock_out = sock_in = dup(STDIN_FILENO);		if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {			dup2(fd, STDIN_FILENO);			dup2(fd, STDOUT_FILENO);			if (fd > STDERR_FILENO)				close(fd);		}		debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",		    sock_in, sock_out, newsock, startup_pipe, config_s[0]);	}	/*	 * Disable the key regeneration alarm.  We will not regenerate the	 * key since we are no longer in a position to give it to anyone. We	 * will not restart on SIGHUP since it no longer makes sense.	 */	alarm(0);	signal(SIGALRM, SIG_DFL);	signal(SIGHUP, SIG_DFL);	signal(SIGTERM, SIG_DFL);	signal(SIGQUIT, SIG_DFL);	signal(SIGCHLD, SIG_DFL);	signal(SIGINT, SIG_DFL);	/* Set SO_KEEPALIVE if requested. */	if (options.tcp_keep_alive &&	    setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on,	    sizeof(on)) < 0)		error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));	/*	 * Register our connection.  This turns encryption off because we do	 * not have a key.	 */	packet_set_connection(sock_in, sock_out);	remote_port = get_remote_port();	remote_ip = get_remote_ipaddr();#ifdef SSH_AUDIT_EVENTS	audit_connection_from(remote_ip, remote_port);#endif#ifdef LIBWRAP	/* Check whether logins are denied from this host. */	if (packet_connection_is_on_socket()) {		struct request_info req;		request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);		fromhost(&req);		if (!hosts_access(&req)) {			debug("Connection refused by tcp wrapper");			refuse(&req);			/* NOTREACHED */			fatal("libwrap refuse returns");		}	}#endif /* LIBWRAP */	/* Log the connection. */	verbose("Connection from %.500s port %d", remote_ip, remote_port);	/*	 * We don\'t want to listen forever unless the other side	 * successfully authenticates itself.  So we set up an alarm which is	 * cleared after successful authentication.  A limit of zero	 * indicates no limit. Note that we don\'t set the alarm in debugging	 * mode; it is just annoying to have the server exit just when you	 * are about to discover the bug.	 */	signal(SIGALRM, grace_alarm_handler);	if (!debug_flag)		alarm(options.login_grace_time);	sshd_exchange_identification(sock_in, sock_out);	packet_set_nonblocking();	/* allocate authentication context */	authctxt = xmalloc(sizeof(*authctxt));	memset(authctxt, 0, sizeof(*authctxt));	/* XXX global for cleanup, access from other modules */	the_authctxt = authctxt;	/* prepare buffer to collect messages to display to user after login */	buffer_init(&loginmsg);	if (use_privsep)		if (privsep_preauth(authctxt) == 1)			goto authenticated;	/* perform the key exchange */	/* authenticate user and start session */	if (compat20) {		do_ssh2_kex();		do_authentication2(authctxt);	} else {		do_ssh1_kex();		do_authentication(authctxt);	}	/*	 * If we use privilege separation, the unprivileged child transfers	 * the current keystate and exits	 */	if (use_privsep) {		mm_send_keystate(pmonitor);		exit(0);	} authenticated:#ifdef SSH_AUDIT_EVENTS	audit_event(SSH_AUTH_SUCCESS);#endif	/*	 * In privilege separation, we fork another child and prepare	 * file descriptor passing.	 */	if (use_privsep) {		privsep_postauth(authctxt);		/* the monitor process [priv] will not return */		if (!compat20)			destroy_sensitive_data();	}	/* Start session. */	do_authenticated(authctxt);	/* The connection has been terminated. */	verbose("Closing connection to %.100s", remote_ip);#ifdef USE_PAM	if (options.use_pam)		finish_pam();#endif /* USE_PAM */#ifdef SSH_AUDIT_EVENTS	PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));#endif	packet_close();	if (use_privsep)		mm_terminate();	exit(0);}/* * Decrypt session_key_int using our private server key and private host key * (key with larger modulus first). */intssh1_session_key(BIGNUM *session_key_int){	int rsafail = 0;	if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {		/* Server key has bigger modulus. */		if (BN_num_bits(sensitive_data.server_key->rsa->n) <		    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {			fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",			    get_remote_ipaddr(),			    BN_num_bits(sensitive_data.server_key->rsa->n),			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),			    SSH_KEY_BITS_RESERVED);		}		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.server_key->rsa) <= 0)			rsafail++;		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.ssh1_host_key->rsa) <= 0)			rsafail++;	} else {		/* Host key has bigger modulus (or they are equal). */		if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <		    BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {			fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",			    get_remote_ipaddr(),			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),			    BN_num_bits(sensitive_data.server_key->rsa->n),			    SSH_KEY_BITS_RESERVED);		}		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.ssh1_host_key->rsa) < 0)			rsafail++;		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.server_key->rsa) < 0)			rsafail++;	}	return (rsafail);}/* * SSH1 key exchange */static voiddo_ssh1_kex(void){	int i, len;	int rsafail = 0;	BIGNUM *session_key_int;	u_char session_key[SSH_SESSION_KEY_LENGTH];	u_char cookie[8];	u_int cipher_type, auth_mask, protocol_flags;	u_int32_t rnd = 0;	/*	 * Generate check bytes that the client must send back in the user	 * packet in order for it to be accepted; this is used to defy ip	 * spoofing attacks.  Note that this only works against somebody	 * doing IP spoofing from a remote machine; any machine on the local	 * network can still see outgoing packets and catch the random	 * cookie.  This only affects rhosts authentication, and this is one	 * of the reasons why it is inherently insecure.	 */	for (i = 0; i < 8; i++) {		if (i % 4 == 0)			rnd = arc4random();		cookie[i] = rnd & 0xff;		rnd >>= 8;	}	/*	 * Send our public key.  We include in the packet 64 bits of random	 * data that must be matched in the reply in order to prevent IP	 * spoofing.	 */	packet_start(SSH_SMSG_PUBLIC_KEY);	for (i = 0; i < 8; i++)		packet_put_char(cookie[i]);	/* Store our public server RSA key. */	packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));	packet_put_bignum(sensitive_data.server_key->rsa->e);	packet_put_bignum(sensitive_data.server_key->rsa->n);	/* Store our public host RSA key. */	packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);	/* Put protocol flags. */	packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);	/* Declare which ciphers we support. */	packet_put_int(cipher_mask_ssh1(0));	/* Declare supported authentication types. */	auth_mask = 0;	if (options.rhosts_rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;	if (options.rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RSA;	if (options.challenge_response_authentication == 1)		auth_mask |= 1 << SSH_AUTH_TIS;	if (options.password_authentication)		auth_mask |= 1 << SSH_AUTH_PASSWORD;	packet_put_int(auth_mask);	/* Send the packet and wait for it to be sent. */	packet_send();	packet_write_wait();	debug("Sent %d bit server key and %d bit host key.",	    BN_num_bits(sensitive_data.server_key->rsa->n),	    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));	/* Read clients reply (cipher type and session key). */	packet_read_expect(SSH_CMSG_SESSION_KEY);	/* Get cipher type and check whether we accept this. */	cipher_type = packet_get_char();	if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))		packet_disconnect("Warning: client selects unsupported cipher.");	/* Get check bytes from the packet.  These must match those we	   sent earlier with the public key packet. */	for (i = 0; i < 8; i++)		if (cookie[i] != packet_get_char())			packet_disconnect("IP Spoofing check bytes do not match.");	debug("Encryption type: %.200s", cipher_name(cipher_type));	/* Get the encrypted integer. */	if ((session_key_int = BN_new()) == NULL)		fatal("do_ssh1_kex: BN_new failed");	packet_get_bignum(session_key_int);	protocol_flags = packet_get_int();	packet_set_protocol_flags(protocol_flags);	packet_check_eom();	/* Decrypt session_key_int using host/server keys */	rsafail = PRIVSEP(ssh1_session_key(session_key_int));	/*	 * Extract session key from the decrypted integer.  The key is in the	 * least significant 256 bits of the integer; the first byte of the	 * key is in the highest bits.	 */	if (!rsafail) {		BN_mask_bits(session_key_int, sizeof(session_key) * 8);		len = BN_num_bytes(session_key_int);		if (len < 0 || len > sizeof(session_key)) {			error("do_connection: bad session key len from %s: "			    "session_key_int %d > sizeof(session_key) %lu",			    get_remote_ipaddr(), len, (u_long)sizeof(session_key));			rsafail++;		} else {			memset(session_key, 0, sizeof(session_key));			BN_bn2bin(session_key_int,			    session_key + sizeof(session_key) - len);			derive_ssh1_session_id(			    sensitive_data.ssh1_host_key->rsa->n,			    sensitive_data.server_key->rsa->n,			    cookie, session_id);			/*			 * Xor the first 16 bytes of the session key with the			 * session id.			 */			for (i = 0; i < 16; i++)				session_key[i] ^= session_id[i];		}	}	if (rsafail) {		int bytes = BN_num_bytes(session_key_int);		u_char *buf = xmalloc(bytes);		MD5_CTX md;		logit("do_connection: generating a fake encryption key");		BN_bn2bin(session_key_int, buf);		MD5_Init(&md);		MD5_Update(&md, buf, bytes);		MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);		MD5_Final(session_key, &md);		MD5_Init(&md);		MD5_Update(&md, session_key, 16);		MD5_Update(&md, buf, bytes);		MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);		MD5_Final(session_key + 16, &md);		memset(buf, 0, bytes);		xfree(buf);		for (i = 0; i < 16; i++)			session_id[i] = session_key[i] ^ session_key[i + 16];	}	/* Destroy the private and public keys. No longer. */	destroy_sensitive_data();	if (use_privsep)		mm_ssh1_session_id(session_id);	/* Destroy the decrypted integer.  It is no longer needed. */	BN_clear_free(session_key_int);	/* Set the session key.  From this on all communications will be encrypted. */	packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);	/* Destroy our copy of the session key.  It is no longer needed. */	memset(session_key, 0, sizeof(session_key));	debug("Received session key; encryption turned on.");	/* Send an acknowledgment packet.  Note that this packet is sent encrypted. */	packet_start(SSH_SMSG_SUCCESS);	packet_send();	packet_write_wait();}/* * SSH2 key exchange: diffie-hellman-group1-sha1 */static voiddo_ssh2_kex(void){	Kex *kex;	if (options.ciphers != NULL) {		myproposal[PROPOSAL_ENC_ALGS_CTOS] =		myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;	}	myproposal[PROPOSAL_ENC_ALGS_CTOS] =	    compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);	myproposal[PROPOSAL_ENC_ALGS_STOC] =	    compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);	if (options.macs != NULL) {		myproposal[PROPOSAL_MAC_ALGS_CTOS] =		myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;	}	if (!options.compression) {		myproposal[PROPOSAL_COMP_ALGS_CTOS] =		myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";	}	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();	/* start key exchange */	kex = kex_setup(myproposal);	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;	kex->server = 1;	kex->client_version_string=client_version_string;	kex->server_version_string=server_version_string;	kex->load_host_key=&get_hostkey_by_type;	kex->host_key_index=&get_hostkey_index;	xxx_kex = kex;	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);	session_id2 = kex->session_id;	session_id2_len = kex->session_id_len;#ifdef DEBUG_KEXDH	/* send 1st encrypted/maced/compressed message */	packet_start(SSH2_MSG_IGNORE);	packet_put_cstring("markus");	packet_send();	packet_write_wait();#endif	debug("KEX done");}/* server specific fatal cleanup */voidcleanup_exit(int i){	if (the_authctxt)		do_cleanup(the_authctxt);#ifdef SSH_AUDIT_EVENTS	/* done after do_cleanup so it can cancel the PAM auth 'thread' */	if (!use_privsep || mm_is_monitor())		audit_event(SSH_CONNECTION_ABANDON);#endif	_exit(i);}

⌨️ 快捷键说明

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