summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2008-08-15 02:34:22 +0200
committerGünther Deschner <gd@samba.org>2008-10-10 15:40:23 +0200
commit3eae89dd7729c08a40d97dc1b095011bf2933dce (patch)
tree62cd0f5d09fa860cae4557f14e18228c5b7769d1
parented2b94c1a29017013a8eb773755c051f4c2a2eb0 (diff)
downloadsamba-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.c144
-rw-r--r--source3/nsswitch/pam_winbind.h8
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(&params, &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 */