diff options
Diffstat (limited to 'src/responder')
-rw-r--r-- | src/responder/common/cache_req/plugins/cache_req_common.c | 5 | ||||
-rw-r--r-- | src/responder/common/cache_req/plugins/cache_req_group_by_filter.c | 2 | ||||
-rw-r--r-- | src/responder/common/cache_req/plugins/cache_req_user_by_filter.c | 2 | ||||
-rw-r--r-- | src/responder/kcm/secrets/secrets.c | 4 | ||||
-rw-r--r-- | src/responder/pac/pacsrv_cmd.c | 2 | ||||
-rw-r--r-- | src/responder/pam/pamsrv.h | 11 | ||||
-rw-r--r-- | src/responder/pam/pamsrv_cmd.c | 32 | ||||
-rw-r--r-- | src/responder/pam/pamsrv_passkey.c | 73 | ||||
-rw-r--r-- | src/responder/pam/pamsrv_passkey.h | 4 |
9 files changed, 98 insertions, 37 deletions
diff --git a/src/responder/common/cache_req/plugins/cache_req_common.c b/src/responder/common/cache_req/plugins/cache_req_common.c index 7eb0921..00b9383 100644 --- a/src/responder/common/cache_req/plugins/cache_req_common.c +++ b/src/responder/common/cache_req/plugins/cache_req_common.c @@ -129,7 +129,10 @@ cache_req_common_process_dp_reply(struct cache_req *cr, bool bret; if (ret != EOK) { - CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr, + int msg_level = SSSDBG_IMPORTANT_INFO; + /* ERR_DOMAIN_NOT_FOUND: 'ad_enabled_domains' option can exclude domain */ + if (ret == ERR_DOMAIN_NOT_FOUND) msg_level = SSSDBG_CONF_SETTINGS; + CACHE_REQ_DEBUG(msg_level, cr, "Could not get account info [%d]: %s\n", ret, sss_strerror(ret)); CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c index 1292f18..2f35107 100644 --- a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c @@ -94,7 +94,7 @@ cache_req_group_by_filter_lookup(TALLOC_CTX *mem_ctx, if (is_files_provider(domain)) { recent_filter = NULL; } else { - recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", SYSDB_LAST_UPDATE, + recent_filter = talloc_asprintf(mem_ctx, "(%s>=%"SPRItime")", SYSDB_LAST_UPDATE, cr->req_start); if (recent_filter == NULL) { return ENOMEM; diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c index 11ea9ec..831b783 100644 --- a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c @@ -97,7 +97,7 @@ cache_req_user_by_filter_lookup(TALLOC_CTX *mem_ctx, if (is_files_provider(domain) || data->name.attr != NULL) { recent_filter = NULL; } else { - recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", SYSDB_LAST_UPDATE, + recent_filter = talloc_asprintf(mem_ctx, "(%s>=%"SPRItime")", SYSDB_LAST_UPDATE, cr->req_start); if (recent_filter == NULL) { return ENOMEM; diff --git a/src/responder/kcm/secrets/secrets.c b/src/responder/kcm/secrets/secrets.c index a37edcc..730fa68 100644 --- a/src/responder/kcm/secrets/secrets.c +++ b/src/responder/kcm/secrets/secrets.c @@ -482,7 +482,7 @@ static int local_db_create(struct sss_sec_req *req) goto done; } - ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%lu", time(NULL)); + ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%"SPRItime"", time(NULL)); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed adding creationTime [%d]: %s\n", @@ -1017,7 +1017,7 @@ errno_t sss_sec_put(struct sss_sec_req *req, goto done; } - ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%lu", time(NULL)); + ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%"SPRItime"", time(NULL)); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed adding creationTime [%d]: %s\n", diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c index abfc2c9..d0663d7 100644 --- a/src/responder/pac/pacsrv_cmd.c +++ b/src/responder/pac/pacsrv_cmd.c @@ -146,7 +146,7 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx) ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str, &pr_ctx->dom); if (ret == EAGAIN || ret == ENOENT) { - req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, + req = sss_dp_get_domains_send(cctx, cctx->rctx, true, pr_ctx->domain_name); if (req == NULL) { ret = ENOMEM; diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h index 7013a8e..2aa14ae 100644 --- a/src/responder/pam/pamsrv.h +++ b/src/responder/pam/pamsrv.h @@ -93,7 +93,17 @@ struct pam_auth_req { struct ldb_message *user_obj; struct cert_auth_info *cert_list; struct cert_auth_info *current_cert; + /* Switched to 'true' if the backend indicates that it cannot handle + * Smartcard authentication, but Smartcard authentication is + * possible and local Smartcard authentication is allowed. */ bool cert_auth_local; + /* Switched to 'true' if authentication (not pre-authentication) was + * started without a login name and the name had to be lookup up with the + * certificate used for authentication. Since reading the certificate from + * the Smartcard already involves the PIN validation in this case there + * would be no need for an additional Smartcard interaction if only local + * Smartcard authentication is possible. */ + bool initial_cert_auth_successful; bool passkey_data_exists; uint32_t client_id_num; @@ -104,6 +114,7 @@ struct pam_resp_auth_type { bool otp_auth; bool cert_auth; bool passkey_auth; + bool backend_returned_no_auth_type; }; struct sss_cmd_table *get_pam_cmds(void); diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index c23ea7b..1394147 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -915,6 +915,7 @@ errno_t pam_get_auth_types(struct pam_data *pd, /* If the backend cannot determine which authentication types are * available the default would be to prompt for a password. */ types.password_auth = true; + types.backend_returned_no_auth_type = true; } DEBUG(SSSDBG_TRACE_ALL, "Authentication types for user [%s] and service " @@ -1002,7 +1003,7 @@ static errno_t pam_eval_local_auth_policy(TALLOC_CTX *mem_ctx, } /* Store the local auth types, in case we go offline */ - if (!auth_types.password_auth) { + if (!auth_types.backend_returned_no_auth_type) { ret = set_local_auth_type(preq, sc_allow, passkey_allow); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, @@ -1418,6 +1419,15 @@ void pam_reply(struct pam_auth_req *preq) goto done; } +#ifdef BUILD_PASSKEY + if(pd->cmd == SSS_PAM_AUTHENTICATE && + pd->pam_status == PAM_NEW_AUTHTOK_REQD && + sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_PASSKEY_REPLY) { + DEBUG(SSSDBG_TRACE_FUNC, "Passkey authentication reply, ignoring " + "new authtok required status\n"); + pd->pam_status = PAM_SUCCESS; + } + /* Passkey auth user notification if no TGT is granted */ if (pd->cmd == SSS_PAM_AUTHENTICATE && pd->pam_status == PAM_SUCCESS && @@ -1429,6 +1439,7 @@ void pam_reply(struct pam_auth_req *preq) "User [%s] logged in with local passkey authentication, single " "sign on ticket is not obtained.\n", pd->user); } +#endif /* BUILD_PASSKEY */ /* Account expiration warning is printed for sshd. If pam_verbosity * is equal or above PAM_VERBOSITY_INFO then all services are informed @@ -1918,7 +1929,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) ret = pam_forwarder_parse_data(cctx, pd); if (ret == EAGAIN) { - req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain); + req = sss_dp_get_domains_send(cctx, cctx->rctx, true, pd->domain); if (req == NULL) { ret = ENOMEM; } else { @@ -2200,8 +2211,8 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) ret = ENOENT; goto done; } - - if (cert_count > 1) { + /* Multiple certificates are only expected during pre-auth */ + if (cert_count > 1 && preq->pd->cmd == SSS_PAM_PREAUTH) { for (preq->current_cert = preq->cert_list; preq->current_cert != NULL; preq->current_cert = sss_cai_get_next(preq->current_cert)) { @@ -2285,7 +2296,9 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) } /* If logon_name was not given during authentication add a - * SSS_PAM_CERT_INFO message to send the name to the caller. */ + * SSS_PAM_CERT_INFO message to send the name to the caller. + * Additionally initial_cert_auth_successful is set to + * indicate that the user is already authenticated. */ if (preq->pd->cmd == SSS_PAM_AUTHENTICATE && preq->pd->logon_name == NULL) { ret = add_pam_cert_response(preq->pd, @@ -2297,6 +2310,8 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL; goto done; } + + preq->initial_cert_auth_successful = true; } /* cert_user will be returned to the PAM client as user name, so @@ -2851,12 +2866,15 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) if (found) { if (local_policy != NULL && strcasecmp(local_policy, "only") == 0) { talloc_free(tmp_ctx); - DEBUG(SSSDBG_IMPORTANT_INFO, "Local auth only set, skipping online auth\n"); + DEBUG(SSSDBG_IMPORTANT_INFO, + "Local auth only set and matching certificate was found, " + "skipping online auth\n"); if (preq->pd->cmd == SSS_PAM_PREAUTH) { preq->pd->pam_status = PAM_SUCCESS; } else if (preq->pd->cmd == SSS_PAM_AUTHENTICATE && IS_SC_AUTHTOK(preq->pd->authtok) - && preq->cert_auth_local) { + && (preq->cert_auth_local + || preq->initial_cert_auth_successful)) { preq->pd->pam_status = PAM_SUCCESS; preq->callback = pam_reply; } diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c index 1125840..4a6bf0d 100644 --- a/src/responder/pam/pamsrv_passkey.c +++ b/src/responder/pam/pamsrv_passkey.c @@ -463,6 +463,32 @@ done: return ret; } +static bool mapping_is_passkey(TALLOC_CTX *tmp_ctx, + const char *mapping_str) +{ + int ret; + char **mappings; + + if (mapping_str == NULL) { + return false; + } + + ret = split_on_separator(tmp_ctx, (const char *) mapping_str, ':', true, true, + &mappings, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Incorrectly formatted passkey data [%d]: %s\n", + ret, sss_strerror(ret)); + return false; + } + + if (strcasecmp(mappings[0], "passkey") != 0) { + DEBUG(SSSDBG_TRACE_FUNC, "Mapping data found is not passkey related\n"); + return false; + } + + return true; +} + errno_t process_passkey_data(TALLOC_CTX *mem_ctx, struct ldb_message *user_mesg, const char *domain, @@ -471,6 +497,7 @@ errno_t process_passkey_data(TALLOC_CTX *mem_ctx, struct ldb_message_element *el; TALLOC_CTX *tmp_ctx; int ret; + int num_creds = 0; char **mappings; const char **kh_mappings; const char **public_keys; @@ -489,22 +516,6 @@ errno_t process_passkey_data(TALLOC_CTX *mem_ctx, goto done; } - /* This attribute may contain other mapping data unrelated to passkey. In that case - * let's omit it. For example, AD user altSecurityIdentities may store ssh public key - * or smart card mapping data */ - ret = split_on_separator(tmp_ctx, (const char *) el->values[0].data, ':', true, true, - &mappings, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Incorrectly formatted passkey data [%d]: %s\n", - ret, sss_strerror(ret)); - ret = ENOENT; - goto done; - } else if (strcasecmp(mappings[0], "passkey") != 0) { - DEBUG(SSSDBG_TRACE_FUNC, "Mapping data found is not passkey related\n"); - ret = ENOENT; - goto done; - } - kh_mappings = talloc_zero_array(tmp_ctx, const char *, el->num_values + 1); if (kh_mappings == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); @@ -520,6 +531,12 @@ errno_t process_passkey_data(TALLOC_CTX *mem_ctx, } for (int i = 0; i < el->num_values; i++) { + /* This attribute may contain other mapping data unrelated to passkey. In that case + * let's skip it. For example, AD user altSecurityIdentities may store ssh public key + * or smart card mapping data */ + if ((mapping_is_passkey(tmp_ctx, (const char *)el->values[i].data)) == false) { + continue; + } ret = split_on_separator(tmp_ctx, (const char *) el->values[i].data, ',', true, true, &mappings, NULL); if (ret != EOK) { @@ -528,19 +545,26 @@ errno_t process_passkey_data(TALLOC_CTX *mem_ctx, goto done; } - kh_mappings[i] = talloc_strdup(kh_mappings, mappings[0] + strlen(PASSKEY_PREFIX)); - if (kh_mappings[i] == NULL) { + kh_mappings[num_creds] = talloc_strdup(kh_mappings, mappings[0] + strlen(PASSKEY_PREFIX)); + if (kh_mappings[num_creds] == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup key handle failed.\n"); ret = ENOMEM; goto done; } - public_keys[i] = talloc_strdup(public_keys, mappings[1]); - if (public_keys[i] == NULL) { + public_keys[num_creds] = talloc_strdup(public_keys, mappings[1]); + if (public_keys[num_creds] == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup public key failed.\n"); ret = ENOMEM; goto done; } + + num_creds++; + } + + if (num_creds == 0) { + ret = ENOENT; + goto done; } domain_name = talloc_strdup(tmp_ctx, domain); @@ -553,7 +577,7 @@ errno_t process_passkey_data(TALLOC_CTX *mem_ctx, _data->domain = talloc_steal(mem_ctx, domain_name); _data->key_handles = talloc_steal(mem_ctx, kh_mappings); _data->public_keys = talloc_steal(mem_ctx, public_keys); - _data->num_credentials = el->num_values; + _data->num_credentials = num_creds; ret = EOK; done: @@ -707,10 +731,11 @@ done: pctx->preq->passkey_data_exists = false; pam_check_user_search(pctx->preq); } else if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unexpected passkey error [%d]: %s." - " Skipping passkey auth\n", + DEBUG(SSSDBG_OP_FAILURE, "Unexpected passkey error [%d]: %s.\n", ret, sss_strerror(ret)); - pam_check_user_search(pctx->preq); + pctx->preq->passkey_data_exists = false; + pctx->preq->pd->pam_status = PAM_SYSTEM_ERR; + pam_reply(pctx->preq); } return; diff --git a/src/responder/pam/pamsrv_passkey.h b/src/responder/pam/pamsrv_passkey.h index 7c5a532..48074d0 100644 --- a/src/responder/pam/pamsrv_passkey.h +++ b/src/responder/pam/pamsrv_passkey.h @@ -77,6 +77,10 @@ errno_t pam_eval_passkey_response(struct pam_ctx *pctx, struct pam_data *pd, struct pam_auth_req *preq, bool *_pk_preauth_done); +errno_t process_passkey_data(TALLOC_CTX *mem_ctx, + struct ldb_message *user_mesg, + const char *domain, + struct pk_child_user_data *_data); bool may_do_passkey_auth(struct pam_ctx *pctx, struct pam_data *pd); |