📄 auth_unix.c
字号:
default: DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user)); break; } return pam_to_nt_status(pam_error);}static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx, const struct auth_usersupplied_info *user_info, struct passwd **pws){ struct smb_pam_user_info *info; struct pam_conv *pamconv; pam_handle_t *pamh; NTSTATUS nt_status; info = talloc(ctx, struct smb_pam_user_info); if (info == NULL) { return NT_STATUS_NO_MEMORY; } info->account_name = user_info->mapped.account_name; info->plaintext_password = user_info->password.plaintext; pamconv = talloc(ctx, struct pam_conv); if (pamconv == NULL) { return NT_STATUS_NO_MEMORY; } pamconv->conv = smb_pam_conv; pamconv->appdata_ptr = (void *)info; /* TODO: * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME * if true set up a crack name routine. */ nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host ? user_info->remote_host->addr : NULL, pamconv); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } nt_status = smb_pam_auth(pamh, lp_null_passwords(lp_ctx), user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; } if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) { nt_status = smb_pam_account(pamh, user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; } nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; } } smb_pam_end(pamh); nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } return NT_STATUS_OK; }#else/****************************************************************************core of password checking routine****************************************************************************/static NTSTATUS password_check(const char *username, const char *password, const char *crypted, const char *salt){ bool ret;#ifdef WITH_AFS if (afs_auth(username, password)) return NT_STATUS_OK;#endif /* WITH_AFS */#ifdef WITH_DFS if (dfs_auth(username, password)) return NT_STATUS_OK;#endif /* WITH_DFS */#ifdef OSF1_ENH_SEC ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0); if (!ret) { DEBUG(2, ("OSF1_ENH_SEC failed. Trying normal crypt.\n")); ret = (strcmp((char *)crypt(password, salt), 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, salt), crypted) == 0); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* ULTRIX_AUTH */ #ifdef LINUX_BIGCRYPT ret = (linux_bigcrypt(password, salt, 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, salt), crypted) == 0) return NT_STATUS_OK; else ret = (strcmp((char *)crypt(password, salt), 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, salt), 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, salt), 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 */}static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx, const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd){ char *username; char *password; char *pwcopy; char *salt; char *crypted; struct passwd *pws; NTSTATUS nt_status; int level = lp_passwordlevel(lp_ctx); *ret_passwd = NULL; username = talloc_strdup(ctx, user_info->mapped.account_name); password = talloc_strdup(ctx, user_info->password.plaintext); nt_status = talloc_getpwnam(ctx, username, &pws); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } crypted = pws->pw_passwd; salt = pws->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(pws->pw_name); if (spass && spass->sp_pwdp) { crypted = talloc_strdup(ctx, spass->sp_pwdp); NT_STATUS_HAVE_NO_MEMORY(crypted); salt = talloc_strdup(ctx, spass->sp_pwdp); NT_STATUS_HAVE_NO_MEMORY(salt); } }#elif defined(IA_UINFO) { char *ia_password; /* 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(pws->pw_name, &uinfo) != -1) { ia_get_logpwd(uinfo, &ia_password); crypted = talloc_strdup(ctx, ia_password); NT_STATUS_HAVE_NO_MEMORY(crypted); } }#endif#ifdef HAVE_GETPRPWNAM { struct pr_passwd *pr_pw = getprpwnam(pws->pw_name); if (pr_pw && pr_pw->ufld.fd_encrypt) { crypted = talloc_strdup(ctx, pr_pw->ufld.fd_encrypt); NT_STATUS_HAVE_NO_MEMORY(crypted); } }#endif#ifdef HAVE_GETPWANAM { struct passwd_adjunct *pwret; pwret = getpwanam(s); if (pwret && pwret->pwa_passwd) { crypted = talloc_strdup(ctx, pwret->pwa_passwd); NT_STATUS_HAVE_NO_MEMORY(crypted); } }#endif#ifdef OSF1_ENH_SEC { struct pr_passwd *mypasswd; DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username)); mypasswd = getprpwnam(username); if (mypasswd) { username = talloc_strdup(ctx, mypasswd->ufld.fd_name); NT_STATUS_HAVE_NO_MEMORY(username); crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt); NT_STATUS_HAVE_NO_MEMORY(crypted); } else { DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username)); } }#endif#ifdef ULTRIX_AUTH { AUTHORIZATION *ap = getauthuid(pws->pw_uid); if (ap) { crypted = talloc_strdup(ctx, ap->a_password); endauthent(); NT_STATUS_HAVE_NO_MEMORY(crypted); } }#endif#if defined(HAVE_TRUNCATED_SALT) /* crypt on some platforms (HPUX in particular) won't work with more than 2 salt characters. */ salt[2] = 0;#endif if (crypted[0] == '\0') { if (!lp_null_passwords(lp_ctx)) { DEBUG(2, ("Disallowing %s with null password\n", username)); return NT_STATUS_LOGON_FAILURE; } if (password == NULL) { DEBUG(3, ("Allowing access to %s with null password\n", username)); *ret_passwd = pws; return NT_STATUS_OK; } } /* try it as it came to us */ nt_status = password_check(username, password, crypted, salt); if (NT_STATUS_IS_OK(nt_status)) { *ret_passwd = pws; 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 ( user_info->flags | USER_INFO_CASE_INSENSITIVE_PASSWORD) { 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 */ pwcopy = talloc_strdup(ctx, password); if (!pwcopy) return NT_STATUS_NO_MEMORY; /* try all lowercase if it's currently all uppercase */ if (strhasupper(pwcopy)) { strlower(pwcopy); nt_status = password_check(username, pwcopy, crypted, salt); if NT_STATUS_IS_OK(nt_status) { *ret_passwd = pws; return nt_status; } } /* give up? */ if (level < 1) { return NT_STATUS_WRONG_PASSWORD; } /* last chance - all combinations of up to level chars upper! */ strlower(pwcopy);#if 0 if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) { *ret_passwd = pws; return nt_status; }#endif return NT_STATUS_WRONG_PASSWORD;}#endif/** Check a plaintext username/password * **/static NTSTATUS authunix_want_check(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info){ if (!user_info->mapped.account_name || !*user_info->mapped.account_name) { return NT_STATUS_NOT_IMPLEMENTED; } return NT_STATUS_OK;}static NTSTATUS authunix_check_password(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info){ TALLOC_CTX *check_ctx; NTSTATUS nt_status; struct passwd *pwd; if (user_info->password_state != AUTH_PASSWORD_PLAIN) { return NT_STATUS_INVALID_PARAMETER; } check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password"); if (check_ctx == NULL) { return NT_STATUS_NO_MEMORY; } nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(check_ctx); return nt_status; } nt_status = authunix_make_server_info(mem_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx), user_info, pwd, server_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(check_ctx); return nt_status; } talloc_free(check_ctx); return NT_STATUS_OK;}static const struct auth_operations unix_ops = { .name = "unix", .get_challenge = auth_get_challenge_not_implemented, .want_check = authunix_want_check, .check_password = authunix_check_password};_PUBLIC_ NTSTATUS auth_unix_init(void){ NTSTATUS ret; ret = auth_register(&unix_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register unix auth backend!\n")); return ret; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -