diff options
author | Günther Deschner <gd@samba.org> | 2008-08-15 02:34:22 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2008-10-10 15:40:23 +0200 |
commit | 3eae89dd7729c08a40d97dc1b095011bf2933dce (patch) | |
tree | 62cd0f5d09fa860cae4557f14e18228c5b7769d1 | |
parent | ed2b94c1a29017013a8eb773755c051f4c2a2eb0 (diff) | |
download | samba-3eae89dd7729c08a40d97dc1b095011bf2933dce.tar.gz samba-3eae89dd7729c08a40d97dc1b095011bf2933dce.tar.bz2 samba-3eae89dd7729c08a40d97dc1b095011bf2933dce.zip |
pam_winbind: use libwbclient for WINBINDD_PAM_CHAUTHTOK.
Guenther
-rw-r--r-- | source3/nsswitch/pam_winbind.c | 144 | ||||
-rw-r--r-- | source3/nsswitch/pam_winbind.h | 8 |
2 files changed, 71 insertions, 81 deletions
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9448890d28..4f9a27b721 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -772,10 +772,6 @@ static int pam_winbind_request_log(struct pwb_context *ctx, _pam_log(ctx, LOG_NOTICE, "user '%s' granted access", user); break; - case WINBINDD_PAM_CHAUTHTOK: - _pam_log(ctx, LOG_NOTICE, - "user '%s' password changed", user); - break; default: _pam_log(ctx, LOG_NOTICE, "user '%s' OK", user); @@ -1317,42 +1313,45 @@ static bool _pam_check_remark_auth_err(struct pwb_context *ctx, /** * Compose Password Restriction String for a PAM_ERROR_MSG conversation. * - * @param response The struct winbindd_response. + * @param i The wbcUserPasswordPolicyInfo struct. * - * @return string (caller needs to free). + * @return string (caller needs to talloc_free). */ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx, - struct winbindd_response *response) + struct wbcUserPasswordPolicyInfo *i) { char *str = NULL; + if (!i) { + goto failed; + } + str = talloc_asprintf(ctx, "Your password "); if (!str) { goto failed; } - if (response->data.auth.policy.min_length_password > 0) { + if (i->min_length_password > 0) { str = talloc_asprintf_append(str, "must be at least %d characters; ", - response->data.auth.policy.min_length_password); + i->min_length_password); if (!str) { goto failed; } } - if (response->data.auth.policy.password_history > 0) { + if (i->password_history > 0) { str = talloc_asprintf_append(str, "cannot repeat any of your previous %d " "passwords; ", - response->data.auth.policy.password_history); + i->password_history); if (!str) { goto failed; } } - if (response->data.auth.policy.password_properties & - DOMAIN_PASSWORD_COMPLEX) { + if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) { str = talloc_asprintf_append(str, "must contain capitals, numerals " "or punctuation; " @@ -1572,99 +1571,95 @@ static int winbind_chauthtok_request(struct pwb_context *ctx, const char *newpass, time_t pwd_last_set) { - struct winbindd_request request; - struct winbindd_response response; - int ret; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (request.data.chauthtok.user == NULL) { - return -2; - } - - strncpy(request.data.chauthtok.user, user, - sizeof(request.data.chauthtok.user) - 1); + wbcErr wbc_status; + struct wbcChangePasswordParams params; + struct wbcAuthErrorInfo *error = NULL; + struct wbcUserPasswordPolicyInfo *policy = NULL; + enum wbcPasswordChangeRejectReason reject_reason = -1; + uint32_t flags = 0; - if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, - sizeof(request.data.chauthtok.oldpass) - 1); - } else { - request.data.chauthtok.oldpass[0] = '\0'; - } + int i; + const char *codes[] = { + "NT_STATUS_BACKUP_CONTROLLER", + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "NT_STATUS_NO_LOGON_SERVERS", + "NT_STATUS_ACCESS_DENIED", + "NT_STATUS_PWD_TOO_SHORT", /* TODO: tell the min pwd length ? */ + "NT_STATUS_PWD_TOO_RECENT", /* TODO: tell the minage ? */ + "NT_STATUS_PWD_HISTORY_CONFLICT" /* TODO: tell the history length ? */ + }; + int ret = PAM_AUTH_ERR; - if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, - sizeof(request.data.chauthtok.newpass) - 1); - } else { - request.data.chauthtok.newpass[0] = '\0'; - } + ZERO_STRUCT(params); if (ctx->ctrl & WINBIND_KRB5_AUTH) { - request.flags = WBFLAG_PAM_KRB5 | - WBFLAG_PAM_CONTACT_TRUSTDOM; + flags |= WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; } if (ctx->ctrl & WINBIND_CACHED_LOGIN) { - request.flags |= WBFLAG_PAM_CACHED_LOGIN; + flags |= WBFLAG_PAM_CACHED_LOGIN; } - ret = pam_winbind_request_log(ctx, WINBINDD_PAM_CHAUTHTOK, - &request, &response, user); - - if (ret == PAM_SUCCESS) { - return ret; - } + params.account_name = user; + params.level = WBC_AUTH_USER_LEVEL_PLAIN; + params.old_password.plaintext = oldpass; + params.new_password.plaintext = newpass; + params.flags = flags; - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_BACKUP_CONTROLLER"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_ACCESS_DENIED"); + wbc_status = wbcChangeUserPasswordEx(¶ms, &error, &reject_reason, &policy); + ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status, + user, "wbcChangeUserPasswordEx"); - /* TODO: tell the min pwd length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_PWD_TOO_SHORT"); + if (WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_NOTICE, + "user '%s' password changed", user); + return PAM_SUCCESS; + } - /* TODO: tell the minage ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_PWD_TOO_RECENT"); + if (!error) { + wbcFreeMemory(policy); + return ret; + } - /* TODO: tell the history length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, - "NT_STATUS_PWD_HISTORY_CONFLICT"); + for (i=0; i<ARRAY_SIZE(codes); i++) { + int _ret = ret; + if (_pam_check_remark_auth_err(ctx, error, codes[i], &_ret)) { + ret = _ret; + goto done; + } + } - if (!strcasecmp(response.data.auth.nt_status_string, + if (!strcasecmp(error->nt_string, "NT_STATUS_PASSWORD_RESTRICTION")) { char *pwd_restriction_string = NULL; - SMB_TIME_T min_pwd_age; - uint32_t reject_reason = response.data.auth.reject_reason; - min_pwd_age = response.data.auth.policy.min_passwordage; + SMB_TIME_T min_pwd_age = 0; + + if (policy) { + min_pwd_age = policy->min_passwordage; + } /* FIXME: avoid to send multiple PAM messages after another */ switch (reject_reason) { case -1: break; - case SAMR_REJECT_OTHER: + case WBC_PWD_CHANGE_REJECT_OTHER: if ((min_pwd_age > 0) && (pwd_last_set + min_pwd_age > time(NULL))) { PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_TOO_RECENT"); } break; - case SAMR_REJECT_TOO_SHORT: + case WBC_PWD_CHANGE_REJECT_TOO_SHORT: PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_TOO_SHORT"); break; - case SAMR_REJECT_IN_HISTORY: + case WBC_PWD_CHANGE_REJECT_IN_HISTORY: PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_HISTORY_CONFLICT"); break; - case SAMR_REJECT_COMPLEXITY: + case WBC_PWD_CHANGE_REJECT_COMPLEXITY: _make_remark(ctx, PAM_ERROR_MSG, "Password does not meet " "complexity requirements"); @@ -1678,13 +1673,16 @@ static int winbind_chauthtok_request(struct pwb_context *ctx, } pwd_restriction_string = - _pam_compose_pwd_restriction_string(ctx, &response); + _pam_compose_pwd_restriction_string(ctx, policy); if (pwd_restriction_string) { _make_remark(ctx, PAM_ERROR_MSG, pwd_restriction_string); TALLOC_FREE(pwd_restriction_string); } } + done: + wbcFreeMemory(error); + wbcFreeMemory(policy); return ret; } diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h index ea7055ae19..f05f2d7018 100644 --- a/source3/nsswitch/pam_winbind.h +++ b/source3/nsswitch/pam_winbind.h @@ -182,14 +182,6 @@ do { \ };\ }; -/* from samr.idl */ -#define DOMAIN_PASSWORD_COMPLEX 0x00000001 - -#define SAMR_REJECT_OTHER 0x00000000 -#define SAMR_REJECT_TOO_SHORT 0x00000001 -#define SAMR_REJECT_IN_HISTORY 0x00000002 -#define SAMR_REJECT_COMPLEXITY 0x00000005 - #define ACB_PWNOEXP 0x00000200 /* from netlogon.idl */ |