diff options
author | Simo Sorce <simo@redhat.com> | 2013-02-26 16:25:07 -0500 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-03-19 14:07:41 +0100 |
commit | 233a3c6c48972b177e60d6ef4cecfacd3cf31659 (patch) | |
tree | e67d6eaed705d8c76173af0c06b49072224460be /src/providers/ldap | |
parent | 4f2e932acd5266e9d4e3f55966baafbdbd2ae210 (diff) | |
download | sssd-233a3c6c48972b177e60d6ef4cecfacd3cf31659.tar.gz sssd-233a3c6c48972b177e60d6ef4cecfacd3cf31659.tar.bz2 sssd-233a3c6c48972b177e60d6ef4cecfacd3cf31659.zip |
Use common error facility instead of sdap_result
Simplifies and consolidates error reporting for ldap authentication paths.
Adds 3 new error codes:
ERR_CHPASS_DENIED - Used when password constraints deny password changes
ERR_ACCOUNT_EXPIRED - Account is expired
ERR_PASSWORD_EXPIRED - Password is expired
Diffstat (limited to 'src/providers/ldap')
-rw-r--r-- | src/providers/ldap/ldap_auth.c | 276 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 13 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.c | 48 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 29 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_connection.c | 152 |
5 files changed, 202 insertions, 316 deletions
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index bc91e2f7..e10c5b0e 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -86,19 +86,16 @@ static errno_t add_expired_warning(struct pam_data *pd, long exp_time) static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, struct pam_data *pd, - enum sdap_result *result, int pwd_exp_warning) { char *end; struct tm tm; time_t expire_time; int expiration_warning; - int ret; + int ret = ERR_INTERNAL; memset(&tm, 0, sizeof(tm)); - *result = SDAP_AUTH_FAILED; - end = strptime(expire_date, "%Y%m%d%H%M%SZ", &tm); if (end == NULL) { DEBUG(1, ("Kerberos expire date [%s] invalid.\n", expire_date)); @@ -124,10 +121,8 @@ static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, if (difftime(now, expire_time) > 0.0) { DEBUG(4, ("Kerberos password expired.\n")); - *result = SDAP_AUTH_PW_EXPIRED; + ret = ERR_PASSWORD_EXPIRED; } else { - *result = SDAP_AUTH_SUCCESS; - if (pwd_exp_warning >= 0) { expiration_warning = pwd_exp_warning; } else { @@ -141,14 +136,14 @@ static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, DEBUG(1, ("add_expired_warning failed.\n")); } } + ret = EOK; } - return EOK; + return ret; } static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, - struct pam_data *pd, - enum sdap_result *result) + struct pam_data *pd) { long today; long password_age; @@ -157,15 +152,13 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, if (spwd->sp_lstchg <= 0) { DEBUG(4, ("Last change day is not set, new password needed.\n")); - *result = SDAP_AUTH_PW_EXPIRED; - return EOK; + return ERR_PASSWORD_EXPIRED; } today = (long) (now / (60 * 60 *24)); password_age = today - spwd->sp_lstchg; if (password_age < 0) { DEBUG(2, ("The last password change time is in the future!.\n")); - *result = SDAP_AUTH_SUCCESS; return EOK; } @@ -174,14 +167,12 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, password_age > spwd->sp_max + spwd->sp_inact)) { DEBUG(4, ("Account expired.\n")); - *result = SDAP_ACCT_EXPIRED; - return EOK; + return ERR_ACCOUNT_EXPIRED; } if (spwd->sp_max != -1 && password_age > spwd->sp_max) { DEBUG(4, ("Password expired.\n")); - *result = SDAP_AUTH_PW_EXPIRED; - return EOK; + return ERR_PASSWORD_EXPIRED; } if (pd != NULL && spwd->sp_max != -1 && spwd->sp_warn != -1 && @@ -200,19 +191,18 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, } } - *result = SDAP_AUTH_SUCCESS; return EOK; } static errno_t check_pwexpire_ldap(struct pam_data *pd, struct sdap_ppolicy_data *ppolicy, - enum sdap_result *result, int pwd_exp_warning) { + int ret = EOK; + if (ppolicy->grace > 0 || ppolicy->expire > 0) { uint32_t *data; uint32_t *ptr; - int ret; if (pwd_exp_warning < 0) { pwd_exp_warning = 0; @@ -245,13 +235,11 @@ static errno_t check_pwexpire_ldap(struct pam_data *pd, (uint8_t*)data); if (ret != EOK) { DEBUG(1, ("pam_add_response failed.\n")); - return ret; } } done: - *result = SDAP_AUTH_SUCCESS; - return EOK; + return ret; } static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, @@ -469,7 +457,6 @@ struct auth_state { struct sdap_handle *sh; - enum sdap_result result; char *dn; enum pwexpire pw_expire_type; void *pw_expire_data; @@ -497,8 +484,7 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx, /* The token must be a password token */ if (sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PASSWORD) { - state->result = SDAP_AUTH_FAILED; - tevent_req_done(req); + tevent_req_error(req, ERR_AUTH_FAILED); return tevent_req_post(req, ev); } @@ -646,54 +632,38 @@ static void auth_bind_user_done(struct tevent_req *subreq) struct auth_state *state = tevent_req_data(req, struct auth_state); int ret; - struct sdap_ppolicy_data *ppolicy; + struct sdap_ppolicy_data *ppolicy = NULL; - ret = sdap_auth_recv(subreq, state, &state->result, &ppolicy); + ret = sdap_auth_recv(subreq, state, &ppolicy); + talloc_zfree(subreq); if (ppolicy != NULL) { DEBUG(9,("Found ppolicy data, " "assuming LDAP password policies are active.\n")); state->pw_expire_type = PWEXPIRE_LDAP_PASSWORD_POLICY; state->pw_expire_data = ppolicy; } - talloc_zfree(subreq); - if (ret != EOK) { + switch (ret) { + case EOK: + break; + case ETIMEDOUT: + case ERR_NETWORK_IO: if (auth_get_server(req) == NULL) { tevent_req_error(req, ENOMEM); } return; + default: + tevent_req_error(req, ret); + return; } tevent_req_done(req); } -int auth_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **sh, - enum sdap_result *result, char **dn, - enum pwexpire *pw_expire_type, void **pw_expire_data) +static errno_t auth_recv(struct tevent_req *req, TALLOC_CTX *memctx, + struct sdap_handle **sh, char **dn, + enum pwexpire *pw_expire_type, void **pw_expire_data) { struct auth_state *state = tevent_req_data(req, struct auth_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(req, &tstate, &err)) { - switch (tstate) { - case TEVENT_REQ_USER_ERROR: - if (err == ETIMEDOUT) { - *result = SDAP_UNAVAIL; - return EOK; - } else if (err == EACCES) { - *result = SDAP_AUTH_FAILED; - return EOK; - } else { - *result = SDAP_ERROR; - return err; - } - default: - *result = SDAP_ERROR; - return EIO; - } - } if (sh != NULL) { *sh = talloc_steal(memctx, state->sh); @@ -711,7 +681,8 @@ int auth_recv(struct tevent_req *req, *pw_expire_type = state->pw_expire_type; - *result = state->result; + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; } @@ -793,22 +764,15 @@ static void sdap_auth4chpass_done(struct tevent_req *req) tevent_req_callback_data(req, struct sdap_pam_chpass_state); struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq); struct tevent_req *subreq; - enum sdap_result result; enum pwexpire pw_expire_type; void *pw_expire_data; int dp_err = DP_ERR_FATAL; int ret; - ret = auth_recv(req, state, &state->sh, - &result, &state->dn, + ret = auth_recv(req, state, &state->sh, &state->dn, &pw_expire_type, &pw_expire_data); talloc_zfree(req); - if (ret) { - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - - if ( (result == SDAP_AUTH_SUCCESS || result == SDAP_AUTH_PW_EXPIRED ) && + if ((ret == EOK || ret == ERR_PASSWORD_EXPIRED) && state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) { DEBUG(9, ("Initial authentication for change password operation " "successful.\n")); @@ -817,46 +781,35 @@ static void sdap_auth4chpass_done(struct tevent_req *req) goto done; } - if (result == SDAP_AUTH_SUCCESS) { + if (ret == EOK) { switch (pw_expire_type) { - case PWEXPIRE_SHADOW: - ret = check_pwexpire_shadow(pw_expire_data, time(NULL), NULL, - &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_shadow failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_KERBEROS: - ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL, &result, - be_ctx->domain->pwd_expiration_warning); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_kerberos failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } + case PWEXPIRE_SHADOW: + ret = check_pwexpire_shadow(pw_expire_data, time(NULL), NULL); + break; + case PWEXPIRE_KERBEROS: + ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL, + be_ctx->domain->pwd_expiration_warning); - if (result == SDAP_AUTH_PW_EXPIRED) { - DEBUG(1, ("LDAP provider cannot change kerberos " - "passwords.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_LDAP_PASSWORD_POLICY: - case PWEXPIRE_NONE: - break; - default: - DEBUG(1, ("Unknow pasword expiration type.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; + if (ret == ERR_PASSWORD_EXPIRED) { + DEBUG(1, ("LDAP provider cannot change kerberos " + "passwords.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + break; + case PWEXPIRE_LDAP_PASSWORD_POLICY: + case PWEXPIRE_NONE: + break; + default: + DEBUG(1, ("Unknow pasword expiration type.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; } } - switch (result) { - case SDAP_AUTH_SUCCESS: - case SDAP_AUTH_PW_EXPIRED: + switch (ret) { + case EOK: + case ERR_PASSWORD_EXPIRED: DEBUG(7, ("user [%s] successfully authenticated.\n", state->dn)); if (pw_expire_type == PWEXPIRE_SHADOW) { /* TODO: implement async ldap modify request */ @@ -891,10 +844,12 @@ static void sdap_auth4chpass_done(struct tevent_req *req) return; } break; - case SDAP_AUTH_FAILED: + case ERR_AUTH_DENIED: + case ERR_AUTH_FAILED: state->pd->pam_status = PAM_AUTH_ERR; break; - case SDAP_UNAVAIL: + case ETIMEDOUT: + case ERR_NETWORK_IO: state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; be_mark_offline(be_ctx); dp_err = DP_ERR_OFFLINE; @@ -912,7 +867,6 @@ static void sdap_pam_chpass_done(struct tevent_req *req) struct sdap_pam_chpass_state *state = tevent_req_callback_data(req, struct sdap_pam_chpass_state); struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq); - enum sdap_result result; int dp_err = DP_ERR_FATAL; int ret; char *user_error_message = NULL; @@ -921,24 +875,23 @@ static void sdap_pam_chpass_done(struct tevent_req *req) size_t msg_len; uint8_t *msg; - ret = sdap_exop_modify_passwd_recv(req, state, &result, &user_error_message); + ret = sdap_exop_modify_passwd_recv(req, state, &user_error_message); talloc_zfree(req); - if (ret && ret != EIO) { - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - switch (result) { - case SDAP_SUCCESS: + switch (ret) { + case EOK: state->pd->pam_status = PAM_SUCCESS; dp_err = DP_ERR_OK; break; - case SDAP_AUTH_PW_CONSTRAINT_VIOLATION: + case ERR_CHPASS_DENIED: state->pd->pam_status = PAM_NEW_AUTHTOK_REQD; break; - default: + case ERR_NETWORK_IO: state->pd->pam_status = PAM_AUTHTOK_ERR; break; + default: + state->pd->pam_status = PAM_SYSTEM_ERR; + break; } if (state->pd->pam_status != PAM_SUCCESS && user_error_message != NULL) { @@ -1068,76 +1021,72 @@ static void sdap_pam_auth_done(struct tevent_req *req) struct sdap_pam_auth_state *state = tevent_req_callback_data(req, struct sdap_pam_auth_state); struct be_ctx *be_ctx = be_req_get_be_ctx(state->breq); - enum sdap_result result; enum pwexpire pw_expire_type; void *pw_expire_data; const char *password; int dp_err = DP_ERR_OK; int ret; - ret = auth_recv(req, state, NULL, - &result, NULL, + ret = auth_recv(req, state, NULL, NULL, &pw_expire_type, &pw_expire_data); talloc_zfree(req); - if (ret != EOK) { - state->pd->pam_status = PAM_SYSTEM_ERR; - dp_err = DP_ERR_FATAL; - goto done; - } - if (result == SDAP_AUTH_SUCCESS) { + if (ret == EOK) { switch (pw_expire_type) { - case PWEXPIRE_SHADOW: - ret = check_pwexpire_shadow(pw_expire_data, time(NULL), - state->pd, &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_shadow failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_KERBEROS: - ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), - state->pd, &result, - be_ctx->domain->pwd_expiration_warning); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_kerberos failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_LDAP_PASSWORD_POLICY: - ret = check_pwexpire_ldap(state->pd, pw_expire_data, &result, + case PWEXPIRE_SHADOW: + ret = check_pwexpire_shadow(pw_expire_data, time(NULL), state->pd); + if (ret != EOK) { + DEBUG(1, ("check_pwexpire_shadow failed.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + break; + case PWEXPIRE_KERBEROS: + ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), + state->pd, be_ctx->domain->pwd_expiration_warning); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_ldap failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_NONE: - break; - default: - DEBUG(1, ("Unknow pasword expiration type.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; + if (ret != EOK) { + DEBUG(1, ("check_pwexpire_kerberos failed.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + break; + case PWEXPIRE_LDAP_PASSWORD_POLICY: + ret = check_pwexpire_ldap(state->pd, pw_expire_data, + be_ctx->domain->pwd_expiration_warning); + if (ret != EOK) { + DEBUG(1, ("check_pwexpire_ldap failed.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + break; + case PWEXPIRE_NONE: + break; + default: + DEBUG(1, ("Unknow pasword expiration type.\n")); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; } } - switch (result) { - case SDAP_AUTH_SUCCESS: + switch (ret) { + case EOK: state->pd->pam_status = PAM_SUCCESS; break; - case SDAP_AUTH_FAILED: + case ERR_AUTH_DENIED: state->pd->pam_status = PAM_PERM_DENIED; break; - case SDAP_UNAVAIL: + case ERR_AUTH_FAILED: + state->pd->pam_status = PAM_AUTH_ERR; + break; + case ETIMEDOUT: + case ERR_NETWORK_IO: state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; break; - case SDAP_ACCT_EXPIRED: + case ERR_ACCOUNT_EXPIRED: state->pd->pam_status = PAM_ACCT_EXPIRED; break; - case SDAP_AUTH_PW_EXPIRED: + case ERR_PASSWORD_EXPIRED: state->pd->pam_status = PAM_NEW_AUTHTOK_REQD; break; default: @@ -1145,13 +1094,13 @@ static void sdap_pam_auth_done(struct tevent_req *req) dp_err = DP_ERR_FATAL; } - if (result == SDAP_UNAVAIL) { + if (ret == ETIMEDOUT || ret == ERR_NETWORK_IO) { be_mark_offline(be_ctx); dp_err = DP_ERR_OFFLINE; goto done; } - if (result == SDAP_AUTH_SUCCESS && be_ctx->domain->cache_credentials) { + if (ret == EOK && be_ctx->domain->cache_credentials) { ret = sss_authtok_get_password(&state->pd->authtok, &password, NULL); if (ret == EOK) { @@ -1167,7 +1116,6 @@ static void sdap_pam_auth_done(struct tevent_req *req) DEBUG(4, ("Password successfully cached for %s\n", state->pd->user)); } - goto done; } done: diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index d1436579..27f18ae1 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -136,19 +136,6 @@ struct sdap_ppolicy_data { #define SDAP_AD_USN "uSNChanged" #define SDAP_AD_LAST_USN "highestCommittedUSN" -enum sdap_result { - SDAP_SUCCESS, - SDAP_NOT_FOUND, - SDAP_UNAVAIL, - SDAP_RETRY, - SDAP_ERROR, - SDAP_AUTH_SUCCESS, - SDAP_AUTH_FAILED, - SDAP_AUTH_PW_EXPIRED, - SDAP_AUTH_PW_CONSTRAINT_VIOLATION, - SDAP_ACCT_EXPIRED -}; - enum sdap_basic_opt { SDAP_URI = 0, SDAP_BACKUP_URI, diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index b7d98392..7ac32b95 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -490,7 +490,6 @@ struct sdap_exop_modify_passwd_state { struct sdap_op *op; - int result; char *user_error_message; }; @@ -552,6 +551,7 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) { DEBUG(1, ("sdap_control_create failed to create " "Password Policy control.\n")); + ret = ERR_INTERNAL; goto fail; } request_controls = ctrls; @@ -564,6 +564,7 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, if (ctrls[0]) ldap_control_free(ctrls[0]); if (ret == -1 || msgid == -1) { DEBUG(1, ("ldap_extended_operation failed\n")); + ret = ERR_NETWORK_IO; goto fail; } DEBUG(8, ("ldap_extended_operation sent, msgid = %d\n", msgid)); @@ -573,13 +574,14 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, sdap_exop_modify_passwd_done, req, 5, &state->op); if (ret) { DEBUG(1, ("Failed to set up operation!\n")); + ret = ERR_INTERNAL; goto fail; } return req; fail: - tevent_req_error(req, EIO); + tevent_req_error(req, ret); tevent_req_post(req, ev); return req; } @@ -598,6 +600,7 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op, ber_int_t pp_grace; ber_int_t pp_expire; LDAPPasswordPolicyError pp_error; + int result; if (error) { tevent_req_error(req, error); @@ -605,11 +608,11 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op, } ret = ldap_parse_result(state->sh->ldap, reply->msg, - &state->result, NULL, &errmsg, NULL, + &result, NULL, &errmsg, NULL, &response_controls, 0); if (ret != LDAP_SUCCESS) { DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - ret = EIO; + ret = ERR_INTERNAL; goto done; } @@ -627,7 +630,7 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op, &pp_error); if (ret != LDAP_SUCCESS) { DEBUG(1, ("ldap_parse_passwordpolicy_control failed.\n")); - ret = EIO; + ret = ERR_NETWORK_IO; goto done; } @@ -639,9 +642,16 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op, } DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n", - sss_ldap_err2string(state->result), state->result, errmsg)); + sss_ldap_err2string(result), result, errmsg)); - if (state->result != LDAP_SUCCESS) { + switch (result) { + case LDAP_SUCCESS: + ret = EOK; + break; + case LDAP_CONSTRAINT_VIOLATION: + ret = ERR_CHPASS_DENIED; + break; + default: if (errmsg) { state->user_error_message = talloc_strdup(state, errmsg); if (state->user_error_message == NULL) { @@ -650,11 +660,10 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op, goto done; } } - ret = EIO; - goto done; + ret = ERR_NETWORK_IO; + break; } - ret = EOK; done: ldap_controls_free(response_controls); ldap_memfree(errmsg); @@ -666,28 +675,15 @@ done: } } -int sdap_exop_modify_passwd_recv(struct tevent_req *req, - TALLOC_CTX * mem_ctx, - enum sdap_result *result, - char **user_error_message) +errno_t sdap_exop_modify_passwd_recv(struct tevent_req *req, + TALLOC_CTX * mem_ctx, + char **user_error_message) { struct sdap_exop_modify_passwd_state *state = tevent_req_data(req, struct sdap_exop_modify_passwd_state); *user_error_message = talloc_steal(mem_ctx, state->user_error_message); - switch (state->result) { - case LDAP_SUCCESS: - *result = SDAP_SUCCESS; - break; - case LDAP_CONSTRAINT_VIOLATION: - *result = SDAP_AUTH_PW_CONSTRAINT_VIOLATION; - break; - default: - *result = SDAP_ERROR; - break; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 69590b9e..59269110 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -86,22 +86,6 @@ int sdap_get_netgroups_recv(struct tevent_req *req, size_t *reply_count, struct sysdb_attrs ***reply); -struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct be_ctx *be, - struct sdap_handle *sh, - const char *service_name, - int timeout, - const char *keytab, - const char *principal, - const char *realm, - bool canonicalize, - int lifetime); - -int sdap_kinit_recv(struct tevent_req *req, - enum sdap_result *result, - time_t *expire_time); - struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_handle *sh, @@ -110,10 +94,9 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *user_dn, struct sss_auth_token *authtok); -int sdap_auth_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - enum sdap_result *result, - struct sdap_ppolicy_data **ppolicy); +errno_t sdap_auth_recv(struct tevent_req *req, + TALLOC_CTX *memctx, + struct sdap_ppolicy_data **ppolicy); struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -129,9 +112,9 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, char *user_dn, const char *password, const char *new_password); -int sdap_exop_modify_passwd_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - enum sdap_result *result, - char **user_error_msg); +errno_t sdap_exop_modify_passwd_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + char **user_error_msg); struct tevent_req * sdap_modify_shadow_lastchange_send(TALLOC_CTX *mem_ctx, diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index b673daf6..d9ea4091 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -446,7 +446,6 @@ struct simple_bind_state { struct sdap_msg *reply; struct sdap_ppolicy_data *ppolicy; - int result; }; static void simple_bind_done(struct sdap_op *op, @@ -529,7 +528,7 @@ fail: if (ret == LDAP_SERVER_DOWN) { tevent_req_error(req, ETIMEDOUT); } else { - tevent_req_error(req, EIO); + tevent_req_error(req, ERR_NETWORK_IO); } tevent_req_post(req, ev); return req; @@ -544,13 +543,14 @@ static void simple_bind_done(struct sdap_op *op, struct simple_bind_state); char *errmsg = NULL; char *nval; - errno_t ret; + errno_t ret = ERR_INTERNAL; int lret; LDAPControl **response_controls; int c; ber_int_t pp_grace; ber_int_t pp_expire; LDAPPasswordPolicyError pp_error; + int result = LDAP_OTHER; if (error) { tevent_req_error(req, error); @@ -560,15 +560,21 @@ static void simple_bind_done(struct sdap_op *op, state->reply = talloc_steal(state, reply); lret = ldap_parse_result(state->sh->ldap, state->reply->msg, - &state->result, NULL, &errmsg, NULL, + &result, NULL, &errmsg, NULL, &response_controls, 0); if (lret != LDAP_SUCCESS) { DEBUG(SSSDBG_MINOR_FAILURE, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - ret = EIO; + ret = ERR_INTERNAL; goto done; } + if (result == LDAP_SUCCESS) { + ret = EOK; + } else { + ret = ERR_AUTH_FAILED; + } + if (response_controls == NULL) { DEBUG(SSSDBG_TRACE_LIBS, ("Server returned no controls.\n")); state->ppolicy = NULL; @@ -586,7 +592,7 @@ static void simple_bind_done(struct sdap_op *op, if (lret != LDAP_SUCCESS) { DEBUG(SSSDBG_MINOR_FAILURE, ("ldap_parse_passwordpolicy_control failed.\n")); - ret = EIO; + ret = ERR_INTERNAL; goto done; } @@ -602,12 +608,13 @@ static void simple_bind_done(struct sdap_op *op, } state->ppolicy->grace = pp_grace; state->ppolicy->expire = pp_expire; - if (state->result == LDAP_SUCCESS) { + if (result == LDAP_SUCCESS) { + if (pp_error == PP_changeAfterReset) { DEBUG(SSSDBG_TRACE_LIBS, ("Password was reset. " "User must set a new password.\n")); - state->result = LDAP_X_SSSD_PASSWORD_EXPIRED; + ret = ERR_PASSWORD_EXPIRED; } else if (pp_grace > 0) { DEBUG(SSSDBG_TRACE_LIBS, ("Password expired. " @@ -618,17 +625,17 @@ static void simple_bind_done(struct sdap_op *op, ("Password will expire in [%d] seconds.\n", pp_expire)); } - } else if (state->result == LDAP_INVALID_CREDENTIALS && + } else if (result == LDAP_INVALID_CREDENTIALS && pp_error == PP_passwordExpired) { DEBUG(SSSDBG_TRACE_LIBS, ("Password expired user must set a new password.\n")); - state->result = LDAP_X_SSSD_PASSWORD_EXPIRED; + ret = ERR_PASSWORD_EXPIRED; } } else if (strcmp(response_controls[c]->ldctl_oid, LDAP_CONTROL_PWEXPIRED) == 0) { DEBUG(SSSDBG_TRACE_LIBS, ("Password expired user must set a new password.\n")); - state->result = LDAP_X_SSSD_PASSWORD_EXPIRED; + ret = ERR_PASSWORD_EXPIRED; } else if (strcmp(response_controls[c]->ldctl_oid, LDAP_CONTROL_PWEXPIRING) == 0) { /* ignore controls with suspiciously long values */ @@ -670,10 +677,13 @@ static void simple_bind_done(struct sdap_op *op, } DEBUG(SSSDBG_TRACE_FUNC, ("Bind result: %s(%d), %s\n", - sss_ldap_err2string(state->result), state->result, + sss_ldap_err2string(result), result, errmsg ? errmsg : "no errmsg set")); - ret = EOK; + if (result != LDAP_SUCCESS && ret == EOK) { + ret = ERR_AUTH_FAILED; + } + done: ldap_controls_free(response_controls); ldap_memfree(errmsg); @@ -685,19 +695,19 @@ done: } } -static int simple_bind_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - int *ldaperr, - struct sdap_ppolicy_data **ppolicy) +static errno_t simple_bind_recv(struct tevent_req *req, + TALLOC_CTX *memctx, + struct sdap_ppolicy_data **ppolicy) { struct simple_bind_state *state = tevent_req_data(req, struct simple_bind_state); - *ldaperr = LDAP_OTHER; + if (ppolicy != NULL) { + *ppolicy = talloc_steal(memctx, state->ppolicy); + } + TEVENT_REQ_RETURN_ON_ERROR(req); - *ldaperr = state->result; - *ppolicy = talloc_steal(memctx, state->ppolicy); return EOK; } @@ -710,8 +720,6 @@ struct sasl_bind_state { const char *sasl_mech; const char *sasl_user; struct berval *sasl_cred; - - int result; }; static int sdap_sasl_interact(LDAP *ld, unsigned flags, @@ -749,7 +757,6 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx, sasl_mech, NULL, NULL, LDAP_SASL_QUIET, (*sdap_sasl_interact), state); - state->result = ret; if (ret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_sasl_bind failed (%d)[%s]\n", @@ -771,14 +778,20 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx, if (ret) goto fail; } + /* This is a hack, relies on the fact that tevent_req_done() will always + * set the state but will not complain if no callback has been set. + * tevent_req_post() will only set the immediate event and then just call + * the async callback set by the caller right after we return using the + * state value set previously by tevent_req_done() */ + tevent_req_done(req); tevent_req_post(req, ev); return req; fail: - if (ret == LDAP_SERVER_DOWN) { + if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) { tevent_req_error(req, ETIMEDOUT); } else { - tevent_req_error(req, EIO); + tevent_req_error(req, ERR_AUTH_FAILED); } tevent_req_post(req, ev); return req; @@ -830,21 +843,10 @@ fail: return LDAP_UNAVAILABLE; } -static int sasl_bind_recv(struct tevent_req *req, int *ldaperr) +static errno_t sasl_bind_recv(struct tevent_req *req) { - struct sasl_bind_state *state = tevent_req_data(req, - struct sasl_bind_state); - enum tevent_req_state tstate; - uint64_t err = EIO; - - if (tevent_req_is_error(req, &tstate, &err)) { - if (tstate != TEVENT_REQ_IN_PROGRESS) { - *ldaperr = LDAP_OTHER; - return err; - } - } + TEVENT_REQ_RETURN_ON_ERROR(req); - *ldaperr = state->result; return EOK; } @@ -862,7 +864,6 @@ struct sdap_kinit_state { struct be_ctx *be; struct fo_server *kdc_srv; - int result; time_t expire_time; }; @@ -870,6 +871,7 @@ static void sdap_kinit_done(struct tevent_req *subreq); static struct tevent_req *sdap_kinit_next_kdc(struct tevent_req *req); static void sdap_kinit_kdc_resolved(struct tevent_req *subreq); +static struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct be_ctx *be, @@ -899,7 +901,6 @@ struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx, req = tevent_req_create(memctx, &state, struct sdap_kinit_state); if (!req) return NULL; - state->result = SDAP_AUTH_FAILED; state->keytab = keytab; state->principal = principal; state->realm = realm; @@ -974,7 +975,7 @@ static void sdap_kinit_kdc_resolved(struct tevent_req *subreq) if (ret != EOK) { /* all servers have been tried and none * was found good, go offline */ - tevent_req_error(req, EIO); + tevent_req_error(req, ERR_NETWORK_IO); return; } @@ -1021,7 +1022,6 @@ static void sdap_kinit_done(struct tevent_req *subreq) return; } else if (ret != EOK) { /* A severe error while executing the child. Abort the operation. */ - state->result = SDAP_AUTH_FAILED; DEBUG(1, ("child failed (%d [%s])\n", ret, strerror(ret))); tevent_req_error(req, ret); return; @@ -1031,12 +1031,10 @@ static void sdap_kinit_done(struct tevent_req *subreq) ret = setenv("KRB5CCNAME", ccname, 1); if (ret == -1) { DEBUG(2, ("Unable to set env. variable KRB5CCNAME!\n")); - state->result = SDAP_AUTH_FAILED; - tevent_req_error(req, EFAULT); + tevent_req_error(req, ERR_AUTH_FAILED); } state->expire_time = expire_time; - state->result = SDAP_AUTH_SUCCESS; tevent_req_done(req); return; } else { @@ -1052,28 +1050,24 @@ static void sdap_kinit_done(struct tevent_req *subreq) } - DEBUG(4, ("Could not get TGT: %d [%s]\n", result, strerror(result))); - state->result = SDAP_AUTH_FAILED; - tevent_req_error(req, EIO); + DEBUG(4, ("Could not get TGT: %d [%s]\n", result, sss_strerror(result))); + tevent_req_error(req, ERR_AUTH_FAILED); } -int sdap_kinit_recv(struct tevent_req *req, - enum sdap_result *result, - time_t *expire_time) +static errno_t sdap_kinit_recv(struct tevent_req *req, + time_t *expire_time) { struct sdap_kinit_state *state = tevent_req_data(req, struct sdap_kinit_state); enum tevent_req_state tstate; - uint64_t err = EIO; + uint64_t err = ERR_INTERNAL; if (tevent_req_is_error(req, &tstate, &err)) { if (tstate != TEVENT_REQ_IN_PROGRESS) { - *result = SDAP_ERROR; return err; } } - *result = state->result; *expire_time = state->expire_time; return EOK; } @@ -1084,7 +1078,6 @@ int sdap_kinit_recv(struct tevent_req *req, struct sdap_auth_state { struct sdap_ppolicy_data *ppolicy; bool is_sasl; - int result; }; static void sdap_auth_done(struct tevent_req *subreq); @@ -1171,46 +1164,31 @@ static void sdap_auth_done(struct tevent_req *subreq) int ret; if (state->is_sasl) { - ret = sasl_bind_recv(subreq, &state->result); + ret = sasl_bind_recv(subreq); state->ppolicy = NULL; } else { - ret = simple_bind_recv(subreq, state, &state->result, &state->ppolicy); + ret = simple_bind_recv(subreq, state, &state->ppolicy); } - if (ret != EOK) { - tevent_req_error(req, ret); + + if (tevent_req_error(req, ret)) { return; } tevent_req_done(req); } -int sdap_auth_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - enum sdap_result *result, - struct sdap_ppolicy_data **ppolicy) +errno_t sdap_auth_recv(struct tevent_req *req, + TALLOC_CTX *memctx, + struct sdap_ppolicy_data **ppolicy) { struct sdap_auth_state *state = tevent_req_data(req, struct sdap_auth_state); - *result = SDAP_ERROR; - TEVENT_REQ_RETURN_ON_ERROR(req); - if (ppolicy != NULL) { *ppolicy = talloc_steal(memctx, state->ppolicy); } - switch (state->result) { - case LDAP_SUCCESS: - *result = SDAP_AUTH_SUCCESS; - break; - case LDAP_INVALID_CREDENTIALS: - *result = SDAP_AUTH_FAILED; - break; - case LDAP_X_SSSD_PASSWORD_EXPIRED: - *result = SDAP_AUTH_PW_EXPIRED; - break; - default: - break; - } + + TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -1564,17 +1542,16 @@ static void sdap_cli_kinit_done(struct tevent_req *subreq) struct tevent_req); struct sdap_cli_connect_state *state = tevent_req_data(req, struct sdap_cli_connect_state); - enum sdap_result result; time_t expire_time; - int ret; + errno_t ret; - ret = sdap_kinit_recv(subreq, &result, &expire_time); + ret = sdap_kinit_recv(subreq, &expire_time); talloc_zfree(subreq); - if (ret != EOK || result != SDAP_AUTH_SUCCESS) { + if (ret != EOK) { /* We're not able to authenticate to the LDAP server. * There's not much we can do except for going offline */ DEBUG(SSSDBG_TRACE_FUNC, - ("Cannot get a TGT: ret [%d] result [%d]\n", ret, result)); + ("Cannot get a TGT: ret [%d](%s)\n", ret, sss_strerror(ret))); tevent_req_error(req, EACCES); return; } @@ -1660,19 +1637,14 @@ static void sdap_cli_auth_done(struct tevent_req *subreq) struct tevent_req); struct sdap_cli_connect_state *state = tevent_req_data(req, struct sdap_cli_connect_state); - enum sdap_result result; int ret; - ret = sdap_auth_recv(subreq, NULL, &result, NULL); + ret = sdap_auth_recv(subreq, NULL, NULL); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); return; } - if (result != SDAP_AUTH_SUCCESS) { - tevent_req_error(req, EACCES); - return; - } if (state->use_rootdse && !state->rootdse) { /* We weren't able to read rootDSE during unauthenticated bind. |