pass_check.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 784 行 · 第 1/2 页

C
784
字号
		crypted += strlen(p);	}	return (1);}#endif#ifdef OSF1_ENH_SEC/****************************************************************************an enhanced crypt for OSF1****************************************************************************/static char *osf1_bigcrypt(char *password, char *salt1){	static char result[AUTH_MAX_PASSWD_LENGTH] = "";	char *p1;	char *p2 = password;	char salt[3];	int i;	int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;	if (strlen(password) % AUTH_CLEARTEXT_SEG_CHARS)		parts++;	StrnCpy(salt, salt1, 2);	StrnCpy(result, salt1, 2);	result[2] = '\0';	for (i = 0; i < parts; i++) {		p1 = crypt(p2, salt);		strncat(result, p1 + 2,			AUTH_MAX_PASSWD_LENGTH - strlen(p1 + 2) - 1);		StrnCpy(salt, &result[2 + i * AUTH_CIPHERTEXT_SEG_CHARS], 2);		p2 += AUTH_CLEARTEXT_SEG_CHARS;	}	return (result);}#endif/****************************************************************************apply a function to upper/lower case combinationsof a string and return true if one of them returns true.try all combinations with N uppercase letters.offset is the first char to try and change (start with 0)it assumes the string starts lowercased****************************************************************************/static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const char *),				 int N){	int len = strlen(s);	int i;	NTSTATUS nt_status;#ifdef PASSWORD_LENGTH	len = MIN(len, PASSWORD_LENGTH);#endif	if (N <= 0 || offset >= len)		return (fn(s));	for (i = offset; i < (len - (N - 1)); i++) {		char c = s[i];		if (!islower_ascii(c))			continue;		s[i] = toupper_ascii(c);		if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) {			return (nt_status);		}		s[i] = c;	}	return (NT_STATUS_WRONG_PASSWORD);}/****************************************************************************apply a function to upper/lower case combinationsof a string and return true if one of them returns true.try all combinations with up to N uppercase letters.offset is the first char to try and change (start with 0)it assumes the string starts lowercased****************************************************************************/static NTSTATUS string_combinations(char *s, NTSTATUS (*fn) (const char *), int N){	int n;	NTSTATUS nt_status;	for (n = 1; n <= N; n++)		if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, 0, fn, n), NT_STATUS_WRONG_PASSWORD))			return nt_status;	return NT_STATUS_WRONG_PASSWORD;}/****************************************************************************core of password checking routine****************************************************************************/static NTSTATUS password_check(const char *password){#ifdef WITH_PAM	return smb_pam_passcheck(this_user, password);#else	BOOL ret;#ifdef WITH_AFS	if (afs_auth(this_user, password))		return NT_STATUS_OK;#endif /* WITH_AFS */#ifdef WITH_DFS	if (dfs_auth(this_user, password))		return NT_STATUS_OK;#endif /* WITH_DFS */#ifdef OSF1_ENH_SEC		ret = (strcmp(osf1_bigcrypt(password, this_salt),		      this_crypted) == 0);	if (!ret) {		DEBUG(2,		      ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));		ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);	}	if (ret) {		return NT_STATUS_OK;	} else {		return NT_STATUS_WRONG_PASSWORD;	}	#endif /* OSF1_ENH_SEC */	#ifdef ULTRIX_AUTH	ret = (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0);	if (ret) {		return NT_STATUS_OK;        } else {		return NT_STATUS_WRONG_PASSWORD;	}	#endif /* ULTRIX_AUTH */	#ifdef LINUX_BIGCRYPT	ret = (linux_bigcrypt(password, this_salt, this_crypted));        if (ret) {		return NT_STATUS_OK;	} else {		return NT_STATUS_WRONG_PASSWORD;	}#endif /* LINUX_BIGCRYPT */	#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)		/*	 * Some systems have bigcrypt in the C library but might not	 * actually use it for the password hashes (HPUX 10.20) is	 * a noteable example. So we try bigcrypt first, followed	 * by crypt.	 */	if (strcmp(bigcrypt(password, this_salt), this_crypted) == 0)		return NT_STATUS_OK;	else		ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);	if (ret) {		return NT_STATUS_OK;	} else {		return NT_STATUS_WRONG_PASSWORD;	}#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */	#ifdef HAVE_BIGCRYPT	ret = (strcmp(bigcrypt(password, this_salt), this_crypted) == 0);        if (ret) {		return NT_STATUS_OK;	} else {		return NT_STATUS_WRONG_PASSWORD;	}#endif /* HAVE_BIGCRYPT */	#ifndef HAVE_CRYPT	DEBUG(1, ("Warning - no crypt available\n"));	return NT_STATUS_LOGON_FAILURE;#else /* HAVE_CRYPT */	ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);        if (ret) {		return NT_STATUS_OK;	} else {		return NT_STATUS_WRONG_PASSWORD;	}#endif /* HAVE_CRYPT */#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */#endif /* WITH_PAM */}/****************************************************************************CHECK if a username/password is OKthe function pointer fn() points to a function to call when a successfulmatch is found and is used to update the encrypted password file return NT_STATUS_OK on correct match, appropriate error otherwise****************************************************************************/NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *password, 		    int pwlen, BOOL (*fn) (const char *, const char *), BOOL run_cracker){	pstring pass2;	int level = lp_passwordlevel();	NTSTATUS nt_status;#ifdef DEBUG_PASSWORD	DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password));#endif	if (!password)		return NT_STATUS_LOGON_FAILURE;	if (((!*password) || (!pwlen)) && !lp_null_passwords())		return NT_STATUS_LOGON_FAILURE;#if defined(WITH_PAM) 	/*	 * If we're using PAM we want to short-circuit all the 	 * checks below and dive straight into the PAM code.	 */	fstrcpy(this_user, user);	DEBUG(4, ("pass_check: Checking (PAM) password for user %s (l=%d)\n", user, pwlen));#else /* Not using PAM */	DEBUG(4, ("pass_check: Checking password for user %s (l=%d)\n", user, pwlen));	if (!pass) {		DEBUG(3, ("Couldn't find user %s\n", user));		return NT_STATUS_NO_SUCH_USER;	}	/* Copy into global for the convenience of looping code */	/* Also the place to keep the 'password' no matter what	   crazy struct it started in... */	fstrcpy(this_crypted, pass->pw_passwd);	fstrcpy(this_salt, pass->pw_passwd);#ifdef HAVE_GETSPNAM	{		struct spwd *spass;		/* many shadow systems require you to be root to get		   the password, in most cases this should already be		   the case when this function is called, except		   perhaps for IPC password changing requests */		spass = getspnam(pass->pw_name);		if (spass && spass->sp_pwdp) {			fstrcpy(this_crypted, spass->sp_pwdp);			fstrcpy(this_salt, spass->sp_pwdp);		}	}#elif defined(IA_UINFO)	{		/* Need to get password with SVR4.2's ia_ functions		   instead of get{sp,pw}ent functions. Required by		   UnixWare 2.x, tested on version		   2.1. (tangent@cyberport.com) */		uinfo_t uinfo;		if (ia_openinfo(pass->pw_name, &uinfo) != -1)			ia_get_logpwd(uinfo, &(pass->pw_passwd));	}#endif#ifdef HAVE_GETPRPWNAM	{		struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);		if (pr_pw && pr_pw->ufld.fd_encrypt)			fstrcpy(this_crypted, pr_pw->ufld.fd_encrypt);	}#endif#ifdef HAVE_GETPWANAM	{		struct passwd_adjunct *pwret;		pwret = getpwanam(s);		if (pwret && pwret->pwa_passwd)			fstrcpy(this_crypted, pwret->pwa_passwd);	}#endif#ifdef OSF1_ENH_SEC	{		struct pr_passwd *mypasswd;		DEBUG(5, ("Checking password for user %s in OSF1_ENH_SEC\n",			  user));		mypasswd = getprpwnam(user);		if (mypasswd) {			fstrcpy(this_user, mypasswd->ufld.fd_name);			fstrcpy(this_crypted, mypasswd->ufld.fd_encrypt);		} else {			DEBUG(5,			      ("OSF1_ENH_SEC: No entry for user %s in protected database !\n",			       user));		}	}#endif#ifdef ULTRIX_AUTH	{		AUTHORIZATION *ap = getauthuid(pass->pw_uid);		if (ap) {			fstrcpy(this_crypted, ap->a_password);			endauthent();		}	}#endif#if defined(HAVE_TRUNCATED_SALT)	/* crypt on some platforms (HPUX in particular)	   won't work with more than 2 salt characters. */	this_salt[2] = 0;#endif	if (!*this_crypted) {		if (!lp_null_passwords()) {			DEBUG(2, ("Disallowing %s with null password\n",				  this_user));			return NT_STATUS_LOGON_FAILURE;		}		if (!*password) {			DEBUG(3,			      ("Allowing access to %s with null password\n",			       this_user));			return NT_STATUS_OK;		}	}#endif /* defined(WITH_PAM) */	/* try it as it came to us */	nt_status = password_check(password);        if NT_STATUS_IS_OK(nt_status) {                if (fn) {                        fn(user, password);		}		return (nt_status);	} else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {                /* No point continuing if its not the password thats to blame (ie PAM disabled). */                return (nt_status);        }	if (!run_cracker) {		return (nt_status);	}	/* if the password was given to us with mixed case then we don't	 * need to proceed as we know it hasn't been case modified by the	 * client */	if (strhasupper(password) && strhaslower(password)) {		return nt_status;	}	/* make a copy of it */	pstrcpy(pass2, password);	/* try all lowercase if it's currently all uppercase */	if (strhasupper(pass2)) {		strlower_m(pass2);		if NT_STATUS_IS_OK(nt_status = password_check(pass2)) {		        if (fn)				fn(user, pass2);			return (nt_status);		}	}	/* give up? */	if (level < 1) {		return NT_STATUS_WRONG_PASSWORD;	}	/* last chance - all combinations of up to level chars upper! */	strlower_m(pass2);         if (NT_STATUS_IS_OK(nt_status = string_combinations(pass2, password_check, level))) {                if (fn)			fn(user, pass2);		return nt_status;	}        	return NT_STATUS_WRONG_PASSWORD;}

⌨️ 快捷键说明

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