diff options
author | Sumit Bose <sbose@redhat.com> | 2010-04-19 11:59:09 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-05-07 16:38:23 -0400 |
commit | fc7ec12f1b851bab1eedf3ecdcb094ea80b46dd2 (patch) | |
tree | 9aa674b262b92ebe2f66c745a42f6cec4a0a1c18 /src/providers/krb5/krb5_auth.c | |
parent | ca6aa84e20e445fb04dfce416a8c3a1912b26451 (diff) | |
download | sssd_unused-fc7ec12f1b851bab1eedf3ecdcb094ea80b46dd2.tar.gz sssd_unused-fc7ec12f1b851bab1eedf3ecdcb094ea80b46dd2.tar.xz sssd_unused-fc7ec12f1b851bab1eedf3ecdcb094ea80b46dd2.zip |
Add support for delayed kinit if offline
If the configuration option krb5_store_password_if_offline is set to
true and the backend is offline the plain text user password is stored
and used to request a TGT if the backend becomes online. If available
the Linux kernel key retention service is used.
Diffstat (limited to 'src/providers/krb5/krb5_auth.c')
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 108 |
1 files changed, 79 insertions, 29 deletions
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index 56539636..92b72f69 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -437,10 +437,10 @@ static errno_t fork_child(struct tevent_req *req, struct tevent_context *ev, /* We need to keep the root privileges to read the keytab file if * validation is enabled, otherwise we can drop them here and run * krb5_child with user privileges. - * If authtok_size is zero we are offline and want to create an empty - * ccache file. In this case we can drop the privileges, too. */ + * If we are offline and want to create an empty ccache file. In this + * case we can drop the privileges, too. */ if (!dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) || - kr->pd->authtok_size == 0) { + kr->is_offline) { ret = become_user(kr->uid, kr->gid); if (ret != EOK) { DEBUG(1, ("become_user failed.\n")); @@ -605,6 +605,7 @@ static void krb5_find_ccache_step(struct tevent_req *req); static void krb5_save_ccname_done(struct tevent_req *req); static void krb5_child_done(struct tevent_req *req); static void krb5_pam_handler_cache_done(struct tevent_req *treq); +static void krb5_pam_handler_cache_auth_done(struct tevent_req *subreq); struct krb5_auth_state { struct tevent_context *ev; @@ -973,19 +974,38 @@ static void krb5_find_ccache_step(struct tevent_req *req) DEBUG(9, ("Preparing for offline operation.\n")); kr->is_offline = true; - if (kr->valid_tgt_present) { - DEBUG(9, ("Valid TGT available, nothing to do.\n")); + if (kr->valid_tgt_present || kr->active_ccache_present) { + DEBUG(9, ("Valid TGT available or " + "ccache file is already in use.\n")); msg = talloc_asprintf(pd, "%s=%s", CCACHE_ENV_NAME, kr->ccname); if (msg == NULL) { DEBUG(1, ("talloc_asprintf failed.\n")); - ret = ENOMEM; - goto done; + } else { + ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(msg) + 1, + (uint8_t *) msg); + if (ret != EOK) { + DEBUG(1, ("pam_add_response failed.\n")); + } } - ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(msg) + 1, - (uint8_t *) msg); - if (ret != EOK) { - DEBUG(1, ("pam_add_response failed.\n")); + if (dp_opt_get_bool(kr->krb5_ctx->opts, + KRB5_STORE_PASSWORD_IF_OFFLINE)) { + subreq = sysdb_cache_auth_send(state, state->ev, + state->be_ctx->sysdb, + state->be_ctx->domain, pd->user, + pd->authtok, pd->authtok_size, + state->be_ctx->cdb, true); + if (subreq == NULL) { + DEBUG(2, ("sysdb_cache_auth_send failed, " + "delayed online authentication not possible.\n")); + /* This is not a fatal error, we continue with standard + * offline authentication. */ + } else { + tevent_req_set_callback(subreq, + krb5_pam_handler_cache_auth_done, + req); + return; + } } state->pam_status = PAM_AUTHINFO_UNAVAIL; @@ -993,23 +1013,6 @@ static void krb5_find_ccache_step(struct tevent_req *req) ret = EOK; goto done; } - memset(pd->authtok, 0, pd->authtok_size); - pd->authtok_size = 0; - - if (kr->active_ccache_present) { - subreq = krb5_save_ccname_send(state, state->ev, - state->be_ctx->sysdb, - state->be_ctx->domain, pd->user, - kr->ccname); - if (subreq == NULL) { - DEBUG(1, ("krb5_save_ccname_send failed.\n")); - ret = ENOMEM; - goto done; - } - - tevent_req_set_callback(subreq, krb5_save_ccname_done, req); - return; - } } subreq = handle_child_send(state, state->ev, kr); @@ -1300,6 +1303,24 @@ static void krb5_save_ccname_done(struct tevent_req *subreq) } if (kr->is_offline) { + if (dp_opt_get_bool(kr->krb5_ctx->opts,KRB5_STORE_PASSWORD_IF_OFFLINE)) { + subreq = sysdb_cache_auth_send(state, state->ev, + state->be_ctx->sysdb, + state->be_ctx->domain, pd->user, + pd->authtok, pd->authtok_size, + state->be_ctx->cdb, true); + if (subreq == NULL) { + DEBUG(2, ("sysdb_cache_auth_send failed, " + "delayed online authentication not possible.\n")); + /* This is not a fatal error, we continue with standard + * offline authentication. */ + } else { + tevent_req_set_callback(subreq, + krb5_pam_handler_cache_auth_done, req); + return; + } + } + DEBUG(4, ("Backend is marked offline, retry later!\n")); state->pam_status = PAM_AUTHINFO_UNAVAIL; state->dp_err = DP_ERR_OFFLINE; @@ -1372,7 +1393,6 @@ static void krb5_pam_handler_cache_done(struct tevent_req *subreq) struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); int ret; - /* password caching failures are not fatal errors */ ret = sysdb_cache_password_recv(subreq); talloc_zfree(subreq); @@ -1386,6 +1406,36 @@ static void krb5_pam_handler_cache_done(struct tevent_req *subreq) tevent_req_done(req); } +static void krb5_pam_handler_cache_auth_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state); + struct pam_data *pd = state->pd; + struct krb5_ctx *krb5_ctx = state->kr->krb5_ctx; + int ret; + time_t expire_date; + time_t delayed_until; + + ret = sysdb_cache_auth_recv(subreq, &expire_date, &delayed_until); + talloc_zfree(subreq); + + if (ret) { + DEBUG(2, ("Offline authentication failed.\n")); + } else { + ret = add_user_to_delayed_online_authentication(krb5_ctx, pd, + state->kr->uid); + if (ret != EOK) { + /* This error is not fatal */ + DEBUG(1, ("add_user_to_delayed_online_authentication failed.\n")); + } + } + + state->pam_status = PAM_AUTHINFO_UNAVAIL; + state->dp_err = DP_ERR_OFFLINE; + + tevent_req_done(req); +} + static void krb_reply(struct be_req *req, int dp_err, int result) { req->fn(req, dp_err, result, NULL); |