diff options
Diffstat (limited to 'src/providers/krb5/krb5_auth.c')
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index be34880..9877382 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -36,6 +36,7 @@ #include "util/crypto/sss_crypto.h" #include "util/find_uid.h" #include "util/auth_utils.h" +#include "util/sss_ptr_hash.h" #include "db/sysdb.h" #include "util/sss_utf8.h" #include "util/child_common.h" @@ -427,6 +428,59 @@ static bool is_otp_enabled(struct ldb_message *user_msg) return false; } +/* Closes the write end of waiting krb5_child */ +static errno_t soft_terminate_krb5_child(TALLOC_CTX *mem_ctx, + struct pam_data *pd, + struct krb5_ctx *krb5_ctx) +{ + char *io_key; + struct child_io_fds *io; + TALLOC_CTX *tmp_ctx; + int ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + if (pd->child_pid == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Expected waiting krb5_child.\n"); + ret = EINVAL; + goto done; + } + + io_key = talloc_asprintf(tmp_ctx, "%d", pd->child_pid); + if (io_key == NULL) { + ret = ENOMEM; + goto done; + } + + io = sss_ptr_hash_lookup(krb5_ctx->io_table, io_key, + struct child_io_fds); + if (io == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "PTR hash lookup failed.\n"); + ret = ENOMEM; + goto done; + } + + if (io->write_to_child_fd != -1) { + ret = close(io->write_to_child_fd); + io->write_to_child_fd = -1; + if (ret != EOK) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "close failed [%d][%s].\n", ret, strerror(ret)); + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + /* krb5_auth request */ struct krb5_auth_state { @@ -532,6 +586,18 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, ret = EOK; goto done; } + + /* If krb5_child is still running from SSS_PAM_PREAUTH, + * terminate the waiting krb5_child and send the + * CHAUTHTOK_PRELIM request again */ + if (pd->child_pid != 0) { + soft_terminate_krb5_child(state, pd, krb5_ctx); + state->pam_status = PAM_TRY_AGAIN; + state->dp_err = DP_ERR_OK; + ret = EOK; + goto done; + } + break; case SSS_CMD_RENEW: if (authtok_type != SSS_AUTHTOK_TYPE_CCFILE) { |