summaryrefslogtreecommitdiffstats
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.c66
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) {