diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
commit | 74aa0bc6779af38018a03fd2cf4419fe85917904 (patch) | |
tree | 9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/pam/pam_prompting_config.c | |
parent | Initial commit. (diff) | |
download | sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip |
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/responder/pam/pam_prompting_config.c')
-rw-r--r-- | src/responder/pam/pam_prompting_config.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/responder/pam/pam_prompting_config.c b/src/responder/pam/pam_prompting_config.c new file mode 100644 index 0000000..7d0362f --- /dev/null +++ b/src/responder/pam/pam_prompting_config.c @@ -0,0 +1,309 @@ +/* + SSSD + + PAM Responder - helpers for PAM prompting configuration + + Copyright (C) Sumit Bose <sbose@redhat.com> 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "util/util.h" +#include "util/sss_pam_data.h" +#include "confdb/confdb.h" +#include "sss_client/sss_cli.h" +#include "responder/pam/pamsrv.h" + +#define DEFAULT_PASSKEY_PROMPT_INTERACTIVE _("Insert your Passkey device, then press ENTER.") +#define DEFAULT_PASSKEY_PROMPT_TOUCH _("Please touch the device.") + +typedef errno_t (pam_set_prompting_fn_t)(TALLOC_CTX *, struct confdb_ctx *, + const char *, + struct prompt_config ***); + + +static errno_t pam_set_password_prompting_options(TALLOC_CTX *tmp_ctx, + struct confdb_ctx *cdb, + const char *section, + struct prompt_config ***pc_list) +{ + int ret; + char *value = NULL; + + ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_PASSWORD_PROMPT, + NULL, &value); + if (ret == EOK && value != NULL) { + ret = pc_list_add_password(pc_list, value); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_password failed.\n"); + } + return ret; + } + + return ENOENT; +} + +static errno_t pam_set_2fa_prompting_options(TALLOC_CTX *tmp_ctx, + struct confdb_ctx *cdb, + const char *section, + struct prompt_config ***pc_list) +{ + bool single_2fa_prompt = false; + char *first_prompt = NULL; + char *second_prompt = NULL; + int ret; + + + ret = confdb_get_bool(cdb, section, CONFDB_PC_2FA_SINGLE_PROMPT, false, + &single_2fa_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_bool failed, using defaults"); + } + ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_2FA_1ST_PROMPT, + NULL, &first_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults"); + } + + if (single_2fa_prompt) { + ret = pc_list_add_2fa_single(pc_list, first_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_2fa_single failed.\n"); + } + return ret; + } else { + ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_2FA_2ND_PROMPT, + NULL, &second_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "confdb_get_string failed, using defaults"); + } + + ret = pc_list_add_2fa(pc_list, first_prompt, second_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_2fa failed.\n"); + } + return ret; + } + + return ENOENT; +} + +static errno_t pam_set_passkey_prompting_options(TALLOC_CTX *tmp_ctx, + struct confdb_ctx *cdb, + const char *section, + struct prompt_config ***pc_list) +{ + bool passkey_interactive = false; + char *passkey_interactive_prompt = NULL; + bool passkey_touch = false; + char *passkey_touch_prompt = NULL; + int ret; + + + ret = confdb_get_bool(cdb, section, CONFDB_PC_PASSKEY_INTERACTIVE, false, + &passkey_interactive); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_bool failed, using defaults"); + } + + if (passkey_interactive) { + ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_PASSKEY_INTERACTIVE_PROMPT, + DEFAULT_PASSKEY_PROMPT_INTERACTIVE, &passkey_interactive_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults"); + } + } + + ret = confdb_get_bool(cdb, section, CONFDB_PC_PASSKEY_TOUCH, false, + &passkey_touch); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_bool failed, using defaults"); + } + + if (passkey_touch) { + ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_PASSKEY_TOUCH_PROMPT, + DEFAULT_PASSKEY_PROMPT_TOUCH, &passkey_touch_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults"); + } + } + + ret = pc_list_add_passkey(pc_list, passkey_interactive_prompt, passkey_touch_prompt); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_passkey_touch failed.\n"); + } + + return ret; +} +static errno_t pam_set_prompting_options(struct confdb_ctx *cdb, + const char *service_name, + char **sections, + int num_sections, + const char *section_path, + pam_set_prompting_fn_t *setter, + struct prompt_config ***pc_list) +{ + char *dummy; + size_t c; + bool global = false; + bool specific = false; + char *section = NULL; + int ret; + char *last; + TALLOC_CTX *tmp_ctx = NULL; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + + dummy = talloc_asprintf(tmp_ctx, "%s/%s", section_path, + service_name); + for (c = 0; c < num_sections; c++) { + if (strcmp(sections[c], section_path) == 0) { + global = true; + } + if (dummy != NULL && strcmp(sections[c], dummy) == 0) { + specific = true; + } + } + + section = talloc_asprintf(tmp_ctx, "%s/%s", CONFDB_PC_CONF_ENTRY, dummy); + if (section == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = ENOENT; + if (specific) { + ret = setter(tmp_ctx, cdb, section, pc_list); + } + if (global && ret == ENOENT) { + last = strrchr(section, '/'); + if (last != NULL) { + *last = '\0'; + ret = setter(tmp_ctx, cdb, section, pc_list); + } + } + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "setter failed.\n"); + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd) +{ + int ret; + struct prompt_config **pc_list = NULL; + int resp_len; + uint8_t *resp_data = NULL; + struct pam_resp_auth_type types; + + if (pctx->num_prompting_config_sections == 0) { + DEBUG(SSSDBG_TRACE_ALL, "No prompting configuration found.\n"); + return EOK; + } + + ret = pam_get_auth_types(pd, &types); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to get authentication types\n"); + goto done; + } + + if (types.passkey_auth) { + ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service, + pctx->prompting_config_sections, + pctx->num_prompting_config_sections, + CONFDB_PC_TYPE_PASSKEY, + pam_set_passkey_prompting_options, + &pc_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "pam_set_prompting_options failed.\n"); + goto done; + } + } + + if (types.cert_auth) { + /* If certificate based authentication is possilbe, i.e. a Smartcard + * or similar with the mapped certificate is available we currently + * prefer this authentication type unconditionally. If other types + * should be used the Smartcard can be removed during authentication. + * Since there currently are no specific options for cert_auth we are + * done. */ + ret = EOK; + goto done; + } + + /* If OTP and password auth are possible we currently prefer OTP. */ + if (types.otp_auth) { + ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service, + pctx->prompting_config_sections, + pctx->num_prompting_config_sections, + CONFDB_PC_TYPE_2FA, + pam_set_2fa_prompting_options, + &pc_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "pam_set_prompting_options failed.\n"); + goto done; + } + } + + if (types.password_auth) { + ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service, + pctx->prompting_config_sections, + pctx->num_prompting_config_sections, + CONFDB_PC_TYPE_PASSWORD, + pam_set_password_prompting_options, + &pc_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "pam_set_prompting_options failed.\n"); + goto done; + } + } + + if (pc_list != NULL) { + ret = pam_get_response_prompt_config(pc_list, &resp_len, &resp_data); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "pam_get_response_prompt_config failed.\n"); + goto done; + } + + ret = pam_add_response(pd, SSS_PAM_PROMPT_CONFIG, resp_len, resp_data); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "pam_add_response failed.\n"); + goto done; + } + } + + ret = EOK; +done: + free(resp_data); + pc_list_free(pc_list); + + return ret; +} |