7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose/*
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose SSSD
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Kerberos 5 Backend Module - Serialize the request of a user
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Authors:
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Sumit Bose <sbose@redhat.com>
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose Copyright (C) 2010 Red Hat
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
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
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
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/>.
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose*/
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose#include <tevent.h>
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose#include <dhash.h>
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek#include <security/pam_modules.h>
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose#include "src/providers/krb5/krb5_auth.h"
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose#define INIT_HASH_SIZE 5
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bosestruct queue_entry {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *prev;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *next;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct be_ctx *be_ctx;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct be_req *be_req;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *parent_req;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct pam_data *pd;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct krb5_ctx *krb5_ctx;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose};
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void wait_queue_auth_done(struct tevent_req *req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_finish(struct tevent_req *req, errno_t ret,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int pam_status, int dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bosestatic void wait_queue_auth(struct tevent_context *ev, struct tevent_timer *te,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct timeval current_time, void *private_data)
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose{
7baccb545ac9829b7e1990f45ff6f70e2de55c2aSimo Sorce struct queue_entry *qe = talloc_get_type(private_data, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct tevent_req *req;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek req = krb5_auth_send(qe->parent_req, qe->be_ctx->ev,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek qe->be_ctx, qe->pd, qe->krb5_ctx);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (req == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth_send failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose } else {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_set_callback(req, wait_queue_auth_done,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek qe->parent_req);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7baccb545ac9829b7e1990f45ff6f70e2de55c2aSimo Sorce talloc_zfree(qe);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose}
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void wait_queue_auth_done(struct tevent_req *req)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *parent_req = \
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_callback_data(req, struct tevent_req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int pam_status;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int dp_err;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek errno_t ret;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = krb5_auth_recv(req, &pam_status, &dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek talloc_zfree(req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (ret != EOK) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed: %d\n", ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek krb5_auth_queue_finish(parent_req, ret, pam_status, dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek}
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bosestatic void wait_queue_del_cb(hash_entry_t *entry, hash_destroy_enum type,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose void *pvt)
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose{
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *head;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (entry->value.type == HASH_VALUE_PTR) {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(entry->value.ptr, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose talloc_zfree(head);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Unexpected value type [%d].\n", entry->value.type);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose}
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic errno_t add_to_wait_queue(struct be_ctx *be_ctx,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *parent_req,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct pam_data *pd,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_ctx *krb5_ctx)
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose{
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose int ret;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose hash_key_t key;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose hash_value_t value;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *head;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *queue_entry;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (krb5_ctx->wait_queue_hash == NULL) {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = sss_hash_create_ex(krb5_ctx, INIT_HASH_SIZE,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose &krb5_ctx->wait_queue_hash, 0, 0, 0, 0,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose wait_queue_del_cb, NULL);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (ret != EOK) {
87f8bee53ee1b4ca87b602ff8536bc5fd5b5b595Lukas Slebodnik DEBUG(SSSDBG_CRIT_FAILURE, "sss_hash_create failed\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return ret;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose key.type = HASH_KEY_STRING;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose key.str = pd->user;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_lookup(krb5_ctx->wait_queue_hash, &key, &value);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose switch (ret) {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose case HASH_SUCCESS:
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (value.type != HASH_VALUE_PTR) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected hash value type.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return EINVAL;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(value.ptr, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry = talloc_zero(head, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (queue_entry == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return ENOMEM;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek queue_entry->be_ctx = be_ctx;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek queue_entry->parent_req = parent_req;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry->pd = pd;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry->krb5_ctx = krb5_ctx;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose DLIST_ADD_END(head, queue_entry, struct queue_entry *);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose break;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose case HASH_ERROR_KEY_NOT_FOUND:
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose value.type = HASH_VALUE_PTR;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_zero(krb5_ctx->wait_queue_hash, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (head == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return ENOMEM;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose value.ptr = head;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_enter(krb5_ctx->wait_queue_hash, &key, &value);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (ret != HASH_SUCCESS) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_enter failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose talloc_free(head);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return EIO;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose break;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose default:
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_lookup failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return EIO;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (head->next == NULL) {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return ENOENT;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose } else {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return EOK;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose}
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void check_wait_queue(struct krb5_ctx *krb5_ctx, char *username)
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose{
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose int ret;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose hash_key_t key;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose hash_value_t value;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *head;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct queue_entry *queue_entry;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose struct tevent_timer *te;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (krb5_ctx->wait_queue_hash == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "No wait queue available.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose key.type = HASH_KEY_STRING;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose key.str = username;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_lookup(krb5_ctx->wait_queue_hash, &key, &value);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose switch (ret) {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose case HASH_SUCCESS:
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (value.type != HASH_VALUE_PTR) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected hash value type.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose head = talloc_get_type(value.ptr, struct queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (head->next == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_LIBS,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Wait queue for user [%s] is empty.\n", username);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose } else {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry = head->next;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose DLIST_REMOVE(head, queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek te = tevent_add_timer(queue_entry->be_ctx->ev, krb5_ctx,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose tevent_timeval_current(), wait_queue_auth,
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose queue_entry);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (te == NULL) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose } else {
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose ret = hash_delete(krb5_ctx->wait_queue_hash, &key);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose if (ret != HASH_SUCCESS) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Failed to remove wait queue for user [%s].\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov username);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose break;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose case HASH_ERROR_KEY_NOT_FOUND:
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "No wait queue for user [%s] found.\n", username);
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose break;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose default:
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "hash_lookup failed.\n");
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose }
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose return;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose}
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstruct krb5_auth_queue_state {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_ctx *krb5_ctx;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct pam_data *pd;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int pam_status;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int dp_err;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek};
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_done(struct tevent_req *subreq);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstruct tevent_req *krb5_auth_queue_send(TALLOC_CTX *mem_ctx,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_context *ev,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct be_ctx *be_ctx,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct pam_data *pd,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_ctx *krb5_ctx)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek errno_t ret;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *req;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *subreq;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_auth_queue_state *state;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek req = tevent_req_create(mem_ctx, &state, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (req == NULL) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek return NULL;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek state->krb5_ctx = krb5_ctx;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek state->pd = pd;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = add_to_wait_queue(be_ctx, req, pd, krb5_ctx);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (ret == EOK) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "Request [%p] successfully added to wait queue "
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "of user [%s].\n", req, pd->user);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = EOK;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek goto immediate;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek } else if (ret == ENOENT) {
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 } else {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "Failed to add request to wait queue of user [%s], "
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek "running request [%p] immediately.\n", pd->user, req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek subreq = krb5_auth_send(req, ev, be_ctx, pd, krb5_ctx);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (req == NULL) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth_send failed.\n");
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = ENOMEM;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek goto immediate;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_set_callback(subreq, krb5_auth_queue_done, req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = EOK;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekimmediate:
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (ret != EOK) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_error(req, ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_post(req, ev);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek return req;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek}
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_done(struct tevent_req *subreq)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct tevent_req *req = \
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_callback_data(subreq, struct tevent_req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_auth_queue_state *state = \
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek errno_t ret;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek ret = krb5_auth_recv(subreq, &state->pam_status, &state->dp_err);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek talloc_zfree(subreq);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek check_wait_queue(state->krb5_ctx, state->pd->user);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (ret != EOK) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed with: %d\n", ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_error(req, ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek return;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "krb5_auth_queue request [%p] done.\n", req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_done(req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek}
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
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 Hrozek */
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekstatic void krb5_auth_queue_finish(struct tevent_req *req,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek errno_t ret,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int pam_status,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int dp_err)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_auth_queue_state *state = \
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek check_wait_queue(state->krb5_ctx, state->pd->user);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek state->pam_status = pam_status;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek state->dp_err = dp_err;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (ret != EOK) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_error(req, ret);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek } else {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "krb5_auth_queue request [%p] done.\n", req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_done(req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek}
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozekint krb5_auth_queue_recv(struct tevent_req *req,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int *_pam_status,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int *_dp_err)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct krb5_auth_queue_state *state = \
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek tevent_req_data(req, struct krb5_auth_queue_state);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
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..
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek */
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (_pam_status) {
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek *_pam_status = state->pam_status;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek if (_dp_err) {
da17e4c19e97a76ed13eaa55a488b3c1b2827749Lukas Slebodnik *_dp_err = state->dp_err;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek }
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek TEVENT_REQ_RETURN_ON_ERROR(req);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek return EOK;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek}