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

📄 sshd.c

📁 C++编写
💻 C
📖 第 1 页 / 共 4 页
字号:
				break;		}	}	/* This is the child processing a new connection. */	/*	 * 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 (!debug_flag && !inetd_flag && setsid() < 0)		error("setsid: %.100s", strerror(errno));	/*	 * 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);	/* Set keepalives if requested. */	if (options.keepalives &&	    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 LIBWRAP	/* Check whether logins are denied from this host. */	{		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);	/*	 * Check that the connection comes from a privileged port.	 * Rhosts-Authentication only makes sense from privileged	 * programs.  Of course, if the intruder has root access on his local	 * machine, he can connect from any port.  So do not use these	 * authentication methods from machines that you do not trust.	 */	if (options.rhosts_authentication &&	    (remote_port >= IPPORT_RESERVED ||	    remote_port < IPPORT_RESERVED / 2)) {		debug("Rhosts Authentication disabled, "		    "originating port %d not trusted.", remote_port);		options.rhosts_authentication = 0;	}#if defined(KRB4) && !defined(KRB5)	if (!packet_connection_is_ipv4() &&	    options.kerberos_authentication) {		debug("Kerberos Authentication disabled, only available for IPv4.");		options.kerberos_authentication = 0;	}#endif /* KRB4 && !KRB5 */#ifdef AFS	/* If machine has AFS, set process authentication group. */	if (k_hasafs()) {		k_setpag();		k_unlog();	}#endif /* AFS */	packet_set_nonblocking();	if (use_privsep)		if ((authctxt = privsep_preauth()) != NULL)			goto authenticated;	/* perform the key exchange */	/* authenticate user and start session */	if (compat20) {		do_ssh2_kex();		authctxt = do_authentication2();	} else {		do_ssh1_kex();		authctxt = do_authentication();	}	/*	 * If we use privilege separation, the unprivileged child transfers	 * the current keystate and exits	 */	if (use_privsep) {		mm_send_keystate(pmonitor);		exit(0);	} authenticated:	/*	 * 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();	}	/* Perform session preparation. */	do_authenticated(authctxt);	/* The connection has been terminated. */	verbose("Closing connection to %.100s", remote_ip);	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_authentication)		auth_mask |= 1 << SSH_AUTH_RHOSTS;	if (options.rhosts_rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;	if (options.rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RSA;#if defined(KRB4) || defined(KRB5)	if (options.kerberos_authentication)		auth_mask |= 1 << SSH_AUTH_KERBEROS;#endif#if defined(AFS) || defined(KRB5)	if (options.kerberos_tgt_passing)		auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;#endif#ifdef AFS	if (options.afs_token_passing)		auth_mask |= 1 << SSH_PASS_AFS_TOKEN;#endif	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);			compute_session_id(session_id, cookie,			    sensitive_data.ssh1_host_key->rsa->n,			    sensitive_data.server_key->rsa->n);			/*			 * 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;		log("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_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");}

⌨️ 快捷键说明

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