summaryrefslogtreecommitdiff
path: root/src/providers/krb5/krb5_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/krb5/krb5_auth.c')
-rw-r--r--src/providers/krb5/krb5_auth.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 48173ba7..a7aebe52 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -371,10 +371,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"));
@@ -537,6 +537,7 @@ static void krb5_resolve_kpasswd_done(struct tevent_req *subreq);
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_auth_step(struct tevent_req *req);
struct krb5_auth_state {
struct tevent_context *ev;
@@ -897,40 +898,31 @@ 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)) {
+ krb5_pam_handler_cache_auth_step(req);
+ return;
}
state->pam_status = PAM_AUTHINFO_UNAVAIL;
state->dp_err = DP_ERR_OFFLINE;
ret = EOK;
goto done;
- }
- memset(pd->authtok, 0, pd->authtok_size);
- pd->authtok_size = 0;
- if (kr->active_ccache_present) {
- ret = krb5_save_ccname(state, state->be_ctx->sysdb,
- state->be_ctx->domain, pd->user,
- kr->ccname);
- if (ret) {
- DEBUG(1, ("krb5_save_ccname failed.\n"));
- goto done;
- }
-
- krb5_save_ccname_done(req);
- return;
}
}
@@ -1214,6 +1206,11 @@ static void krb5_save_ccname_done(struct tevent_req *req)
char *password = NULL;
if (kr->is_offline) {
+ if (dp_opt_get_bool(kr->krb5_ctx->opts,KRB5_STORE_PASSWORD_IF_OFFLINE)) {
+ krb5_pam_handler_cache_auth_step(req);
+ return;
+ }
+
DEBUG(4, ("Backend is marked offline, retry later!\n"));
state->pam_status = PAM_AUTHINFO_UNAVAIL;
state->dp_err = DP_ERR_OFFLINE;
@@ -1277,6 +1274,34 @@ done:
}
+static void krb5_pam_handler_cache_auth_step(struct tevent_req *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;
+
+ ret = sysdb_cache_auth(state, state->be_ctx->sysdb, state->be_ctx->domain,
+ pd->user, pd->authtok, pd->authtok_size,
+ state->be_ctx->cdb, true, NULL, NULL);
+ if (ret != EOK) {
+ DEBUG(1, ("Offline authentication failed\n"));
+ state->pam_status = PAM_SYSTEM_ERR;
+ state->dp_err = DP_ERR_OK;
+ } 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);
@@ -1335,4 +1360,3 @@ void krb5_auth_done(struct tevent_req *req)
krb_reply(be_req, dp_err, pd->pam_status);
}
-