From aab2ed7eb50356f8eec9de8498b0953358ac93b0 Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Wed, 14 Mar 2012 06:25:44 -0400 Subject: [PATCH 07/14] Accept be_req instead if be_ctx in krb5 auth provider --- src/providers/ipa/ipa_auth.c | 4 +- src/providers/krb5/krb5_auth.c | 64 +++++++++++-------- src/providers/krb5/krb5_auth.h | 2 +- .../krb5/krb5_delayed_online_authentication.c | 26 +++++++- src/providers/krb5/krb5_renew_tgt.c | 30 ++++++++- src/providers/krb5/krb5_wait_queue.c | 2 +- 6 files changed, 91 insertions(+), 37 deletions(-) diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 2bd313b..9321565 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -233,7 +233,7 @@ void ipa_auth(struct be_req *be_req) goto fail; } - req = krb5_auth_send(state, state->ev, be_req->be_ctx, state->pd, + req = krb5_auth_send(state, state->ev, be_req, state->pd, state->ipa_auth_ctx->krb5_auth_ctx); if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("krb5_auth_send failed.\n")); @@ -427,7 +427,7 @@ static void ipa_auth_ldap_done(struct tevent_req *req) "trying Kerberos authentication again.\n")); req = krb5_auth_send(state, state->ev, - state->be_req->be_ctx, state->pd, + state->be_req, state->pd, state->ipa_auth_ctx->krb5_auth_ctx); if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("krb5_auth_send failed.\n")); diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index e244cea..1054030 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -279,7 +279,7 @@ static void krb5_pam_handler_cache_auth_step(struct tevent_req *req); struct krb5_auth_state { struct tevent_context *ev; - struct be_ctx *be_ctx; + struct be_req *be_req; struct pam_data *pd; struct krb5_ctx *krb5_ctx; struct krb5child_req *kr; @@ -303,9 +303,14 @@ int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err) static struct tevent_req *krb5_next_kdc(struct tevent_req *req); static struct tevent_req *krb5_next_kpasswd(struct tevent_req *req); +/* + * Beware that the struct be_req *be_req can be only a stub + * with only a subset of members set. See krb5_renew_tgt.c + * and krb5_delayed_online_authentication.c for details. + */ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct be_ctx *be_ctx, + struct be_req *be_req, struct pam_data *pd, struct krb5_ctx *krb5_ctx) { @@ -326,7 +331,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, } state->ev = ev; - state->be_ctx = be_ctx; + state->be_req = be_req; state->pd = pd; state->krb5_ctx = krb5_ctx; state->kr = NULL; @@ -355,7 +360,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, goto done; } - if (be_is_offline(be_ctx) && + if (be_is_offline(be_req->be_ctx) && (pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM || pd->cmd == SSS_CMD_RENEW)) { DEBUG(9, ("Password changes and ticket renewal are not possible " @@ -386,7 +391,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, } kr = state->kr; - ret = sysdb_get_user_attr(state, be_ctx->sysdb, state->pd->user, attrs, + ret = sysdb_get_user_attr(state, be_req->sysdb, state->pd->user, attrs, &res); if (ret) { DEBUG(5, ("sysdb search for upn of user [%s] failed.\n", pd->user)); @@ -521,7 +526,7 @@ static void krb5_resolve_kdc_done(struct tevent_req *subreq) * was found good, setting offline, * but we still have to call the child to setup * the ccache file if we are performing auth */ - be_mark_offline(state->be_ctx); + be_mark_offline(state->be_req->be_ctx); kr->is_offline = true; if (kr->pd->cmd == SSS_PAM_CHAUTHTOK || @@ -587,7 +592,7 @@ static void krb5_find_ccache_step(struct tevent_req *req) struct tevent_req *subreq = NULL; if (!kr->is_offline) { - kr->is_offline = be_is_offline(state->be_ctx); + kr->is_offline = be_is_offline(state->be_req->be_ctx); } /* The ccache file should be (re)created if one of the following conditions @@ -613,7 +618,7 @@ static void krb5_find_ccache_step(struct tevent_req *req) dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL), true, - state->be_ctx->domain->case_sensitive, + state->be_req->domain->case_sensitive, &private_path); if (kr->ccname == NULL) { DEBUG(1, ("expand_ccname_template failed.\n")); @@ -750,7 +755,7 @@ static void krb5_child_done(struct tevent_req *subreq) } ret = parse_krb5_child_response(state, buf, len, pd, - state->be_ctx->domain->pwd_expiration_warning, + state->be_req->domain->pwd_expiration_warning, &res); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Could not parse child response [%d]: %s\n", @@ -793,7 +798,7 @@ static void krb5_child_done(struct tevent_req *subreq) "please remove it manually.\n", kr->old_ccname)); } - ret = krb5_delete_ccname(state, state->be_ctx->sysdb, + ret = krb5_delete_ccname(state, state->be_req->sysdb, pd->user, kr->old_ccname); if (ret != EOK) { DEBUG(1, ("krb5_delete_ccname failed.\n")); @@ -821,7 +826,7 @@ static void krb5_child_done(struct tevent_req *subreq) (pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) { /* ..which is unreachable by now.. */ if (res->msg_status == PAM_AUTHTOK_LOCK_BUSY) { - be_fo_set_port_status(state->be_ctx, + be_fo_set_port_status(state->be_req->be_ctx, state->krb5_ctx->service->name, kr->kpasswd_srv, PORT_NOT_WORKING); /* ..try to resolve next kpasswd server */ @@ -830,7 +835,7 @@ static void krb5_child_done(struct tevent_req *subreq) } return; } else { - be_fo_set_port_status(state->be_ctx, + be_fo_set_port_status(state->be_req->be_ctx, state->krb5_ctx->service->name, kr->kpasswd_srv, PORT_WORKING); } @@ -842,8 +847,9 @@ static void krb5_child_done(struct tevent_req *subreq) if (res->msg_status == PAM_AUTHINFO_UNAVAIL || (kr->kpasswd_srv == NULL && res->msg_status == PAM_AUTHTOK_LOCK_BUSY)) { if (kr->srv != NULL) { - be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name, - kr->srv, PORT_NOT_WORKING); + be_fo_set_port_status(state->be_req->be_ctx, + state->krb5_ctx->service->name, kr->srv, + PORT_NOT_WORKING); /* ..try to resolve next KDC */ if (krb5_next_kdc(req) == NULL) { tevent_req_error(req, ENOMEM); @@ -851,8 +857,9 @@ static void krb5_child_done(struct tevent_req *subreq) return; } } else if (kr->srv != NULL) { - be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name, - kr->srv, PORT_WORKING); + be_fo_set_port_status(state->be_req->be_ctx, + state->krb5_ctx->service->name, kr->srv, + PORT_WORKING); } /* Now only a successful authentication or password change is left. @@ -882,7 +889,7 @@ static void krb5_child_done(struct tevent_req *subreq) "please remove it manually.\n", kr->old_ccname)); } - ret = krb5_save_ccname(state, state->be_ctx->sysdb, + ret = krb5_save_ccname(state, state->be_req->sysdb, pd->user, store_ccname); if (ret) { DEBUG(1, ("krb5_save_ccname failed.\n")); @@ -924,19 +931,22 @@ static struct tevent_req *krb5_next_server(struct tevent_req *req) switch (pd->cmd) { case SSS_PAM_AUTHENTICATE: case SSS_CMD_RENEW: - be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name, + be_fo_set_port_status(state->be_req->be_ctx, + state->krb5_ctx->service->name, state->kr->srv, PORT_NOT_WORKING); next_req = krb5_next_kdc(req); break; case SSS_PAM_CHAUTHTOK: case SSS_PAM_CHAUTHTOK_PRELIM: if (state->kr->kpasswd_srv) { - be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name, + be_fo_set_port_status(state->be_req->be_ctx, + state->krb5_ctx->service->name, state->kr->kpasswd_srv, PORT_NOT_WORKING); next_req = krb5_next_kpasswd(req); break; } else { - be_fo_set_port_status(state->be_ctx, state->krb5_ctx->service->name, + be_fo_set_port_status(state->be_req->be_ctx, + state->krb5_ctx->service->name, state->kr->srv, PORT_NOT_WORKING); next_req = krb5_next_kdc(req); break; @@ -954,7 +964,7 @@ static struct tevent_req *krb5_next_kdc(struct tevent_req *req) struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state); next_req = be_resolve_server_send(state, state->ev, - state->be_ctx, + state->be_req->be_ctx, state->krb5_ctx->service->name, state->kr->srv == NULL ? true : false); if (next_req == NULL) { @@ -972,7 +982,7 @@ static struct tevent_req *krb5_next_kpasswd(struct tevent_req *req) struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state); next_req = be_resolve_server_send(state, state->ev, - state->be_ctx, + state->be_req->be_ctx, state->krb5_ctx->kpasswd_service->name, state->kr->kpasswd_srv == NULL ? true : false); if (next_req == NULL) { @@ -1005,7 +1015,7 @@ static void krb5_save_ccname_done(struct tevent_req *req) goto done; } - if (state->be_ctx->domain->cache_credentials == TRUE) { + if (state->be_req->domain->cache_credentials == TRUE) { /* password caching failures are not fatal errors */ state->pam_status = PAM_SUCCESS; @@ -1048,7 +1058,7 @@ static void krb5_save_ccname_done(struct tevent_req *req) talloc_set_destructor((TALLOC_CTX *)password, password_destructor); - ret = sysdb_cache_password(state->be_ctx->sysdb, pd->user, password); + ret = sysdb_cache_password(state->be_req->sysdb, pd->user, password); if (ret) { DEBUG(2, ("Failed to cache password, offline auth may not work." " (%d)[%s]!?\n", ret, strerror(ret))); @@ -1076,8 +1086,8 @@ static void krb5_pam_handler_cache_auth_step(struct tevent_req *req) struct krb5_ctx *krb5_ctx = state->kr->krb5_ctx; int ret; - ret = sysdb_cache_auth(state->be_ctx->sysdb, pd->user, pd->authtok, - pd->authtok_size, state->be_ctx->cdb, true, NULL, + ret = sysdb_cache_auth(state->be_req->sysdb, pd->user, pd->authtok, + pd->authtok_size, state->be_req->be_ctx->cdb, true, NULL, NULL); if (ret != EOK) { DEBUG(1, ("Offline authentication failed\n")); @@ -1140,7 +1150,7 @@ void krb5_pam_handler(struct be_req *be_req) "running request immediately.\n", pd->user)); } - req = krb5_auth_send(be_req, be_req->be_ctx->ev, be_req->be_ctx, pd, + req = krb5_auth_send(be_req, be_req->be_ctx->ev, be_req, pd, krb5_ctx); if (req == NULL) { DEBUG(1, ("krb5_auth_send failed.\n")); diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index cc079ba..87583c5 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -63,7 +63,7 @@ void krb5_pam_handler(struct be_req *be_req); struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct be_ctx *be_ctx, + struct be_req *be_req, struct pam_data *pd, struct krb5_ctx *krb5_ctx); int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err); diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c index d5dea3b..aacdc58 100644 --- a/src/providers/krb5/krb5_delayed_online_authentication.c +++ b/src/providers/krb5/krb5_delayed_online_authentication.c @@ -43,7 +43,7 @@ struct deferred_auth_ctx { }; struct auth_data { - struct be_ctx *be_ctx; + struct be_req *breq; struct krb5_ctx *krb5_ctx; struct pam_data *pd; }; @@ -98,7 +98,7 @@ static void authenticate_user(struct tevent_context *ev, } #endif - req = krb5_auth_send(auth_data, ev, auth_data->be_ctx, auth_data->pd, + req = krb5_auth_send(auth_data, ev, auth_data->breq, auth_data->pd, auth_data->krb5_ctx); if (req == NULL) { DEBUG(1, ("krb5_auth_send failed.\n")); @@ -144,6 +144,7 @@ static errno_t authenticate_stored_users( hash_value_t value; struct pam_data *pd; struct auth_data *auth_data; + struct be_req *breq; struct tevent_timer *te; ret = get_uid_table(deferred_auth_ctx, &uid_table); @@ -176,7 +177,26 @@ static errno_t authenticate_stored_users( } else { auth_data->pd = talloc_steal(auth_data, pd); auth_data->krb5_ctx = deferred_auth_ctx->krb5_ctx; - auth_data->be_ctx = deferred_auth_ctx->be_ctx; + + /* Create a stub of be_req for krb5_auth_send() */ + auth_data->breq = talloc_zero(auth_data, + struct be_req); + if (auth_data->breq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed\n")); + return ENOMEM; + } + breq = auth_data->breq; + breq->be_ctx = deferred_auth_ctx->be_ctx; + if (strcmp(pd->domain, breq->be_ctx->domain->name) != 0) { + breq->domain = new_subdomain(breq, breq->be_ctx->domain, + pd->domain, NULL, NULL); + if (breq->domain == NULL) { + return ENOMEM; + } + } else { + breq->domain = breq->be_ctx->domain; + } + breq->sysdb = breq->domain->sysdb; te = tevent_add_timer(deferred_auth_ctx->ev, auth_data, tevent_timeval_current(), diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c index 2ad5592..74375dc 100644 --- a/src/providers/krb5/krb5_renew_tgt.c +++ b/src/providers/krb5/krb5_renew_tgt.c @@ -48,7 +48,7 @@ struct renew_data { }; struct auth_data { - struct be_ctx *be_ctx; + struct be_req *breq; struct krb5_ctx *krb5_ctx; struct pam_data *pd; struct renew_data *renew_data; @@ -65,7 +65,7 @@ static void renew_tgt(struct tevent_context *ev, struct tevent_timer *te, struct auth_data); struct tevent_req *req; - req = krb5_auth_send(auth_data, ev, auth_data->be_ctx, auth_data->pd, + req = krb5_auth_send(auth_data, ev, auth_data->breq, auth_data->pd, auth_data->krb5_ctx); if (req == NULL) { DEBUG(1, ("krb5_auth_send failed.\n")); @@ -156,6 +156,7 @@ static errno_t renew_all_tgts(struct renew_tgt_ctx *renew_tgt_ctx) size_t c; time_t now; struct auth_data *auth_data; + struct be_req *breq; struct renew_data *renew_data; struct tevent_timer *te; @@ -189,9 +190,31 @@ static errno_t renew_all_tgts(struct renew_tgt_ctx *renew_tgt_ctx) * auth_data to allow a new renewal attempt. */ auth_data->pd = talloc_move(auth_data, &renew_data->pd); auth_data->krb5_ctx = renew_tgt_ctx->krb5_ctx; - auth_data->be_ctx = renew_tgt_ctx->be_ctx; auth_data->table = renew_tgt_ctx->tgt_table; auth_data->renew_data = renew_data; + + /* Create a stub of be_req for krb5_auth_send() */ + auth_data->breq = talloc_zero(auth_data, + struct be_req); + if (auth_data->breq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed\n")); + return ENOMEM; + } + breq = auth_data->breq; + breq->be_ctx = renew_tgt_ctx->be_ctx; + if (strcmp(auth_data->pd->domain, + breq->be_ctx->domain->name) != 0) { + breq->domain = new_subdomain(breq, breq->be_ctx->domain, + auth_data->pd->domain, + NULL, NULL); + if (breq->domain == NULL) { + return ENOMEM; + } + } else { + breq->domain = breq->be_ctx->domain; + } + breq->sysdb = breq->domain->sysdb; + auth_data->key.type = entries[c].key.type; auth_data->key.str = talloc_strdup(auth_data, entries[c].key.str); @@ -389,6 +412,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx) return ENOMEM; } + /* TODO: this HAS to be fixed - the routine has to go through all subdomains */ ret = sysdb_search_users(tmp_ctx, renew_tgt_ctx->be_ctx->sysdb, ccache_filter, ccache_attrs, &msgs_count, &msgs); if (ret != EOK) { diff --git a/src/providers/krb5/krb5_wait_queue.c b/src/providers/krb5/krb5_wait_queue.c index 3863b1b..a4e6297 100644 --- a/src/providers/krb5/krb5_wait_queue.c +++ b/src/providers/krb5/krb5_wait_queue.c @@ -46,7 +46,7 @@ static void wait_queue_auth(struct tevent_context *ev, struct tevent_timer *te, struct tevent_req *req; req = krb5_auth_send(queue_entry->be_req, queue_entry->be_req->be_ctx->ev, - queue_entry->be_req->be_ctx, queue_entry->pd, + queue_entry->be_req, queue_entry->pd, queue_entry->krb5_ctx); if (req == NULL) { DEBUG(1, ("krb5_auth_send failed.\n")); -- 1.7.7.6