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

📄 auth1.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
字号:
/* * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */#include "includes.h"RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $");#include "xmalloc.h"#include "rsa.h"#include "ssh1.h"#include "packet.h"#include "buffer.h"#include "log.h"#include "servconf.h"#include "compat.h"#include "auth.h"#include "channels.h"#include "session.h"#include "uidswap.h"#include "monitor_wrap.h"#include "buffer.h"/* import */extern ServerOptions options;extern Buffer loginmsg;/* * convert ssh auth msg type into description */static char *get_authname(int type){	static char buf[1024];	switch (type) {	case SSH_CMSG_AUTH_PASSWORD:		return "password";	case SSH_CMSG_AUTH_RSA:		return "rsa";	case SSH_CMSG_AUTH_RHOSTS_RSA:		return "rhosts-rsa";	case SSH_CMSG_AUTH_RHOSTS:		return "rhosts";	case SSH_CMSG_AUTH_TIS:	case SSH_CMSG_AUTH_TIS_RESPONSE:		return "challenge-response";	}	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);	return buf;}/* * read packets, try to authenticate the user and * return only if authentication is successful */static voiddo_authloop(Authctxt *authctxt){	int authenticated = 0;	u_int bits;	Key *client_host_key;	BIGNUM *n;	char *client_user, *password;	char info[1024];	u_int dlen;	u_int ulen;	int prev, type = 0;	debug("Attempting authentication for %s%.100s.",	    authctxt->valid ? "" : "invalid user ", authctxt->user);	/* If the user has no password, accept authentication immediately. */	if (options.password_authentication &&#ifdef KRB5	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&#endif	    PRIVSEP(auth_password(authctxt, ""))) {#ifdef USE_PAM		if (options.use_pam && (PRIVSEP(do_pam_account())))#endif		{			auth_log(authctxt, 1, "without authentication", "");			return;		}	}	/* Indicate that authentication is needed. */	packet_start(SSH_SMSG_FAILURE);	packet_send();	packet_write_wait();	client_user = NULL;	for (;;) {		/* default to fail */		authenticated = 0;		info[0] = '\0';		/* Get a packet from the client. */		prev = type;		type = packet_read();		/*		 * If we started challenge-response authentication but the		 * next packet is not a response to our challenge, release		 * the resources allocated by get_challenge() (which would		 * normally have been released by verify_response() had we		 * received such a response)		 */		if (prev == SSH_CMSG_AUTH_TIS &&		    type != SSH_CMSG_AUTH_TIS_RESPONSE)			abandon_challenge_response(authctxt);		/* Process the packet. */		switch (type) {		case SSH_CMSG_AUTH_RHOSTS_RSA:			if (!options.rhosts_rsa_authentication) {				verbose("Rhosts with RSA authentication disabled.");				break;			}			/*			 * Get client user name.  Note that we just have to			 * trust the client; root on the client machine can			 * claim to be any user.			 */			client_user = packet_get_string(&ulen);			/* Get the client host key. */			client_host_key = key_new(KEY_RSA1);			bits = packet_get_int();			packet_get_bignum(client_host_key->rsa->e);			packet_get_bignum(client_host_key->rsa->n);			if (bits != BN_num_bits(client_host_key->rsa->n))				verbose("Warning: keysize mismatch for client_host_key: "				    "actual %d, announced %d",				    BN_num_bits(client_host_key->rsa->n), bits);			packet_check_eom();			authenticated = auth_rhosts_rsa(authctxt, client_user,			    client_host_key);			key_free(client_host_key);			snprintf(info, sizeof info, " ruser %.100s", client_user);			break;		case SSH_CMSG_AUTH_RSA:			if (!options.rsa_authentication) {				verbose("RSA authentication disabled.");				break;			}			/* RSA authentication requested. */			if ((n = BN_new()) == NULL)				fatal("do_authloop: BN_new failed");			packet_get_bignum(n);			packet_check_eom();			authenticated = auth_rsa(authctxt, n);			BN_clear_free(n);			break;		case SSH_CMSG_AUTH_PASSWORD:			if (!options.password_authentication) {				verbose("Password authentication disabled.");				break;			}			/*			 * Read user password.  It is in plain text, but was			 * transmitted over the encrypted channel so it is			 * not visible to an outside observer.			 */			password = packet_get_string(&dlen);			packet_check_eom();			/* Try authentication with the password. */			authenticated = PRIVSEP(auth_password(authctxt, password));			memset(password, 0, strlen(password));			xfree(password);			break;		case SSH_CMSG_AUTH_TIS:			debug("rcvd SSH_CMSG_AUTH_TIS");			if (options.challenge_response_authentication == 1) {				char *challenge = get_challenge(authctxt);				if (challenge != NULL) {					debug("sending challenge '%s'", challenge);					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);					packet_put_cstring(challenge);					xfree(challenge);					packet_send();					packet_write_wait();					continue;				}			}			break;		case SSH_CMSG_AUTH_TIS_RESPONSE:			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");			if (options.challenge_response_authentication == 1) {				char *response = packet_get_string(&dlen);				packet_check_eom();				authenticated = verify_response(authctxt, response);				memset(response, 'r', dlen);				xfree(response);			}			break;		default:			/*			 * Any unknown messages will be ignored (and failure			 * returned) during authentication.			 */			logit("Unknown message during authentication: type %d", type);			break;		}#ifdef BSD_AUTH		if (authctxt->as) {			auth_close(authctxt->as);			authctxt->as = NULL;		}#endif		if (!authctxt->valid && authenticated)			fatal("INTERNAL ERROR: authenticated invalid user %s",			    authctxt->user);#ifdef _UNICOS		if (authenticated && cray_access_denied(authctxt->user)) {			authenticated = 0;			fatal("Access denied for user %s.",authctxt->user);		}#endif /* _UNICOS */#ifdef HAVE_CYGWIN		if (authenticated &&		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, 		    authctxt->pw)) {			packet_disconnect("Authentication rejected for uid %d.",			    authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid);			authenticated = 0;		}#else		/* Special handling for root */		if (authenticated && authctxt->pw->pw_uid == 0 &&		    !auth_root_allowed(get_authname(type))) {			authenticated = 0;# ifdef SSH_AUDIT_EVENTS			PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));# endif		}#endif#ifdef USE_PAM		if (options.use_pam && authenticated &&		    !PRIVSEP(do_pam_account())) {			char *msg;			size_t len;			error("Access denied for user %s by PAM account "			   "configuration", authctxt->user);			len = buffer_len(&loginmsg);			buffer_append(&loginmsg, "\0", 1);			msg = buffer_ptr(&loginmsg);			/* strip trailing newlines */			if (len > 0)				while (len > 0 && msg[--len] == '\n')					msg[len] = '\0';			else				msg = "Access denied.";			packet_disconnect(msg);		}#endif		/* Log before sending the reply */		auth_log(authctxt, authenticated, get_authname(type), info);		if (client_user != NULL) {			xfree(client_user);			client_user = NULL;		}		if (authenticated)			return;		if (authctxt->failures++ > options.max_authtries) {#ifdef SSH_AUDIT_EVENTS			PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));#endif			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);		}		packet_start(SSH_SMSG_FAILURE);		packet_send();		packet_write_wait();	}}/* * Performs authentication of an incoming connection.  Session key has already * been exchanged and encryption is enabled. */voiddo_authentication(Authctxt *authctxt){	u_int ulen;	char *user, *style = NULL;	/* Get the name of the user that we wish to log in as. */	packet_read_expect(SSH_CMSG_USER);	/* Get the user name. */	user = packet_get_string(&ulen);	packet_check_eom();	if ((style = strchr(user, ':')) != NULL)		*style++ = '\0';	authctxt->user = user;	authctxt->style = style;	/* Verify that the user is a valid user. */	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)		authctxt->valid = 1;	else {		debug("do_authentication: invalid user %s", user);		authctxt->pw = fakepw();	}	setproctitle("%s%s", authctxt->valid ? user : "unknown",	    use_privsep ? " [net]" : "");#ifdef USE_PAM	if (options.use_pam)		PRIVSEP(start_pam(authctxt));#endif	/*	 * If we are not running as root, the user must have the same uid as	 * the server. (Unless you are running Windows)	 */#ifndef HAVE_CYGWIN	if (!use_privsep && getuid() != 0 && authctxt->pw &&	    authctxt->pw->pw_uid != getuid())		packet_disconnect("Cannot change user when server not running as root.");#endif	/*	 * Loop until the user has been authenticated or the connection is	 * closed, do_authloop() returns only if authentication is successful	 */	do_authloop(authctxt);	/* The user has been authenticated and accepted. */	packet_start(SSH_SMSG_SUCCESS);	packet_send();	packet_write_wait();}

⌨️ 快捷键说明

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