7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Kerberos 5 Backend Module - Serialize the request of a user
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Sumit Bose <sbose@redhat.com>
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Copyright (C) 2010 Red Hat
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose This program is free software; you can redistribute it and/or modify
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose it under the terms of the GNU General Public License as published by
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose the Free Software Foundation; either version 3 of the License, or
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose (at your option) any later version.
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose This program is distributed in the hope that it will be useful,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose GNU General Public License for more details.
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose You should have received a copy of the GNU General Public License
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void wait_queue_auth_done(struct tevent_req *req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_finish(struct tevent_req *req, errno_t ret,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bosestatic void wait_queue_auth(struct tevent_context *ev, struct tevent_timer *te,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct timeval current_time, void *private_data)
7baccb545ac9829b7e1990f45ff6f70e2de55c2aSimo Sorce struct queue_entry *qe = talloc_get_type(private_data, struct queue_entry);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek req = krb5_auth_send(qe->parent_req, qe->be_ctx->ev,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth_send failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_set_callback(req, wait_queue_auth_done,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void wait_queue_auth_done(struct tevent_req *req)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_callback_data(req, struct tevent_req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = krb5_auth_recv(req, &pam_status, &dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed: %d\n", ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek krb5_auth_queue_finish(parent_req, ret, pam_status, dp_err);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bosestatic void wait_queue_del_cb(hash_entry_t *entry, hash_destroy_enum type,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(entry->value.ptr, struct queue_entry);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Unexpected value type [%d].\n", entry->value.type);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic errno_t add_to_wait_queue(struct be_ctx *be_ctx,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = sss_hash_create_ex(krb5_ctx, INIT_HASH_SIZE,
87f8bee53ee1b4ca87b602ff8536bc5fd5b5b595Lukas Slebodnik DEBUG(SSSDBG_CRIT_FAILURE, "sss_hash_create failed\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_lookup(krb5_ctx->wait_queue_hash, &key, &value);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected hash value type.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(value.ptr, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry = talloc_zero(head, struct queue_entry);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose DLIST_ADD_END(head, queue_entry, struct queue_entry *);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_zero(krb5_ctx->wait_queue_hash, struct queue_entry);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_enter(krb5_ctx->wait_queue_hash, &key, &value);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_enter failed.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_lookup failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void check_wait_queue(struct krb5_ctx *krb5_ctx, char *username)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "No wait queue available.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_lookup(krb5_ctx->wait_queue_hash, &key, &value);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected hash value type.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(value.ptr, struct queue_entry);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Wait queue for user [%s] is empty.\n", username);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek te = tevent_add_timer(queue_entry->be_ctx->ev, krb5_ctx,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_delete(krb5_ctx->wait_queue_hash, &key);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Failed to remove wait queue for user [%s].\n",
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "No wait queue for user [%s] found.\n", username);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_lookup failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_done(struct tevent_req *subreq);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstruct tevent_req *krb5_auth_queue_send(TALLOC_CTX *mem_ctx,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek req = tevent_req_create(mem_ctx, &state, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = add_to_wait_queue(be_ctx, req, pd, krb5_ctx);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "Request [%p] successfully added to wait queue "
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Wait queue of user [%s] is empty, "
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "running request [%p] immediately.\n", pd->user, req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "Failed to add request to wait queue of user [%s], "
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "running request [%p] immediately.\n", pd->user, req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek subreq = krb5_auth_send(req, ev, be_ctx, pd, krb5_ctx);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth_send failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_set_callback(subreq, krb5_auth_queue_done, req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_done(struct tevent_req *subreq)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_callback_data(subreq, struct tevent_req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = krb5_auth_recv(subreq, &state->pam_status, &state->dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek check_wait_queue(state->krb5_ctx, state->pd->user);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed with: %d\n", ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "krb5_auth_queue request [%p] done.\n", req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek/* This is a violation of the tevent_req style. Ideally, the wait queue would
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek * be rewritten to the tevent_req style in the future, expose per-request recv
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek * and not hide the request underneath. But this function allows us to expose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek * a tevent_req API for users of this module
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_finish(struct tevent_req *req,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek check_wait_queue(state->krb5_ctx, state->pd->user);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "krb5_auth_queue request [%p] done.\n", req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekint krb5_auth_queue_recv(struct tevent_req *req,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek /* Returning values even on failure is not typical, but IPA password migration
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek * relies on receiving PAM_CRED_ERR even if the request fails..