mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
pam_winbind: use libwbclient for WINBINDD_PAM_CHAUTHTOK.
Guenther
This commit is contained in:
parent
ed2b94c1a2
commit
3eae89dd77
@ -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;
|
||||
wbcErr wbc_status;
|
||||
struct wbcChangePasswordParams params;
|
||||
struct wbcAuthErrorInfo *error = NULL;
|
||||
struct wbcUserPasswordPolicyInfo *policy = NULL;
|
||||
enum wbcPasswordChangeRejectReason reject_reason = -1;
|
||||
uint32_t flags = 0;
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
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 (request.data.chauthtok.user == NULL) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
strncpy(request.data.chauthtok.user, user,
|
||||
sizeof(request.data.chauthtok.user) - 1);
|
||||
|
||||
if (oldpass != NULL) {
|
||||
strncpy(request.data.chauthtok.oldpass, oldpass,
|
||||
sizeof(request.data.chauthtok.oldpass) - 1);
|
||||
} else {
|
||||
request.data.chauthtok.oldpass[0] = '\0';
|
||||
}
|
||||
|
||||
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);
|
||||
params.account_name = user;
|
||||
params.level = WBC_AUTH_USER_LEVEL_PLAIN;
|
||||
params.old_password.plaintext = oldpass;
|
||||
params.new_password.plaintext = newpass;
|
||||
params.flags = flags;
|
||||
|
||||
if (ret == PAM_SUCCESS) {
|
||||
wbc_status = wbcChangeUserPasswordEx(¶ms, &error, &reject_reason, &policy);
|
||||
ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status,
|
||||
user, "wbcChangeUserPasswordEx");
|
||||
|
||||
if (WBC_ERROR_IS_OK(wbc_status)) {
|
||||
_pam_log(ctx, LOG_NOTICE,
|
||||
"user '%s' password changed", user);
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
wbcFreeMemory(policy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: tell the min pwd length ? */
|
||||
PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response,
|
||||
"NT_STATUS_PWD_TOO_SHORT");
|
||||
|
||||
/* TODO: tell the minage ? */
|
||||
PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response,
|
||||
"NT_STATUS_PWD_TOO_RECENT");
|
||||
|
||||
/* TODO: tell the history length ? */
|
||||
PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response,
|
||||
"NT_STATUS_PWD_HISTORY_CONFLICT");
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user