diff options
Diffstat (limited to 'server/providers/ldap/ldap_auth.c')
| -rw-r--r-- | server/providers/ldap/ldap_auth.c | 1055 | 
1 files changed, 0 insertions, 1055 deletions
| diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c deleted file mode 100644 index cfe8adb9..00000000 --- a/server/providers/ldap/ldap_auth.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* -    SSSD - -    LDAP Backend Module - -    Authors: -        Sumit Bose <sbose@redhat.com> - -    Copyright (C) 2008 Red Hat - -    This program is free software; you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation; either version 3 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - -    You should have received a copy of the GNU General Public License -    along with this program.  If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifdef WITH_MOZLDAP -#define LDAP_OPT_SUCCESS LDAP_SUCCESS -#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID  ((ber_tag_t) 0x80U) -#define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U) -#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) -#endif - -#define _XOPEN_SOURCE 500 /* for strptime() */ -#include <time.h> -#undef _XOPEN_SOURCE -#include <errno.h> -#include <sys/time.h> -#include <strings.h> - -#include <shadow.h> -#include <security/pam_modules.h> - -#include "util/util.h" -#include "util/user_info_msg.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -enum pwexpire { -    PWEXPIRE_NONE = 0, -    PWEXPIRE_LDAP_PASSWORD_POLICY, -    PWEXPIRE_KERBEROS, -    PWEXPIRE_SHADOW -}; - -static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, -                                       enum sdap_result *result) -{ -    char *end; -    struct tm tm = {0, 0, 0, 0, 0, 0, 0, 0, 0}; -    time_t expire_time; - -    *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)); -        return EINVAL; -    } -    if (*end != '\0') { -        DEBUG(1, ("Kerberos expire date [%s] contains extra characters.\n", -                  expire_date)); -        return EINVAL; -    } - -    expire_time = mktime(&tm); -    if (expire_time == -1) { -        DEBUG(1, ("mktime failed to convert [%s].\n", expire_date)); -        return EINVAL; -    } - -    tzset(); -    expire_time -= timezone; -    DEBUG(9, ("Time info: tzname[0] [%s] tzname[1] [%s] timezone [%d] " -              "daylight [%d] now [%d] expire_time [%d].\n", tzname[0], -              tzname[1], timezone, daylight, now, expire_time)); - -    if (difftime(now, expire_time) > 0.0) { -        DEBUG(4, ("Kerberos password expired.\n")); -        *result = SDAP_AUTH_PW_EXPIRED; -    } else { -        *result = SDAP_AUTH_SUCCESS; -    } - -    return EOK; -} - -static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, -                                     enum sdap_result *result) -{ -    long today; -    long password_age; - -    if (spwd->sp_lstchg <= 0) { -        DEBUG(4, ("Last change day is not set, new password needed.\n")); -        *result = SDAP_AUTH_PW_EXPIRED; -        return EOK; -    } - -    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; -    } - -    if ((spwd->sp_expire != -1 && today > spwd->sp_expire) || -        (spwd->sp_max != -1 && spwd->sp_inact != -1 && -         password_age > spwd->sp_max + spwd->sp_inact)) -    { -        DEBUG(4, ("Account expired.\n")); -        *result = SDAP_ACCT_EXPIRED; -        return EOK; -    } - -    if (spwd->sp_max != -1 && password_age > spwd->sp_max) { -        DEBUG(4, ("Password expired.\n")); -        *result = SDAP_AUTH_PW_EXPIRED; -        return EOK; -    } - -/* TODO: evaluate spwd->min and spwd->warn */ - -    *result = SDAP_AUTH_SUCCESS; -    return EOK; -} - -static errno_t string_to_shadowpw_days(const char *s, long *d) -{ -    long l; -    char *endptr; - -    if (s == NULL || *s == '\0') { -        *d = -1; -        return EOK; -    } - -    errno = 0; -    l = strtol(s, &endptr, 10); -    if (errno != 0) { -        DEBUG(1, ("strtol failed [%d][%s].\n", errno, strerror(errno))); -        return errno; -    } - -    if (*endptr != '\0') { -        DEBUG(1, ("Input string [%s] is invalid.\n", s)); -        return EINVAL; -    } - -    if (*d < -1) { -        DEBUG(1, ("Input string contains not allowed negative value [%d].\n", -                  *d)); -        return EINVAL; -    } - -    *d = l; - -    return EOK; -} - -static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, -                                               const struct ldb_message *msg, -                                               struct dp_option *opts, -                                               enum pwexpire *type, void **data) -{ -    const char *mark; -    const char *val; -    struct spwd *spwd; -    const char *pwd_policy; -    int ret; - -    *type = PWEXPIRE_NONE; -    *data = NULL; - -    pwd_policy = dp_opt_get_string(opts, SDAP_PWD_POLICY); -    if (pwd_policy == NULL) { -        DEBUG(1, ("Missing password policy.\n")); -        return EINVAL; -    } - -    mark = ldb_msg_find_attr_as_string(msg, SYSDB_PWD_ATTRIBUTE, NULL); -    if (mark != NULL) { -        DEBUG(9, ("Found pwdAttribute, " -                  "assuming LDAP password policies are active.\n")); - -        *type = PWEXPIRE_LDAP_PASSWORD_POLICY; -        return EOK; -    } - -    if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) == 0) { -        DEBUG(9, ("No password policy requested.\n")); -        return EOK; -    } else if (strcasecmp(pwd_policy, PWD_POL_OPT_MIT) == 0) { -        mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL); -        if (mark != NULL) { -            DEBUG(9, ("Found Kerberos password expiration attributes.\n")) -            val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION, -                                              NULL); -            if (val != NULL) { -                *data = talloc_strdup(mem_ctx, val); -                if (*data == NULL) { -                    DEBUG(1, ("talloc_strdup failed.\n")); -                    return ENOMEM; -                } -                *type = PWEXPIRE_KERBEROS; - -                return EOK; -            } -        } else { -            DEBUG(1, ("No Kerberos password expiration attributes found, " -                      "but MIT Kerberos password policy was requested.\n")); -            return EINVAL; -        } -    } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) { -        mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); -        if (mark != NULL) { -            DEBUG(9, ("Found shadow password expiration attributes.\n")) -            spwd = talloc_zero(mem_ctx, struct spwd); -            if (spwd == NULL) { -                DEBUG(1, ("talloc failed.\n")); -                return ENOMEM; -            } - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_lstchg); -            if (ret != EOK) goto shadow_fail; - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_min); -            if (ret != EOK) goto shadow_fail; - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_max); -            if (ret != EOK) goto shadow_fail; - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_warn); -            if (ret != EOK) goto shadow_fail; - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_inact); -            if (ret != EOK) goto shadow_fail; - -            val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL); -            ret = string_to_shadowpw_days(val, &spwd->sp_expire); -            if (ret != EOK) goto shadow_fail; - -            *data = spwd; -            *type = PWEXPIRE_SHADOW; - -            return EOK; -        } else { -            DEBUG(1, ("No shadow password attributes found, " -                      "but shadow password policy was requested.\n")); -            return EINVAL; -        } -    } - -    DEBUG(9, ("No password expiration attributes found.\n")); -    return EOK; - -shadow_fail: -        talloc_free(spwd); -        return ret; -} - -/* ==Get-User-DN========================================================== */ - -struct get_user_dn_state { -    struct tevent_context *ev; -    struct sdap_auth_ctx *ctx; -    struct sdap_handle *sh; - -    const char **attrs; -    const char *name; - -    char *dn; -    enum pwexpire pw_expire_type; -    void *pw_expire_data; -}; - -static void get_user_dn_done(void *pvt, int err, struct ldb_result *res); - -struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, -                                    struct tevent_context *ev, -                                    struct sdap_auth_ctx *ctx, -                                    struct sdap_handle *sh, -                                    const char *username) -{ -    struct tevent_req *req; -    struct get_user_dn_state *state; -    int ret; - -    req = tevent_req_create(memctx, &state, struct get_user_dn_state); -    if (!req) return NULL; - -    state->ev = ev; -    state->ctx = ctx; -    state->sh = sh; -    state->name = username; - -    state->attrs = talloc_array(state, const char *, 11); -    if (!state->attrs) { -        talloc_zfree(req); -        return NULL; -    } -    state->attrs[0] = SYSDB_ORIG_DN; -    state->attrs[1] = SYSDB_SHADOWPW_LASTCHANGE; -    state->attrs[2] = SYSDB_SHADOWPW_MIN; -    state->attrs[3] = SYSDB_SHADOWPW_MAX; -    state->attrs[4] = SYSDB_SHADOWPW_WARNING; -    state->attrs[5] = SYSDB_SHADOWPW_INACTIVE; -    state->attrs[6] = SYSDB_SHADOWPW_EXPIRE; -    state->attrs[7] = SYSDB_KRBPW_LASTCHANGE; -    state->attrs[8] = SYSDB_KRBPW_EXPIRATION; -    state->attrs[9] = SYSDB_PWD_ATTRIBUTE; -    state->attrs[10] = NULL; - -    /* this sysdb call uses a sysdn operation, which means it will be -     * schedule only after we return, no timer hack needed */ -    ret = sysdb_get_user_attr(state, state->ctx->be->sysdb, -                              state->ctx->be->domain, state->name, -                              state->attrs, get_user_dn_done, req); -    if (ret) { -        tevent_req_error(req, ret); -        tevent_req_post(req, ev); -    } - -    return req; -} - -static void get_user_dn_done(void *pvt, int err, struct ldb_result *res) -{ -    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); -    struct get_user_dn_state *state = tevent_req_data(req, -                                           struct get_user_dn_state); -    const char *dn; -    int ret; - -    if (err != LDB_SUCCESS) { -        tevent_req_error(req, EIO); -        return; -    } - -    switch (res->count) { -    case 0: -        /* FIXME: not in cache, needs a true search */ -        tevent_req_error(req, ENOENT); -        break; - -    case 1: -        dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL); -        if (!dn) { -            /* TODO: try to search ldap server ? */ - -            /* FIXME: remove once we store originalDN on every call -             * NOTE: this is wrong, works only with some DITs */ -            dn = talloc_asprintf(state, "%s=%s,%s", -                        state->ctx->opts->user_map[SDAP_AT_USER_NAME].name, -                        state->name, -                        dp_opt_get_string(state->ctx->opts->basic, -                                          SDAP_USER_SEARCH_BASE)); -            if (!dn) { -                tevent_req_error(req, ENOMEM); -                break; -            } -        } - -        state->dn = talloc_strdup(state, dn); -        if (!state->dn) { -            tevent_req_error(req, ENOMEM); -            break; -        } - -        ret = find_password_expiration_attributes(state, res->msgs[0], -                                                  state->ctx->opts->basic, -                                                  &state->pw_expire_type, -                                                  &state->pw_expire_data); -        if (ret != EOK) { -            DEBUG(1, ("find_password_expiration_attributes failed.\n")); -            tevent_req_error(req, ENOMEM); -            break; -        } - -        tevent_req_done(req); -        break; - -    default: -        DEBUG(1, ("A user search by name (%s) returned > 1 results!\n", -                  state->name)); -        tevent_req_error(req, EFAULT); -        break; -    } -} - -static int get_user_dn_recv(struct tevent_req *req, -                            TALLOC_CTX *memctx, char **dn, -                            enum pwexpire *pw_expire_type, -                            void **pw_expire_data) -{ -    struct get_user_dn_state *state = tevent_req_data(req, -                                           struct get_user_dn_state); - -    TEVENT_REQ_RETURN_ON_ERROR(req); - -    *dn = talloc_steal(memctx, state->dn); -    if (!*dn) return ENOMEM; - -    /* state->pw_expire_data may be NULL */ -    *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); - -    *pw_expire_type = state->pw_expire_type; - -    return EOK; -} - -/* ==Authenticate-User==================================================== */ - -struct auth_state { -    struct tevent_context *ev; -    struct sdap_auth_ctx *ctx; -    const char *username; -    struct dp_opt_blob password; - -    struct sdap_handle *sh; - -    enum sdap_result result; -    char *dn; -    enum pwexpire pw_expire_type; -    void *pw_expire_data; - -    struct fo_server *srv; -}; - -static void auth_resolve_done(struct tevent_req *subreq); -static void auth_connect_done(struct tevent_req *subreq); -static void auth_get_user_dn_done(struct tevent_req *subreq); -static void auth_bind_user_done(struct tevent_req *subreq); - -static struct tevent_req *auth_send(TALLOC_CTX *memctx, -                                    struct tevent_context *ev, -                                    struct sdap_auth_ctx *ctx, -                                    const char *username, -                                    struct dp_opt_blob password) -{ -    struct tevent_req *req, *subreq; -    struct auth_state *state; - -    req = tevent_req_create(memctx, &state, struct auth_state); -    if (!req) return NULL; - -    state->ev = ev; -    state->ctx = ctx; -    state->username = username; -    state->password = password; -    state->srv = NULL; - -    subreq = be_resolve_server_send(state, ev, ctx->be, ctx->service->name); -    if (!subreq) goto fail; - -    tevent_req_set_callback(subreq, auth_resolve_done, req); - -    return req; - -fail: -    talloc_zfree(req); -    return NULL; -} - -static void auth_resolve_done(struct tevent_req *subreq) -{ -    struct tevent_req *req = tevent_req_callback_data(subreq, -                                                      struct tevent_req); -    struct auth_state *state = tevent_req_data(req, -                                                    struct auth_state); -    int ret; - -    ret = be_resolve_server_recv(subreq, &state->srv); -    talloc_zfree(subreq); -    if (ret) { -        tevent_req_error(req, ret); -        return; -    } - -    subreq = sdap_connect_send(state, state->ev, state->ctx->opts, -                               state->ctx->service->uri, true); -    if (!subreq) { -        tevent_req_error(req, ENOMEM); -        return; -    } - -    tevent_req_set_callback(subreq, auth_connect_done, req); -} - -static void auth_connect_done(struct tevent_req *subreq) -{ -    struct tevent_req *req = tevent_req_callback_data(subreq, -                                                      struct tevent_req); -    struct auth_state *state = tevent_req_data(req, -                                                    struct auth_state); -    int ret; - -    ret = sdap_connect_recv(subreq, state, &state->sh); -    talloc_zfree(subreq); -    if (ret) { -        if (state->srv) { -            /* mark this server as bad if connection failed */ -            fo_set_port_status(state->srv, PORT_NOT_WORKING); -        } - -        tevent_req_error(req, ret); -        return; -    } else if (state->srv) { -        fo_set_port_status(state->srv, PORT_WORKING); -    } - -    subreq = get_user_dn_send(state, state->ev, -                              state->ctx, state->sh, -                              state->username); -    if (!subreq) { -        tevent_req_error(req, ENOMEM); -        return; -    } - -    tevent_req_set_callback(subreq, auth_get_user_dn_done, req); -} - -static void auth_get_user_dn_done(struct tevent_req *subreq) -{ -    struct tevent_req *req = tevent_req_callback_data(subreq, -                                                      struct tevent_req); -    struct auth_state *state = tevent_req_data(req, -                                                    struct auth_state); -    int ret; - -    ret = get_user_dn_recv(subreq, state, &state->dn, &state->pw_expire_type, -                           &state->pw_expire_data); -    talloc_zfree(subreq); -    if (ret) { -        tevent_req_error(req, ret); -        return; -    } - -    subreq = sdap_auth_send(state, state->ev, state->sh, -                            NULL, NULL, state->dn, -                            "password", state->password); -    if (!subreq) { -        tevent_req_error(req, ENOMEM); -        return; -    } - -    tevent_req_set_callback(subreq, auth_bind_user_done, req); -} - -static void auth_bind_user_done(struct tevent_req *subreq) -{ -    struct tevent_req *req = tevent_req_callback_data(subreq, -                                                      struct tevent_req); -    struct auth_state *state = tevent_req_data(req, -                                                    struct auth_state); -    int ret; - -    ret = sdap_auth_recv(subreq, &state->result); -    talloc_zfree(subreq); -    if (ret) { -        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) -{ -    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; -            else *result = SDAP_ERROR; -            return err; -        default: -            *result = SDAP_ERROR; -            return EIO; -        } -    } - -    if (sh != NULL) { -        *sh = talloc_steal(memctx, state->sh); -        if (*sh == NULL) return ENOMEM; -    } - -    if (dn != NULL) { -        *dn = talloc_steal(memctx, state->dn); -        if (*dn == NULL) return ENOMEM; -    } - -    if (pw_expire_data != NULL) { -        *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); -    } - -    *pw_expire_type = state->pw_expire_type; - -    *result = state->result; -    return EOK; -} - -/* ==Perform-Password-Change===================== */ - -struct sdap_pam_chpass_state { -    struct be_req *breq; -    struct pam_data *pd; -    const char *username; -    char *dn; -    char *password; -    char *new_password; -    struct sdap_handle *sh; -}; - -static void sdap_auth4chpass_done(struct tevent_req *req); -static void sdap_pam_chpass_done(struct tevent_req *req); -static void sdap_pam_auth_reply(struct be_req *breq, int dp_err, int result); - -void sdap_pam_chpass_handler(struct be_req *breq) -{ -    struct sdap_pam_chpass_state *state; -    struct sdap_auth_ctx *ctx; -    struct tevent_req *subreq; -    struct pam_data *pd; -    struct dp_opt_blob authtok; -    int dp_err = DP_ERR_FATAL; - -    ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data, -                          struct sdap_auth_ctx); -    pd = talloc_get_type(breq->req_data, struct pam_data); - -    if (be_is_offline(ctx->be)) { -        DEBUG(4, ("Backend is marked offline, retry later!\n")); -        pd->pam_status = PAM_AUTHINFO_UNAVAIL; -        dp_err = DP_ERR_OFFLINE; -        goto done; -    } - -    DEBUG(2, ("starting password change request for user [%s].\n", pd->user)); - -    pd->pam_status = PAM_SYSTEM_ERR; - -    if (pd->cmd != SSS_PAM_CHAUTHTOK && pd->cmd != SSS_PAM_CHAUTHTOK_PRELIM) { -        DEBUG(2, ("chpass target was called by wrong pam command.\n")); -        goto done; -    } - -    state = talloc_zero(breq, struct sdap_pam_chpass_state); -    if (!state) goto done; - -    state->breq = breq; -    state->pd = pd; -    state->username = pd->user; -    state->password = talloc_strndup(state, -                                     (char *)pd->authtok, pd->authtok_size); -    if (!state->password) goto done; -    talloc_set_destructor((TALLOC_CTX *)state->password, -                          password_destructor); - -    if (pd->cmd == SSS_PAM_CHAUTHTOK) { -        state->new_password = talloc_strndup(state, -                                             (char *)pd->newauthtok, -                                             pd->newauthtok_size); -        if (!state->new_password) goto done; -        talloc_set_destructor((TALLOC_CTX *)state->new_password, -                              password_destructor); -    } - -    authtok.data = (uint8_t *)state->password; -    authtok.length = strlen(state->password); -    subreq = auth_send(breq, breq->be_ctx->ev, -                       ctx, state->username, authtok); -    if (!subreq) goto done; - -    tevent_req_set_callback(subreq, sdap_auth4chpass_done, state); -    return; - -done: -    sdap_pam_auth_reply(breq, dp_err, pd->pam_status); -} - -static void sdap_auth4chpass_done(struct tevent_req *req) -{ -    struct sdap_pam_chpass_state *state = -                    tevent_req_callback_data(req, struct sdap_pam_chpass_state); -    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, -                    &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 && -        state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) { -        DEBUG(9, ("Initial authentication for change password operation " -                  "successful.\n")); -        state->pd->pam_status = PAM_SUCCESS; -        goto done; -    } - -    if (result == SDAP_AUTH_SUCCESS) { -        switch (pw_expire_type) { -            case PWEXPIRE_SHADOW: -                ret = check_pwexpire_shadow(pw_expire_data, time(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), -                                              &result); -                if (ret != EOK) { -                    DEBUG(1, ("check_pwexpire_kerberos failed.\n")); -                    state->pd->pam_status = PAM_SYSTEM_ERR; -                    goto done; -                } - -                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; -        } -    } - -    switch (result) { -    case SDAP_AUTH_SUCCESS: -    case SDAP_AUTH_PW_EXPIRED: -        DEBUG(7, ("user [%s] successfully authenticated.\n", state->dn)); -        if (pw_expire_type == PWEXPIRE_SHADOW) { -/* TODO: implement async ldap modify request */ -            DEBUG(1, ("Changing shadow password attributes not implemented.\n")); -            state->pd->pam_status = PAM_MODULE_UNKNOWN; -            goto done; -        } else { -            subreq = sdap_exop_modify_passwd_send(state, -                                                  state->breq->be_ctx->ev, -                                                  state->sh, -                                                  state->dn, -                                                  state->password, -                                                  state->new_password); - -            if (!subreq) { -                DEBUG(2, ("Failed to change password for %s\n", state->username)); -                goto done; -            } - -            tevent_req_set_callback(subreq, sdap_pam_chpass_done, state); -            return; -        } -        break; -    case SDAP_AUTH_FAILED: -        state->pd->pam_status = PAM_AUTH_ERR; -        break; -    default: -        state->pd->pam_status = PAM_SYSTEM_ERR; -    } - -done: -    sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} - -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); -    enum sdap_result result; -    int dp_err = DP_ERR_FATAL; -    int ret; -    char *user_error_message = NULL; -    size_t msg_len; -    uint8_t *msg; - -    ret = sdap_exop_modify_passwd_recv(req, state, &result, &user_error_message); -    talloc_zfree(req); -    if (ret) { -        state->pd->pam_status = PAM_SYSTEM_ERR; -        goto done; -    } - -    switch (result) { -    case SDAP_SUCCESS: -        state->pd->pam_status = PAM_SUCCESS; -        dp_err = DP_ERR_OK; -        break; -    default: -        state->pd->pam_status = PAM_AUTHTOK_ERR; -        if (user_error_message != NULL) { -            ret = pack_user_info_chpass_error(state->pd, user_error_message, -                                              &msg_len, &msg); -            if (ret != EOK) { -                DEBUG(1, ("pack_user_info_chpass_error failed.\n")); -            } else { -                ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len, -                                       msg); -                if (ret != EOK) { -                    DEBUG(1, ("pam_add_response failed.\n")); -                } -            } -        } -    } - -done: -    sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} -/* ==Perform-User-Authentication-and-Password-Caching===================== */ - -struct sdap_pam_auth_state { -    struct be_req *breq; -    struct pam_data *pd; -    const char *username; -    struct dp_opt_blob password; -}; - -static void sdap_pam_auth_done(struct tevent_req *req); -static void sdap_password_cache_done(struct tevent_req *req); - -void sdap_pam_auth_handler(struct be_req *breq) -{ -    struct sdap_pam_auth_state *state; -    struct sdap_auth_ctx *ctx; -    struct tevent_req *subreq; -    struct pam_data *pd; -    int dp_err = DP_ERR_FATAL; - -    ctx = talloc_get_type(breq->be_ctx->bet_info[BET_AUTH].pvt_bet_data, -                          struct sdap_auth_ctx); -    pd = talloc_get_type(breq->req_data, struct pam_data); - -    if (be_is_offline(ctx->be)) { -        DEBUG(4, ("Backend is marked offline, retry later!\n")); -        pd->pam_status = PAM_AUTHINFO_UNAVAIL; -        dp_err = DP_ERR_OFFLINE; -        goto done; -    } - -    pd->pam_status = PAM_SYSTEM_ERR; - -    switch (pd->cmd) { -    case SSS_PAM_AUTHENTICATE: -    case SSS_PAM_CHAUTHTOK_PRELIM: - -        state = talloc_zero(breq, struct sdap_pam_auth_state); -        if (!state) goto done; - -        state->breq = breq; -        state->pd = pd; -        state->username = pd->user; -        state->password.data = pd->authtok; -        state->password.length = pd->authtok_size; - -        subreq = auth_send(breq, breq->be_ctx->ev, ctx, -                           state->username, state->password); -        if (!subreq) goto done; - -        tevent_req_set_callback(subreq, sdap_pam_auth_done, state); -        return; - -    case SSS_PAM_CHAUTHTOK: -        break; - -    case SSS_PAM_ACCT_MGMT: -    case SSS_PAM_SETCRED: -    case SSS_PAM_OPEN_SESSION: -    case SSS_PAM_CLOSE_SESSION: -        pd->pam_status = PAM_SUCCESS; -        dp_err = DP_ERR_OK; -        break; -    default: -        pd->pam_status = PAM_MODULE_UNKNOWN; -        dp_err = DP_ERR_OK; -    } - -done: -    sdap_pam_auth_reply(breq, dp_err, pd->pam_status); -} - -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 tevent_req *subreq; -    enum sdap_result result; -    enum pwexpire pw_expire_type; -    void *pw_expire_data; -    int dp_err = DP_ERR_OK; -    int ret; - -    ret = auth_recv(req, state, NULL, -                    &result, NULL, -                    &pw_expire_type, &pw_expire_data); -    talloc_zfree(req); -    if (ret) { -        state->pd->pam_status = PAM_SYSTEM_ERR; -        dp_err = DP_ERR_FATAL; -        goto done; -    } - -    if (result == SDAP_AUTH_SUCCESS) { -        switch (pw_expire_type) { -            case PWEXPIRE_SHADOW: -                ret = check_pwexpire_shadow(pw_expire_data, time(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), -                                              &result); -                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: -            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: -        state->pd->pam_status = PAM_SUCCESS; -        break; -    case SDAP_AUTH_FAILED: -        state->pd->pam_status = PAM_PERM_DENIED; -        break; -    case SDAP_UNAVAIL: -        state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; -        break; -    case SDAP_ACCT_EXPIRED: -        state->pd->pam_status = PAM_ACCT_EXPIRED; -        break; -    case SDAP_AUTH_PW_EXPIRED: -        state->pd->pam_status = PAM_AUTHTOK_EXPIRED; -        break; -    default: -        state->pd->pam_status = PAM_SYSTEM_ERR; -        dp_err = DP_ERR_FATAL; -    } - -    if (result == SDAP_UNAVAIL) { -        be_mark_offline(state->breq->be_ctx); -        dp_err = DP_ERR_OFFLINE; -        goto done; -    } - -    if (result == SDAP_AUTH_SUCCESS && -        state->breq->be_ctx->domain->cache_credentials) { - -        char *password = talloc_strndup(state, (char *) -                                        state->password.data, -                                        state->password.length); -        /* password caching failures are not fatal errors */ -        if (!password) { -            DEBUG(2, ("Failed to cache password for %s\n", state->username)); -            goto done; -        } -        talloc_set_destructor((TALLOC_CTX *)password, password_destructor); - -        subreq = sysdb_cache_password_send(state, -                                           state->breq->be_ctx->ev, -                                           state->breq->be_ctx->sysdb, -                                           NULL, -                                           state->breq->be_ctx->domain, -                                           state->username, password); - -        /* password caching failures are not fatal errors */ -        if (!subreq) { -            DEBUG(2, ("Failed to cache password for %s\n", state->username)); -            goto done; -        } - -        tevent_req_set_callback(subreq, sdap_password_cache_done, state); -        return; -    } - -done: -    sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} - -static void sdap_password_cache_done(struct tevent_req *subreq) -{ -    struct sdap_pam_auth_state *state = tevent_req_callback_data(subreq, -                                                struct sdap_pam_auth_state); -    int ret; - -    ret = sysdb_cache_password_recv(subreq); -    talloc_zfree(subreq); -    if (ret) { -        /* password caching failures are not fatal errors */ -        DEBUG(2, ("Failed to cache password for %s\n", state->username)); -    } else { -        DEBUG(4, ("Password successfully cached for %s\n", state->username)); -    } - -    sdap_pam_auth_reply(state->breq, DP_ERR_OK, state->pd->pam_status); -} - -static void sdap_pam_auth_reply(struct be_req *req, int dp_err, int result) -{ -    req->fn(req, dp_err, result, NULL); -} - | 
