From 74a180ce2644cc86b1ac49f6732e9410641673cb Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 21 Oct 2025 11:53:45 -0400 Subject: [PATCH 01/39] DO NOT PUSH TO MASTER minimal: Initial implementation of minimal provider (cherry picked from commit 0f5f3b61a0fa529d777f2c8b2552f91fea2e8d0b) --- Makefile.am | 24 +++ minimal-provider-notes.txt | 39 +++++ src/providers/minimal/minimal_id.c | 240 +++++++++++++++++++++++++++ src/providers/minimal/minimal_id.h | 51 ++++++ src/providers/minimal/minimal_init.c | 211 +++++++++++++++++++++++ src/tests/dlopen-tests.c | 2 + 6 files changed, 567 insertions(+) create mode 100644 minimal-provider-notes.txt create mode 100644 src/providers/minimal/minimal_id.c create mode 100644 src/providers/minimal/minimal_id.h create mode 100644 src/providers/minimal/minimal_init.c diff --git a/Makefile.am b/Makefile.am index d55dc358528..c1f42a82681 100644 --- a/Makefile.am +++ b/Makefile.am @@ -422,6 +422,10 @@ sssdlib_LTLIBRARIES += \ $(NULL) endif +sssdlib_LTLIBRARIES += \ + libsss_minimal.la \ + $(NULL) + ldblib_LTLIBRARIES = \ memberof.la @@ -911,6 +915,7 @@ dist_noinst_HEADERS = \ src/providers/idp/idp_id.h \ src/providers/idp/idp_opts.h \ src/providers/idp/idp_private.h \ + src/providers/minimal/minimal_id.h \ src/tools/tools_util.h \ src/resolv/async_resolv.h \ src/tests/common.h \ @@ -4717,6 +4722,25 @@ libsss_idp_la_LDFLAGS = \ -module \ $(NULL) +libsss_minimal_la_SOURCES = \ + src/providers/minimal/minimal_init.c \ + src/providers/minimal/minimal_id.c \ + $(NULL) + +libsss_minimal_la_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) + +libsss_minimal_la_LIBADD = \ + $(SSSD_INTERNAL_LTLIBS) \ + libsss_ldap_common.la \ + $(NULL) + +libsss_minimal_la_LDFLAGS = \ + -avoid-version \ + -module \ + $(NULL) + krb5_child_SOURCES = \ src/providers/krb5/krb5_child.c \ src/providers/krb5/krb5_child_share.c \ diff --git a/minimal-provider-notes.txt b/minimal-provider-notes.txt new file mode 100644 index 00000000000..1c0157ee1cb --- /dev/null +++ b/minimal-provider-notes.txt @@ -0,0 +1,39 @@ +-- On sssd-ci-containers podman 'ldap' container, create services.ldif + + $ vim services.ldif + dn: ou=services,dc=ldap,dc=test + objectClass: top + objectClass: organizationalUnit + ou: services + + dn: cn=service0,ou=services,dc=ldap,dc=test + objectClass: ipService + cn: service0 + ipServiceProtocol: tcp + ipServicePort: 12345 + +-- Add services OU and object to LDAP + + $ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -f services.ldif -vv + +-- Verify the entries were added + + $ ldapsearch -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -b ou=services,dc=ldap,dc=test + +--- On SSSD client with minimal provider installed, add the domain below to sssd.conf: + + [sssd] + domains = testmin + + [domain/testmin] + id_provider = minimal + # failover to backup uri + ldap_uri = ldap://invalid.ldap.test/ + ldap_backup_uri = ldap://master.ldap.test/ + ldap_id_use_start_tls = false + debug_level = 9 + +-- Restart SSSD and test + + # getent services -s sss service0 + service0 12345/tcp diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c new file mode 100644 index 00000000000..c495140d16c --- /dev/null +++ b/src/providers/minimal/minimal_id.c @@ -0,0 +1,240 @@ +/* + SSSD + + minimal Identity Backend Module + + Authors: + Justin Stephenson + + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include + +#include "util/util.h" +#include "providers/minimal/minimal_id.h" + +struct minimal_handle_acct_req_state { + struct dp_id_data *ar; + const char *err; + int dp_error; + int minimal_ret; + int sdap_ret; +}; + +static void minimal_handle_acct_req_done(struct tevent_req *subreq); + +static struct tevent_req * +minimal_handle_acct_req_send(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct dp_id_data *ar, + struct sdap_id_ctx *id_ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn, + bool noexist_delete) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct minimal_handle_acct_req_state *state; + errno_t ret; + + + req = tevent_req_create(mem_ctx, &state, + struct minimal_handle_acct_req_state); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create() failed.\n"); + return NULL; + } + state->ar = ar; + + if (ar == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Missing input.\n"); + ret = EINVAL; + goto done; + } + + switch (ar->entry_type & BE_REQ_TYPE_MASK) { + case BE_REQ_SERVICES: + DEBUG(SSSDBG_TRACE_FUNC, "Executing BE_REQ_SERVICES request\n"); + subreq = services_get_send(state, be_ctx->ev, id_ctx, + sdom, conn, + ar->filter_value, + ar->extra_value, + ar->filter_type, + noexist_delete); + break; + default: /*fail*/ + ret = EINVAL; + state->err = "Invalid request type"; + DEBUG(SSSDBG_OP_FAILURE, + "Unexpected request type: 0x%X [%s:%s] in %s\n", + ar->entry_type, ar->filter_value, + ar->extra_value?ar->extra_value:"-", + ar->domain); + goto done; + } + + if (!subreq) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, minimal_handle_acct_req_done, req); + return req; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + + tevent_req_post(req, be_ctx->ev); + return req; +} + +static void minimal_handle_acct_req_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct minimal_handle_acct_req_state *state; + errno_t ret; + const char *err = "Invalid request type"; + + state = tevent_req_data(req, struct minimal_handle_acct_req_state); + + switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { + case BE_REQ_SERVICES: + err = "Service lookup failed"; + ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret); + break; + default: /* fail */ + ret = EINVAL; + break; + } + talloc_zfree(subreq); + + if (ret != EOK) { + state->err = err; + tevent_req_error(req, ret); + return; + } + + state->err = "Success"; + tevent_req_done(req); +} + +static errno_t +minimal_handle_acct_req_recv(struct tevent_req *req, + int *_dp_error, const char **_err, + int *minimal_ret) +{ + struct minimal_handle_acct_req_state *state; + + state = tevent_req_data(req, struct minimal_handle_acct_req_state); + + if (_dp_error) { + *_dp_error = state->dp_error; + } + + if (_err) { + *_err = state->err; + } + + if (minimal_ret) { + *minimal_ret = state->minimal_ret; + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +struct minimal_account_info_handler_state { + struct dp_reply_std reply; +}; + +static void minimal_account_info_handler_done(struct tevent_req *subreq); + +struct tevent_req * +minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + struct dp_id_data *data, + struct dp_req_params *params) +{ + struct minimal_account_info_handler_state *state; + struct tevent_req *subreq = NULL; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct minimal_account_info_handler_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + subreq = minimal_handle_acct_req_send(state, params->be_ctx, data, id_ctx, + id_ctx->opts->sdom, id_ctx->conn, true); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "minimal_handle_acct_req_send() failed.\n"); + ret = ENOMEM; + goto immediately; + } + + tevent_req_set_callback(subreq, minimal_account_info_handler_done, req); + + return req; + +immediately: + dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + + tevent_req_done(req); + tevent_req_post(req, params->ev); + + return req; +} + +static void minimal_account_info_handler_done(struct tevent_req *subreq) +{ + struct minimal_account_info_handler_state *state; + struct tevent_req *req; + const char *error_msg = NULL; + int dp_error = DP_ERR_FATAL; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct minimal_account_info_handler_state); + + ret = minimal_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL); + talloc_zfree(subreq); + + dp_reply_std_set(&state->reply, dp_error, ret, error_msg); + tevent_req_done(req); +} + +errno_t minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data) +{ + struct minimal_account_info_handler_state *state = NULL; + + state = tevent_req_data(req, struct minimal_account_info_handler_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *data = state->reply; + + return EOK; +} diff --git a/src/providers/minimal/minimal_id.h b/src/providers/minimal/minimal_id.h new file mode 100644 index 00000000000..1ac40c8e148 --- /dev/null +++ b/src/providers/minimal/minimal_id.h @@ -0,0 +1,51 @@ +/* + SSSD + + minimal Identity Backend Module + + Authors: + Justin Stephenson + + Copyright (C) 2025 Red Hat + + 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 . +*/ + + +#ifndef _MINIMAL_ID_H_ +#define _MINIMAL_ID_H_ + +#include "config.h" +#include + +#include "providers/backend.h" +#include "providers/ldap/ldap_common.h" +#include "util/util.h" + +struct minimal_id_ctx { + struct be_ctx *be_ctx; + struct minimal_init_ctx *init_ctx; + struct dp_option *minimal_options; +}; + +struct tevent_req * +minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + struct dp_id_data *data, + struct dp_req_params *params); + +errno_t minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data); +#endif diff --git a/src/providers/minimal/minimal_init.c b/src/providers/minimal/minimal_init.c new file mode 100644 index 00000000000..d27791968be --- /dev/null +++ b/src/providers/minimal/minimal_init.c @@ -0,0 +1,211 @@ +/* + SSSD + + minimal Provider Initialization functions + + Authors: + Justin Stephenson + + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include "src/providers/data_provider.h" +#include "providers/ldap/ldap_common.h" +#include "providers/ldap/ldap_opts.h" +#include "providers/ldap/sdap_async_private.h" +#include "providers/ldap/sdap_access.h" +#include "providers/ldap/ldap_resolver_enum.h" +#include "providers/fail_over_srv.h" +#include "providers/be_refresh.h" + +#include "src/providers/minimal/minimal_id.h" + +struct minimal_init_ctx { + struct sdap_options *options; + struct sdap_id_ctx *id_ctx; +}; + +/* Copied from ldap_init.c with no changes */ +static errno_t get_sdap_service(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts, + struct sdap_service **_sdap_service) +{ + errno_t ret; + const char *urls; + const char *backup_urls; + const char *dns_service_name; + struct sdap_service *sdap_service; + + urls = dp_opt_get_string(opts->basic, SDAP_URI); + backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI); + dns_service_name = dp_opt_get_string(opts->basic, SDAP_DNS_SERVICE_NAME); + if (dns_service_name != NULL) { + DEBUG(SSSDBG_CONF_SETTINGS, + "Service name for discovery set to %s\n", dns_service_name); + } + + ret = sdap_service_init(mem_ctx, be_ctx, "LDAP", + dns_service_name, + urls, + backup_urls, + &sdap_service); + if (ret != EOK) { + return ret; + } + + *_sdap_service = sdap_service; + return EOK; +} + +/* Copied from ldap_init.c with some changes + * removing calls to + * - sdap_gssapi_init() + * - sdap_idmap_init() + * - confdb_certmap_to_sysdb() + * - sdap_init_certmap() */ +static errno_t ldap_init_misc(struct be_ctx *be_ctx, + struct sdap_options *options, + struct sdap_id_ctx *id_ctx) +{ + errno_t ret; + + setup_ldap_debug(options->basic); + + ret = setup_tls_config(options->basic); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get TLS options [%d]: %s\n", + ret, sss_strerror(ret)); + return ret; + } + + ret = ldap_id_setup_tasks(id_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup background tasks " + "[%d]: %s\n", ret, sss_strerror(ret)); + return ret; + } + + /* Setup SRV lookup plugin */ + ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " + "[%d]: %s\n", ret, sss_strerror(ret)); + return ret; + } + + /* Setup periodical refresh of expired records */ + ret = sdap_refresh_init(be_ctx, id_ctx); + if (ret != EOK && ret != EEXIST) { + DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh will not work " + "[%d]: %s\n", ret, sss_strerror(ret)); + } + + return EOK; +} + +errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct data_provider *provider, + const char *module_name, + void **_module_data) +{ + struct sdap_service *sdap_service; + struct minimal_init_ctx *init_ctx; + errno_t ret; + + init_ctx = talloc_zero(mem_ctx, struct minimal_init_ctx); + if (init_ctx == NULL) { + return ENOMEM; + } + + /* Always initialize options since it is needed everywhere. */ + ret = ldap_get_options(init_ctx, be_ctx->domain, be_ctx->cdb, + be_ctx->conf_path, be_ctx->provider, + &init_ctx->options); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP options " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + /* Always initialize id_ctx since it is needed everywhere. */ + ret = get_sdap_service(init_ctx, be_ctx, init_ctx->options, &sdap_service); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + init_ctx->id_ctx = sdap_id_ctx_new(init_ctx, be_ctx, sdap_service); + if (init_ctx->id_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP ID context\n"); + ret = ENOMEM; + goto done; + } + + init_ctx->id_ctx->opts = init_ctx->options; + + /* Setup miscellaneous things. */ + ret = ldap_init_misc(be_ctx, init_ctx->options, init_ctx->id_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init LDAP module " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + *_module_data = init_ctx; + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(init_ctx); + } + + return ret; +} + +errno_t sssm_minimal_id_init(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + void *module_data, + struct dp_method *dp_methods) +{ + struct minimal_init_ctx *init_ctx; + struct sdap_id_ctx *id_ctx; + errno_t ret; + + init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); + id_ctx = init_ctx->id_ctx; + + dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER, + minimal_account_info_handler_send, minimal_account_info_handler_recv, id_ctx, + struct sdap_id_ctx, struct dp_id_data, struct dp_reply_std); + + /* LDAP provider check online handler */ + dp_set_method(dp_methods, DPM_CHECK_ONLINE, + sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx, + struct sdap_id_ctx, void, struct dp_reply_std); + + dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, + default_account_domain_send, default_account_domain_recv, NULL, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + + init_ctx->id_ctx = id_ctx; + ret = EOK; + + return ret; +} diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c index ceaaedc5d5d..878f8767fc4 100644 --- a/src/tests/dlopen-tests.c +++ b/src/tests/dlopen-tests.c @@ -111,6 +111,8 @@ struct so { { "libsss_idp.so", { LIBPFX"libdlopen_test_providers.so", LIBPFX"libsss_idp.so", NULL } }, #endif /* BUILD_ID_PROVIDER_IDP */ + { "libsss_minimal.so", { LIBPFX"libdlopen_test_providers.so", + LIBPFX"libsss_minimal.so", NULL } }, #ifdef HAVE_PYTHON2_BINDINGS { "_py2hbac.so", { LIBPFX"_py2hbac.so", NULL } }, { "_py2sss.so", { LIBPFX"_py2sss.so", NULL } }, From 588f4dff1117dbff8a17412d6817b52437c7e1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 17 Dec 2025 14:24:05 +0100 Subject: [PATCH 02/39] DO NOT PUSH TO MASTER minimal: copy paste services code so it can be directly modified --- Makefile.am | 1 + src/providers/minimal/minimal_id.c | 14 + src/providers/minimal/minimal_id_services.c | 308 ++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 src/providers/minimal/minimal_id_services.c diff --git a/Makefile.am b/Makefile.am index c1f42a82681..66ab6ebdd88 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4725,6 +4725,7 @@ libsss_idp_la_LDFLAGS = \ libsss_minimal_la_SOURCES = \ src/providers/minimal/minimal_init.c \ src/providers/minimal/minimal_id.c \ + src/providers/minimal/minimal_id_services.c \ $(NULL) libsss_minimal_la_CFLAGS = \ diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c index c495140d16c..7eb861eab4e 100644 --- a/src/providers/minimal/minimal_id.c +++ b/src/providers/minimal/minimal_id.c @@ -27,6 +27,20 @@ #include "util/util.h" #include "providers/minimal/minimal_id.h" +struct tevent_req * +minimal_services_get_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_ctx *id_ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn, + const char *name, + const char *protocol, + int filter_type, + bool noexist_delete); + +errno_t +minimal_services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); + struct minimal_handle_acct_req_state { struct dp_id_data *ar; const char *err; diff --git a/src/providers/minimal/minimal_id_services.c b/src/providers/minimal/minimal_id_services.c new file mode 100644 index 00000000000..4ca6a46ec82 --- /dev/null +++ b/src/providers/minimal/minimal_id_services.c @@ -0,0 +1,308 @@ +/* + SSSD + + Authors: + Stephen Gallagher + + Copyright (C) 2012 Red Hat + + 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 . +*/ + + +#include + +#include "util/util.h" +#include "util/strtonum.h" +#include "db/sysdb.h" +#include "db/sysdb_services.h" +#include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_async.h" + +struct sdap_services_get_state { + struct tevent_context *ev; + struct sdap_id_ctx *id_ctx; + struct sdap_domain *sdom; + struct sdap_id_op *op; + struct sysdb_ctx *sysdb; + struct sss_domain_info *domain; + struct sdap_id_conn_ctx *conn; + + const char *name; + const char *protocol; + + char *filter; + const char **attrs; + + int filter_type; + + int dp_error; + int sdap_ret; + bool noexist_delete; +}; + +static errno_t +services_get_retry(struct tevent_req *req); +static void +services_get_connect_done(struct tevent_req *subreq); +static void +services_get_done(struct tevent_req *subreq); + +struct tevent_req * +minimal_services_get_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_ctx *id_ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn, + const char *name, + const char *protocol, + int filter_type, + bool noexist_delete) +{ + errno_t ret; + struct tevent_req *req; + struct sdap_services_get_state *state; + const char *attr_name; + char *clean_name; + char *clean_protocol = NULL; + + req = tevent_req_create(mem_ctx, &state, struct sdap_services_get_state); + if (!req) return NULL; + + state->ev = ev; + state->id_ctx = id_ctx; + state->sdom = sdom; + state->conn = conn; + state->dp_error = DP_ERR_FATAL; + state->domain = sdom->dom; + state->sysdb = sdom->dom->sysdb; + state->name = name; + state->protocol = protocol; + state->filter_type = filter_type; + state->noexist_delete = noexist_delete; + + state->op = sdap_id_op_create(state, state->conn->conn_cache); + if (!state->op) { + DEBUG(SSSDBG_MINOR_FAILURE, "sdap_id_op_create failed\n"); + ret = ENOMEM; + goto error; + } + + switch(filter_type) { + case BE_FILTER_NAME: + attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_NAME].name; + break; + case BE_FILTER_IDNUM: + attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_PORT].name; + break; + default: + ret = EINVAL; + goto error; + } + + ret = sss_filter_sanitize(state, name, &clean_name); + if (ret != EOK) goto error; + + if (protocol != NULL) { + ret = sss_filter_sanitize(state, protocol, &clean_protocol); + if (ret != EOK) goto error; + } + + if (clean_protocol) { + state->filter = talloc_asprintf( + state, "(&(%s=%s)(%s=%s)(objectclass=%s))", + attr_name, clean_name, + id_ctx->opts->service_map[SDAP_AT_SERVICE_PROTOCOL].name, + clean_protocol, + id_ctx->opts->service_map[SDAP_OC_SERVICE].name); + } else { + state->filter = + talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", + attr_name, clean_name, + id_ctx->opts->service_map[SDAP_OC_SERVICE].name); + } + talloc_zfree(clean_name); + talloc_zfree(clean_protocol); + if (!state->filter) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Failed to build the base filter\n"); + ret = ENOMEM; + goto error; + } + DEBUG(SSSDBG_TRACE_LIBS, + "Preparing to search for services with filter [%s]\n", + state->filter); + + ret = build_attrs_from_map(state, id_ctx->opts->service_map, + SDAP_OPTS_SERVICES, NULL, + &state->attrs, NULL); + if (ret != EOK) goto error; + + ret = services_get_retry(req); + if (ret != EOK) goto error; + + return req; + +error: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static errno_t +services_get_retry(struct tevent_req *req) +{ + errno_t ret; + struct sdap_services_get_state *state = + tevent_req_data(req, struct sdap_services_get_state); + struct tevent_req *subreq; + + subreq = sdap_id_op_connect_send(state->op, state, &ret); + if (!subreq) { + return ret; + } + + tevent_req_set_callback(subreq, services_get_connect_done, req); + return EOK; +} + +static void +services_get_connect_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_services_get_state *state = + tevent_req_data(req, struct sdap_services_get_state); + int dp_error = DP_ERR_FATAL; + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + + subreq = sdap_get_services_send(state, state->ev, + state->domain, state->sysdb, + state->id_ctx->opts, + state->sdom->service_search_bases, + sdap_id_op_handle(state->op), + state->attrs, state->filter, + dp_opt_get_int(state->id_ctx->opts->basic, + SDAP_SEARCH_TIMEOUT), + false); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, services_get_done, req); +} + +static void +services_get_done(struct tevent_req *subreq) +{ + errno_t ret; + uint16_t port; + char *endptr; + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_services_get_state *state = + tevent_req_data(req, struct sdap_services_get_state); + int dp_error = DP_ERR_FATAL; + + ret = sdap_get_services_recv(NULL, subreq, NULL); + talloc_zfree(subreq); + + /* Check whether we need to try again with another + * failover server. + */ + ret = sdap_id_op_done(state->op, ret, &dp_error); + if (dp_error == DP_ERR_OK && ret != EOK) { + /* retry */ + ret = services_get_retry(req); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + /* Return to the mainloop to retry */ + return; + } + state->sdap_ret = ret; + + /* An error occurred. */ + if (ret && ret != ENOENT) { + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + + if (ret == ENOENT && state->noexist_delete == true) { + /* Ensure that this entry is removed from the sysdb */ + switch(state->filter_type) { + case BE_FILTER_NAME: + ret = sysdb_svc_delete(state->domain, state->name, + 0, state->protocol); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + break; + + case BE_FILTER_IDNUM: + port = strtouint16(state->name, &endptr, 10); + if (errno || *endptr || (state->name == endptr)) { + tevent_req_error(req, (errno ? errno : EINVAL)); + return; + } + + ret = sysdb_svc_delete(state->domain, NULL, port, + state->protocol); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + break; + + default: + tevent_req_error(req, EINVAL); + return; + } + } + + state->dp_error = DP_ERR_OK; + tevent_req_done(req); +} + +errno_t +minimal_services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +{ + struct sdap_services_get_state *state = + tevent_req_data(req, struct sdap_services_get_state); + + if (dp_error_out) { + *dp_error_out = state->dp_error; + } + + if (sdap_ret) { + *sdap_ret = state->sdap_ret; + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} From 6373cd21e30b73e30ded732e10649c7c32743128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Thu, 18 Dec 2025 13:30:13 +0100 Subject: [PATCH 03/39] DO NOT PUSH TO MASTER minimal: push init_ctx instead of id_ctx so we can easily pass new fctx --- src/providers/minimal/minimal.h | 39 ++++++++++++++++++++++++++++ src/providers/minimal/minimal_id.c | 16 +++++++----- src/providers/minimal/minimal_id.h | 6 ++--- src/providers/minimal/minimal_init.c | 17 ++++-------- 4 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 src/providers/minimal/minimal.h diff --git a/src/providers/minimal/minimal.h b/src/providers/minimal/minimal.h new file mode 100644 index 00000000000..645aa26ef5b --- /dev/null +++ b/src/providers/minimal/minimal.h @@ -0,0 +1,39 @@ +/* + SSSD + + minimal Identity Backend Module + + Authors: + Justin Stephenson + + Copyright (C) 2025 Red Hat + + 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 . +*/ + + +#ifndef _MINIMAL_H_ +#define _MINIMAL_H_ + +#include "config.h" +#include + +#include "providers/ldap/ldap_common.h" + +struct minimal_init_ctx { + struct sdap_options *options; + struct sdap_id_ctx *id_ctx; +}; + +#endif diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c index 7eb861eab4e..e9450f97416 100644 --- a/src/providers/minimal/minimal_id.c +++ b/src/providers/minimal/minimal_id.c @@ -25,6 +25,7 @@ #include #include "util/util.h" +#include "providers/minimal/minimal.h" #include "providers/minimal/minimal_id.h" struct tevent_req * @@ -183,7 +184,7 @@ static void minimal_account_info_handler_done(struct tevent_req *subreq); struct tevent_req * minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, + struct minimal_init_ctx *init_ctx, struct dp_id_data *data, struct dp_req_params *params) { @@ -199,8 +200,10 @@ minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, return NULL; } - subreq = minimal_handle_acct_req_send(state, params->be_ctx, data, id_ctx, - id_ctx->opts->sdom, id_ctx->conn, true); + subreq = minimal_handle_acct_req_send(state, params->be_ctx, data, + init_ctx->id_ctx, + init_ctx->id_ctx->opts->sdom, + init_ctx->id_ctx->conn, true); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "minimal_handle_acct_req_send() failed.\n"); ret = ENOMEM; @@ -238,9 +241,10 @@ static void minimal_account_info_handler_done(struct tevent_req *subreq) tevent_req_done(req); } -errno_t minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct dp_reply_std *data) +errno_t +minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data) { struct minimal_account_info_handler_state *state = NULL; diff --git a/src/providers/minimal/minimal_id.h b/src/providers/minimal/minimal_id.h index 1ac40c8e148..d7f9e79a24c 100644 --- a/src/providers/minimal/minimal_id.h +++ b/src/providers/minimal/minimal_id.h @@ -41,9 +41,9 @@ struct minimal_id_ctx { struct tevent_req * minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, - struct dp_id_data *data, - struct dp_req_params *params); + struct minimal_init_ctx *init_ctx, + struct dp_id_data *data, + struct dp_req_params *params); errno_t minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, diff --git a/src/providers/minimal/minimal_init.c b/src/providers/minimal/minimal_init.c index d27791968be..e75866c9380 100644 --- a/src/providers/minimal/minimal_init.c +++ b/src/providers/minimal/minimal_init.c @@ -31,13 +31,9 @@ #include "providers/fail_over_srv.h" #include "providers/be_refresh.h" +#include "src/providers/minimal/minimal.h" #include "src/providers/minimal/minimal_id.h" -struct minimal_init_ctx { - struct sdap_options *options; - struct sdap_id_ctx *id_ctx; -}; - /* Copied from ldap_init.c with no changes */ static errno_t get_sdap_service(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, @@ -185,26 +181,23 @@ errno_t sssm_minimal_id_init(TALLOC_CTX *mem_ctx, struct dp_method *dp_methods) { struct minimal_init_ctx *init_ctx; - struct sdap_id_ctx *id_ctx; errno_t ret; init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); - id_ctx = init_ctx->id_ctx; dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER, - minimal_account_info_handler_send, minimal_account_info_handler_recv, id_ctx, - struct sdap_id_ctx, struct dp_id_data, struct dp_reply_std); + minimal_account_info_handler_send, minimal_account_info_handler_recv, init_ctx, + struct minimal_init_ctx, struct dp_id_data, struct dp_reply_std); /* LDAP provider check online handler */ dp_set_method(dp_methods, DPM_CHECK_ONLINE, - sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx, - struct sdap_id_ctx, void, struct dp_reply_std); + sdap_online_check_handler_send, sdap_online_check_handler_recv, init_ctx, + struct minimal_init_ctx, void, struct dp_reply_std); dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, default_account_domain_send, default_account_domain_recv, NULL, void, struct dp_get_acct_domain_data, struct dp_reply_std); - init_ctx->id_ctx = id_ctx; ret = EOK; return ret; From 25c672f2be02f05e75033d508d46df83f827edc0 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 14 Jan 2026 15:29:17 -0500 Subject: [PATCH 04/39] DO NOT PUSH TO MASTER minimal: add authentication provider --- src/providers/minimal/minimal.h | 1 + src/providers/minimal/minimal_init.c | 53 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/providers/minimal/minimal.h b/src/providers/minimal/minimal.h index 645aa26ef5b..f8f004a3c41 100644 --- a/src/providers/minimal/minimal.h +++ b/src/providers/minimal/minimal.h @@ -34,6 +34,7 @@ struct minimal_init_ctx { struct sdap_options *options; struct sdap_id_ctx *id_ctx; + struct sdap_auth_ctx *auth_ctx; }; #endif diff --git a/src/providers/minimal/minimal_init.c b/src/providers/minimal/minimal_init.c index e75866c9380..500000f78f5 100644 --- a/src/providers/minimal/minimal_init.c +++ b/src/providers/minimal/minimal_init.c @@ -113,6 +113,30 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, return EOK; } +/* Copied from ldap_init.c */ +static errno_t minimal_init_auth_ctx(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_id_ctx *id_ctx, + struct sdap_options *options, + struct sdap_auth_ctx **_auth_ctx) +{ + struct sdap_auth_ctx *auth_ctx; + + auth_ctx = talloc(mem_ctx, struct sdap_auth_ctx); + if (auth_ctx == NULL) { + return ENOMEM; + } + + auth_ctx->be = be_ctx; + auth_ctx->opts = options; + auth_ctx->service = id_ctx->conn->service; + auth_ctx->chpass_service = NULL; + + *_auth_ctx = auth_ctx; + + return EOK; +} + errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, @@ -163,6 +187,17 @@ errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx, goto done; } + /* Initialize auth_ctx only if DPT_AUTH target is enabled. */ + if (dp_target_enabled(provider, module_name, DPT_AUTH)) { + ret = minimal_init_auth_ctx(init_ctx, be_ctx, init_ctx->id_ctx, + init_ctx->options, &init_ctx->auth_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create auth context " + "[%d]: %s\n", ret, sss_strerror(ret)); + return ret; + } + } + *_module_data = init_ctx; ret = EOK; @@ -202,3 +237,21 @@ errno_t sssm_minimal_id_init(TALLOC_CTX *mem_ctx, return ret; } + +errno_t sssm_minimal_auth_init(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + void *module_data, + struct dp_method *dp_methods) +{ + struct minimal_init_ctx *init_ctx; + struct sdap_auth_ctx *auth_ctx; + + init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); + auth_ctx = init_ctx->auth_ctx; + + dp_set_method(dp_methods, DPM_AUTH_HANDLER, + sdap_pam_auth_handler_send, sdap_pam_auth_handler_recv, auth_ctx, + struct sdap_auth_ctx, struct pam_data, struct pam_data *); + + return EOK; +} From 37043c2324db9c1e4560477a212839da3cfd329c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 21 Jan 2026 11:42:20 +0100 Subject: [PATCH 05/39] DO NOT PUSH TO MASTER minimal: copy paste authentication code So it can be modified later. --- Makefile.am | 2 + src/providers/minimal/minimal_ldap_auth.c | 916 ++++++++++++++++++++++ src/providers/minimal/minimal_ldap_auth.h | 48 ++ 3 files changed, 966 insertions(+) create mode 100644 src/providers/minimal/minimal_ldap_auth.c create mode 100644 src/providers/minimal/minimal_ldap_auth.h diff --git a/Makefile.am b/Makefile.am index 66ab6ebdd88..d0d705d54fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4726,6 +4726,8 @@ libsss_minimal_la_SOURCES = \ src/providers/minimal/minimal_init.c \ src/providers/minimal/minimal_id.c \ src/providers/minimal/minimal_id_services.c \ + src/providers/minimal/minimal_ldap_auth.c \ + $(SSSD_NEW_FAILOVER_OBJ) \ $(NULL) libsss_minimal_la_CFLAGS = \ diff --git a/src/providers/minimal/minimal_ldap_auth.c b/src/providers/minimal/minimal_ldap_auth.c new file mode 100644 index 00000000000..82804271742 --- /dev/null +++ b/src/providers/minimal/minimal_ldap_auth.c @@ -0,0 +1,916 @@ +/* + SSSD + + LDAP Backend Module + + Authors: + Sumit Bose + + Copyright (C) 2008 Red Hat + Copyright (C) 2010, rhafer@suse.de, Novell Inc. + + 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 . +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include + +#include "util/util.h" +#include "util/user_info_msg.h" +#include "db/sysdb.h" +#include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_async.h" +#include "providers/ldap/sdap_async_private.h" +#include "providers/ldap/ldap_auth.h" +#include "providers/minimal/minimal.h" + +static errno_t +find_password_expiration_attributes(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + enum sdap_access_type access_type, + struct dp_option *opts, + enum pwexpire *pwd_exp_type, + void **data) +{ + const char *mark; + const char *val; + struct spwd *spwd; + const char *pwd_policy; + int ret; + + *pwd_exp_type = PWEXPIRE_NONE; + *data = NULL; + + switch (access_type) { + case SDAP_TYPE_IPA: + /* MIT-Kerberos is the only option for IPA */ + pwd_policy = PWD_POL_OPT_MIT; + break; + case SDAP_TYPE_LDAP: + pwd_policy = dp_opt_get_string(opts, SDAP_PWD_POLICY); + if (pwd_policy == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing password policy.\n"); + return EINVAL; + } + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE,"Unknown access_type [%i].\n", access_type); + return EINVAL; + } + + if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) == 0) { + DEBUG(SSSDBG_TRACE_ALL, "No password policy requested.\n"); + return EOK; + } else if (strcasecmp(pwd_policy, PWD_POL_OPT_MIT) == 0) { + mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL); + if (mark != NULL) { + DEBUG(SSSDBG_TRACE_ALL, + "Found Kerberos password expiration attributes.\n"); + val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION, + NULL); + if (val != NULL) { + *data = talloc_strdup(mem_ctx, val); + if (*data == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n"); + return ENOMEM; + } + *pwd_exp_type = PWEXPIRE_KERBEROS; + + return EOK; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "No Kerberos password expiration attributes found, " + "but MIT Kerberos password policy was requested. " + "Access will be denied.\n"); + return EACCES; + } + } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) { + mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); + if (mark != NULL) { + DEBUG(SSSDBG_TRACE_ALL, + "Found shadow password expiration attributes.\n"); + spwd = talloc_zero(mem_ctx, struct spwd); + if (spwd == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n"); + return ENOMEM; + } + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_lstchg); + if (ret != EOK) goto shadow_fail; + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_min); + if (ret != EOK) goto shadow_fail; + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_max); + if (ret != EOK) goto shadow_fail; + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_warn); + if (ret != EOK) goto shadow_fail; + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_inact); + if (ret != EOK) goto shadow_fail; + + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_expire); + if (ret != EOK) goto shadow_fail; + + *data = spwd; + *pwd_exp_type = PWEXPIRE_SHADOW; + + return EOK; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "No shadow password attributes found, " + "but shadow password policy was requested. " + "Access will be denied.\n"); + return EACCES; + } + } + + DEBUG(SSSDBG_TRACE_ALL, "No password expiration attributes found.\n"); + return EOK; + +shadow_fail: + talloc_free(spwd); + return ret; +} + +/* ==Get-User-DN========================================================== */ +struct get_user_dn_state { + char *username; + + char *orig_dn; +}; + +static void get_user_dn_done(struct tevent_req *subreq); + +static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sss_domain_info *domain, + struct sdap_handle *sh, + struct sdap_options *opts, + const char *username) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct get_user_dn_state *state; + char *clean_name; + char *filter; + const char **attrs; + errno_t ret; + + req = tevent_req_create(memctx, &state, struct get_user_dn_state); + if (!req) return NULL; + + ret = sss_parse_internal_fqname(state, username, + &state->username, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot parse %s\n", username); + goto done; + } + + ret = sss_filter_sanitize(state, state->username, &clean_name); + if (ret != EOK) { + goto done; + } + + filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", + opts->user_map[SDAP_AT_USER_NAME].name, + clean_name, + opts->user_map[SDAP_OC_USER].name); + talloc_zfree(clean_name); + if (filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n"); + ret = ENOMEM; + goto done; + } + + /* We're mostly interested in the DN anyway */ + attrs = talloc_array(state, const char *, 3); + if (attrs == NULL) { + ret = ENOMEM; + goto done; + } + attrs[0] = "objectclass"; + attrs[1] = opts->user_map[SDAP_AT_USER_NAME].name; + attrs[2] = NULL; + + subreq = sdap_search_user_send(state, ev, domain, opts, + opts->sdom->user_search_bases, + sh, attrs, filter, + dp_opt_get_int(opts->basic, + SDAP_SEARCH_TIMEOUT), + SDAP_LOOKUP_SINGLE); + if (!subreq) { + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(subreq, get_user_dn_done, req); + return req; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + return req; +} + +static void get_user_dn_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct get_user_dn_state *state = tevent_req_data(req, + struct get_user_dn_state); + struct ldb_message_element *el; + struct sysdb_attrs **users; + size_t count; + + ret = sdap_search_user_recv(state, subreq, NULL, &users, &count); + talloc_zfree(subreq); + if (ret && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve users\n"); + tevent_req_error(req, ret); + return; + } + + if (count == 0) { + DEBUG(SSSDBG_OP_FAILURE, "No such user\n"); + tevent_req_error(req, ENOMEM); + return; + } else if (count > 1) { + DEBUG(SSSDBG_OP_FAILURE, "Multiple users matched\n"); + tevent_req_error(req, EIO); + return; + } + + /* exactly one user. Get the originalDN */ + ret = sysdb_attrs_get_el_ext(users[0], SYSDB_ORIG_DN, false, &el); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "originalDN is not available for [%s].\n", state->username); + tevent_req_error(req, ret); + return; + } + + state->orig_dn = talloc_strdup(state, (const char *) el->values[0].data); + if (state->orig_dn == NULL) { + tevent_req_error(req, ENOMEM); + return; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, "Found originalDN [%s] for [%s]\n", + state->orig_dn, state->username); + tevent_req_done(req); +} + +static int get_user_dn_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, + char **orig_dn) +{ + struct get_user_dn_state *state = tevent_req_data(req, + struct get_user_dn_state); + + if (orig_dn) { + *orig_dn = talloc_move(mem_ctx, &state->orig_dn); + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +int get_user_dn(TALLOC_CTX *memctx, + struct sss_domain_info *domain, + enum sdap_access_type access_type, + struct sdap_options *opts, + const char *username, + char **user_dn, + enum pwexpire *user_pw_expire_type, + void **user_pw_expire_data) +{ + TALLOC_CTX *tmpctx; + enum pwexpire pw_expire_type = PWEXPIRE_NONE; + void *pw_expire_data; + struct ldb_result *res; + const char **attrs; + const char *dn = NULL; + int ret; + + tmpctx = talloc_new(memctx); + if (!tmpctx) { + return ENOMEM; + } + + attrs = talloc_array(tmpctx, const char *, 11); + if (!attrs) { + ret = ENOMEM; + goto done; + } + + attrs[0] = SYSDB_ORIG_DN; + attrs[1] = SYSDB_SHADOWPW_LASTCHANGE; + attrs[2] = SYSDB_SHADOWPW_MIN; + attrs[3] = SYSDB_SHADOWPW_MAX; + attrs[4] = SYSDB_SHADOWPW_WARNING; + attrs[5] = SYSDB_SHADOWPW_INACTIVE; + attrs[6] = SYSDB_SHADOWPW_EXPIRE; + attrs[7] = SYSDB_KRBPW_LASTCHANGE; + attrs[8] = SYSDB_KRBPW_EXPIRATION; + attrs[9] = SYSDB_PWD_ATTRIBUTE; + attrs[10] = NULL; + + ret = sysdb_get_user_attr(tmpctx, domain, username, attrs, &res); + if (ret) { + goto done; + } + + switch (res->count) { + case 0: + /* No such user entry? Look it up */ + ret = EAGAIN; + break; + + case 1: + dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL); + if (dn == NULL) { + /* The user entry has no original DN. This is the case when the ID + * provider is not LDAP-based (proxy perhaps) */ + ret = EAGAIN; + break; + } + + dn = talloc_strdup(tmpctx, dn); + if (!dn) { + ret = ENOMEM; + break; + } + + ret = find_password_expiration_attributes(tmpctx, + res->msgs[0], + access_type, + opts->basic, + &pw_expire_type, + &pw_expire_data); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "find_password_expiration_attributes failed.\n"); + } + break; + + default: + DEBUG(SSSDBG_CRIT_FAILURE, + "User search by name (%s) returned > 1 results!\n", + username); + ret = EFAULT; + break; + } + +done: + if (ret == EOK) { + *user_dn = talloc_strdup(memctx, dn); + if (!*user_dn) { + ret = ENOMEM; + } + /* pw_expire_data may be NULL */ + *user_pw_expire_data = talloc_steal(memctx, pw_expire_data); + *user_pw_expire_type = pw_expire_type; + } + + talloc_zfree(tmpctx); + return ret; +} + +/* ==Authenticate-User==================================================== */ + +struct minimal_auth_state { + struct tevent_context *ev; + struct sdap_auth_ctx *ctx; + const char *username; + struct sss_auth_token *authtok; + struct sdap_service *sdap_service; + + struct sdap_handle *sh; + + char *dn; + enum pwexpire pw_expire_type; + void *pw_expire_data; +}; + +static struct tevent_req *auth_connect_send(struct tevent_req *req); +static void auth_get_dn_done(struct tevent_req *subreq); +static void auth_do_bind(struct tevent_req *req); +static void auth_connect_done(struct tevent_req *subreq); +static void auth_bind_user_done(struct tevent_req *subreq); + +static struct tevent_req * +minimal_auth_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_auth_ctx *ctx, + const char *username, + struct sss_auth_token *authtok, + bool try_chpass_service) +{ + struct tevent_req *req; + struct minimal_auth_state *state; + errno_t ret; + + req = tevent_req_create(memctx, &state, struct minimal_auth_state); + if (!req) return NULL; + + /* The token must be a password token */ + if (sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PASSWORD && + sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PAM_STACKED) { + if (sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_PIN + || sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) { + /* Tell frontend that we do not support Smartcard authentication */ + ret = ERR_SC_AUTH_NOT_SUPPORTED; + } else { + ret = ERR_AUTH_FAILED; + } + goto fail; + } + + state->ev = ev; + state->ctx = ctx; + state->username = username; + state->authtok = authtok; + if (try_chpass_service && ctx->chpass_service != NULL && + ctx->chpass_service->name != NULL) { + state->sdap_service = ctx->chpass_service; + } else { + state->sdap_service = ctx->service; + } + + ret = get_user_dn(state, state->ctx->be->domain, SDAP_TYPE_LDAP, + state->ctx->opts, state->username, &state->dn, + &state->pw_expire_type, &state->pw_expire_data); + if (ret == EAGAIN) { + DEBUG(SSSDBG_TRACE_FUNC, + "Need to look up the DN of %s later\n", state->username); + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot get user DN [%d]: %s\n", ret, sss_strerror(ret)); + goto fail; + } + + if (auth_connect_send(req) == NULL) { + ret = ENOMEM; + goto fail; + } + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static struct tevent_req *auth_connect_send(struct tevent_req *req) +{ + struct tevent_req *subreq; + struct minimal_auth_state *state = tevent_req_data(req, + struct minimal_auth_state); + bool use_tls; + bool skip_conn_auth = false; + const char *sasl_mech; + + /* Check for undocumented debugging feature to disable TLS + * for authentication. This should never be used in production + * for obvious reasons. + */ + use_tls = !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS); + if (!use_tls) { + sss_log(SSS_LOG_ALERT, "LDAP authentication being performed over " + "insecure connection. This should be done " + "for debugging purposes only."); + } + + if (state->dn != NULL) { + /* In case the user's DN is known, the connection will only be used + * to bind as the user to perform the authentication. In that case, + * we don't need to authenticate the connection, because we're not + * looking up any information using the connection. This might be + * needed e.g. in case both ID and AUTH providers are set to LDAP + * and the server is AD, because otherwise the connection would both + * do a startTLS and later bind using GSSAPI or GSS-SPNEGO which + * doesn't work well with AD. + */ + skip_conn_auth = true; + } + + if (skip_conn_auth == false) { + sasl_mech = dp_opt_get_string(state->ctx->opts->basic, + SDAP_SASL_MECH); + if (sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) { + /* Don't force TLS on if we're told to use GSSAPI or GSS-SPNEGO */ + use_tls = false; + } + } + + if (ldap_is_ldapi_url(state->sdap_service->uri)) { + /* Don't force TLS on if we're a unix domain socket */ + use_tls = false; + } + + subreq = sdap_cli_resolve_and_connect_send(state, state->ev, + state->ctx->opts, + state->ctx->be, + state->sdap_service, false, + use_tls ? CON_TLS_ON : CON_TLS_OFF, + skip_conn_auth); + + if (subreq == NULL) { + tevent_req_error(req, ENOMEM); + return NULL; + } + + tevent_req_set_callback(subreq, auth_connect_done, req); + + return subreq; +} + +static bool check_encryption_used(LDAP *ldap) +{ + ber_len_t sasl_ssf = 0; + int tls_inplace = 0; + int ret; + + ret = ldap_get_option(ldap, LDAP_OPT_X_SASL_SSF, &sasl_ssf); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_TRACE_LIBS, "ldap_get_option failed to get sasl ssf, " + "assuming SASL is not used.\n"); + sasl_ssf = 0; + } + + tls_inplace = ldap_tls_inplace(ldap); + + DEBUG(SSSDBG_TRACE_ALL, + "Encryption used: SASL SSF [%lu] tls_inplace [%s].\n", sasl_ssf, + tls_inplace == 1 ? "TLS inplace" : "TLS NOT inplace"); + + if (sasl_ssf <= 1 && tls_inplace != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "No encryption detected on LDAP connection.\n"); + sss_log(SSS_LOG_CRIT, "No encryption detected on LDAP connection.\n"); + return false; + } + + return true; +} + +static void auth_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct minimal_auth_state *state = tevent_req_data(req, + struct minimal_auth_state); + int ret; + + ret = sdap_cli_resolve_and_connect_recv(subreq, state, NULL, &state->sh, + NULL); + talloc_zfree(subreq); + if (ret != EOK) { + /* As sdap_cli_resolve_and_connect_recv() returns EIO in case all the + * servers are down and we have to go offline, let's treat it + * accordingly here and allow the PAM responder to switch to offline + * authentication. + * + * Unfortunately, there's not much pattern within our code and the way + * to indicate we're going down in this part of the code is returning an + * ETIMEDOUT. + */ + if (ret == EIO) { + tevent_req_error(req, ETIMEDOUT); + } else { + if (auth_connect_send(req) == NULL) { + tevent_req_error(req, ENOMEM); + } + } + return; + } + + if (!ldap_is_ldapi_url(state->sdap_service->uri) && + !check_encryption_used(state->sh->ldap) && + !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Aborting the authentication request.\n"); + sss_log(SSS_LOG_CRIT, "Aborting the authentication request.\n"); + tevent_req_error(req, ERR_AUTH_FAILED); + return; + } + + if (state->dn == NULL) { + /* The cached user entry was missing the bind DN. Need to look + * it up based on user name in order to perform the bind */ + subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain, + state->sh, state->ctx->opts, state->username); + if (subreq == NULL) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, auth_get_dn_done, req); + return; + } + + /* All required user data was pre-cached during an identity lookup. + * We can proceed with the bind */ + auth_do_bind(req); + return; +} + +static void auth_get_dn_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); + errno_t ret; + + ret = get_user_dn_recv(state, subreq, &state->dn); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ERR_ACCOUNT_UNKNOWN); + return; + } + + /* The DN was found with an LDAP lookup + * We can proceed with the bind */ + return auth_do_bind(req); +} + +static void auth_do_bind(struct tevent_req *req) +{ + struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); + struct tevent_req *subreq; + bool use_ppolicy = dp_opt_get_bool(state->ctx->opts->basic, + SDAP_USE_PPOLICY); + int timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT); + + subreq = sdap_auth_send(state, state->ev, state->sh, + NULL, NULL, state->dn, + state->authtok, + timeout, use_ppolicy, + state->ctx->opts->pwmodify_mode); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, auth_bind_user_done, req); +} + +static void auth_bind_user_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct minimal_auth_state *state = tevent_req_data(req, + struct minimal_auth_state); + int ret; + struct sdap_ppolicy_data *ppolicy = NULL; + + ret = sdap_auth_recv(subreq, state, &ppolicy); + talloc_zfree(subreq); + if (ppolicy != NULL) { + DEBUG(SSSDBG_TRACE_ALL,"Found ppolicy data, " + "assuming LDAP password policies are active.\n"); + state->pw_expire_type = PWEXPIRE_LDAP_PASSWORD_POLICY; + state->pw_expire_data = ppolicy; + } + switch (ret) { + case EOK: + break; + case ETIMEDOUT: + case ERR_NETWORK_IO: + if (auth_connect_send(req) == NULL) { + tevent_req_error(req, ENOMEM); + } + return; + default: + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +static errno_t +minimal_auth_recv(struct tevent_req *req, + TALLOC_CTX *memctx, + struct sdap_handle **sh, + char **dn, + enum pwexpire *pw_expire_type, + void **pw_expire_data) +{ + struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); + + if (sh != NULL) { + *sh = talloc_steal(memctx, state->sh); + if (*sh == NULL) return ENOMEM; + } + + if (dn != NULL) { + *dn = talloc_steal(memctx, state->dn); + if (*dn == NULL) return ENOMEM; + } + + if (pw_expire_data != NULL) { + *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); + } + + *pw_expire_type = state->pw_expire_type; + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +struct minimal_sdap_pam_auth_handler_state { + struct pam_data *pd; + struct be_ctx *be_ctx; + struct sdap_auth_ctx *auth_ctx; +}; + +static void minimal_sdap_pam_auth_handler_done(struct tevent_req *subreq); + +struct tevent_req * +minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, + struct minimal_init_ctx *init_ctx, + struct pam_data *pd, + struct dp_req_params *params) +{ + struct sdap_auth_ctx *auth_ctx = init_ctx->auth_ctx; + struct minimal_sdap_pam_auth_handler_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + + req = tevent_req_create(mem_ctx, &state, + struct minimal_sdap_pam_auth_handler_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->pd = pd; + state->be_ctx = params->be_ctx; + state->auth_ctx = auth_ctx; + pd->pam_status = PAM_SYSTEM_ERR; + + switch (pd->cmd) { + case SSS_PAM_AUTHENTICATE: + subreq = minimal_auth_send(state, params->ev, auth_ctx, + pd->user, pd->authtok, false); + if (subreq == NULL) { + pd->pam_status = PAM_SYSTEM_ERR; + goto immediately; + } + + tevent_req_set_callback(subreq, minimal_sdap_pam_auth_handler_done, req); + break; + case SSS_PAM_CHAUTHTOK_PRELIM: + case SSS_PAM_CHAUTHTOK: + pd->pam_status = PAM_SYSTEM_ERR; + goto immediately; + + case SSS_PAM_ACCT_MGMT: + case SSS_PAM_SETCRED: + case SSS_PAM_OPEN_SESSION: + case SSS_PAM_CLOSE_SESSION: + pd->pam_status = PAM_SUCCESS; + goto immediately; + default: + pd->pam_status = PAM_MODULE_UNKNOWN; + goto immediately; + } + + return req; + +immediately: + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); + tevent_req_post(req, params->ev); + + return req; +} + +static void minimal_sdap_pam_auth_handler_done(struct tevent_req *subreq) +{ + struct minimal_sdap_pam_auth_handler_state *state; + struct tevent_req *req; + enum pwexpire pw_expire_type; + void *pw_expire_data; + const char *password; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct minimal_sdap_pam_auth_handler_state); + + ret = minimal_auth_recv(subreq, state, NULL, NULL, + &pw_expire_type, &pw_expire_data); + talloc_free(subreq); + + if (ret == EOK) { + ret = check_pwexpire_policy(pw_expire_type, pw_expire_data, state->pd, + state->be_ctx->domain->pwd_expiration_warning, + state->auth_ctx->opts); + if (ret == EINVAL) { + /* Unknown password expiration type. */ + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + } + + switch (ret) { + case EOK: + state->pd->pam_status = PAM_SUCCESS; + break; + case ERR_AUTH_DENIED: + state->pd->pam_status = PAM_PERM_DENIED; + break; + case ERR_AUTH_FAILED: + state->pd->pam_status = PAM_AUTH_ERR; + break; + case ETIMEDOUT: + case ERR_NETWORK_IO: + state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; + be_mark_offline(state->be_ctx); + break; + case ERR_ACCOUNT_EXPIRED: + state->pd->pam_status = PAM_ACCT_EXPIRED; + break; + case ERR_PASSWORD_EXPIRED: + state->pd->pam_status = PAM_NEW_AUTHTOK_REQD; + break; + case ERR_ACCOUNT_LOCKED: + state->pd->account_locked = true; + state->pd->pam_status = PAM_PERM_DENIED; + break; + case ERR_SC_AUTH_NOT_SUPPORTED: + state->pd->pam_status = PAM_BAD_ITEM; + break; + default: + state->pd->pam_status = PAM_SYSTEM_ERR; + break; + } + + if (ret == EOK && state->be_ctx->domain->cache_credentials) { + ret = sss_authtok_get_password(state->pd->authtok, &password, NULL); + if (ret == EOK) { + ret = sysdb_cache_password(state->be_ctx->domain, state->pd->user, + password); + } + + /* password caching failures are not fatal errors */ + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password for %s\n", + state->pd->user); + } else { + DEBUG(SSSDBG_CONF_SETTINGS, "Password successfully cached for %s\n", + state->pd->user); + } + } + +done: + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); +} + +errno_t +minimal_sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data) +{ + struct minimal_sdap_pam_auth_handler_state *state = NULL; + + state = tevent_req_data(req, struct minimal_sdap_pam_auth_handler_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *_data = talloc_steal(mem_ctx, state->pd); + + return EOK; +} diff --git a/src/providers/minimal/minimal_ldap_auth.h b/src/providers/minimal/minimal_ldap_auth.h new file mode 100644 index 00000000000..8bcf1929f32 --- /dev/null +++ b/src/providers/minimal/minimal_ldap_auth.h @@ -0,0 +1,48 @@ +/* + SSSD + + minimal Identity Backend Module + + Authors: + Pavel Březina + + Copyright (C) 2026 Red Hat + + 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 . +*/ + + +#ifndef _MINIMAL_LDAP_AUTH_H_ +#define _MINIMAL_LDAP_AUTH_H_ + +#include "config.h" +#include +#include + +#include "providers/data_provider/dp.h" +#include "providers/ldap/ldap_common.h" +#include "util/sss_pam_data.h" + +struct tevent_req * +minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, + struct sdap_auth_ctx *auth_ctx, + struct pam_data *pd, + struct dp_req_params *params); + +errno_t +minimal_sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data); + +#endif From 7a8f357c1f883dab602c4b25c47e53a04d7b8f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 17 Dec 2025 14:35:42 +0100 Subject: [PATCH 06/39] DO NOT PUSH TO MASTER minimal: switch to new failover for service lookup and user authentication --- Makefile.am | 3 + src/providers/minimal/minimal.h | 2 + src/providers/minimal/minimal_id.c | 37 ++--- src/providers/minimal/minimal_id_services.c | 143 ++++++++------------ src/providers/minimal/minimal_id_services.h | 52 +++++++ src/providers/minimal/minimal_init.c | 104 +++++++++++++- src/providers/minimal/minimal_ldap_auth.c | 104 ++++++-------- src/providers/minimal/minimal_ldap_auth.h | 3 +- src/util/sss_ini.c | 2 +- 9 files changed, 270 insertions(+), 180 deletions(-) create mode 100644 src/providers/minimal/minimal_id_services.h diff --git a/Makefile.am b/Makefile.am index d0d705d54fc..90803eafdc9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -915,7 +915,10 @@ dist_noinst_HEADERS = \ src/providers/idp/idp_id.h \ src/providers/idp/idp_opts.h \ src/providers/idp/idp_private.h \ + src/providers/minimal/minimal.h \ src/providers/minimal/minimal_id.h \ + src/providers/minimal/minimal_id_services.h \ + src/providers/minimal/minimal_ldap_auth.h \ src/tools/tools_util.h \ src/resolv/async_resolv.h \ src/tests/common.h \ diff --git a/src/providers/minimal/minimal.h b/src/providers/minimal/minimal.h index f8f004a3c41..0f9a15adf7c 100644 --- a/src/providers/minimal/minimal.h +++ b/src/providers/minimal/minimal.h @@ -30,11 +30,13 @@ #include #include "providers/ldap/ldap_common.h" +#include "providers/failover/failover.h" struct minimal_init_ctx { struct sdap_options *options; struct sdap_id_ctx *id_ctx; struct sdap_auth_ctx *auth_ctx; + struct sss_failover_ctx *fctx; }; #endif diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c index e9450f97416..6e080965f97 100644 --- a/src/providers/minimal/minimal_id.c +++ b/src/providers/minimal/minimal_id.c @@ -27,20 +27,8 @@ #include "util/util.h" #include "providers/minimal/minimal.h" #include "providers/minimal/minimal_id.h" - -struct tevent_req * -minimal_services_get_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *id_ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, - const char *name, - const char *protocol, - int filter_type, - bool noexist_delete); - -errno_t -minimal_services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +#include "providers/minimal/minimal_id_services.h" +#include "providers/failover/failover_transaction.h" struct minimal_handle_acct_req_state { struct dp_id_data *ar; @@ -56,9 +44,9 @@ static struct tevent_req * minimal_handle_acct_req_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_id_data *ar, + struct sss_failover_ctx *fctx, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, bool noexist_delete) { struct tevent_req *req; @@ -84,12 +72,11 @@ minimal_handle_acct_req_send(TALLOC_CTX *mem_ctx, switch (ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_SERVICES: DEBUG(SSSDBG_TRACE_FUNC, "Executing BE_REQ_SERVICES request\n"); - subreq = services_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, - ar->filter_value, - ar->extra_value, - ar->filter_type, - noexist_delete); + + subreq = minimal_services_get_send(state, be_ctx->ev, fctx, id_ctx, + sdom, ar->filter_value, + ar->extra_value, ar->filter_type, + noexist_delete); break; default: /*fail*/ ret = EINVAL; @@ -133,7 +120,7 @@ static void minimal_handle_acct_req_done(struct tevent_req *subreq) switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_SERVICES: err = "Service lookup failed"; - ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = minimal_services_get_recv(subreq); break; default: /* fail */ ret = EINVAL; @@ -141,6 +128,7 @@ static void minimal_handle_acct_req_done(struct tevent_req *subreq) } talloc_zfree(subreq); + state->minimal_ret = ret; if (ret != EOK) { state->err = err; tevent_req_error(req, ret); @@ -161,7 +149,7 @@ minimal_handle_acct_req_recv(struct tevent_req *req, state = tevent_req_data(req, struct minimal_handle_acct_req_state); if (_dp_error) { - *_dp_error = state->dp_error; + *_dp_error = DP_ERR_OK; } if (_err) { @@ -201,9 +189,10 @@ minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, } subreq = minimal_handle_acct_req_send(state, params->be_ctx, data, + init_ctx->fctx, init_ctx->id_ctx, init_ctx->id_ctx->opts->sdom, - init_ctx->id_ctx->conn, true); + true); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "minimal_handle_acct_req_send() failed.\n"); ret = ENOMEM; diff --git a/src/providers/minimal/minimal_id_services.c b/src/providers/minimal/minimal_id_services.c index 4ca6a46ec82..2fa8e530563 100644 --- a/src/providers/minimal/minimal_id_services.c +++ b/src/providers/minimal/minimal_id_services.c @@ -29,15 +29,17 @@ #include "db/sysdb_services.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" +#include "providers/minimal/minimal_id_services.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" -struct sdap_services_get_state { +struct minimal_services_get_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; const char *name; const char *protocol; @@ -47,24 +49,21 @@ struct sdap_services_get_state { int filter_type; - int dp_error; - int sdap_ret; bool noexist_delete; + bool test; }; -static errno_t -services_get_retry(struct tevent_req *req); static void -services_get_connect_done(struct tevent_req *subreq); +minimal_services_get_connect_done(struct tevent_req *subreq); static void -services_get_done(struct tevent_req *subreq); +minimal_services_get_done(struct tevent_req *subreq); struct tevent_req * minimal_services_get_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct sss_failover_ctx *fctx, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, const char *name, const char *protocol, int filter_type, @@ -72,32 +71,24 @@ minimal_services_get_send(TALLOC_CTX *mem_ctx, { errno_t ret; struct tevent_req *req; - struct sdap_services_get_state *state; + struct minimal_services_get_state *state; const char *attr_name; char *clean_name; char *clean_protocol = NULL; - req = tevent_req_create(mem_ctx, &state, struct sdap_services_get_state); + req = tevent_req_create(mem_ctx, &state, struct minimal_services_get_state); if (!req) return NULL; state->ev = ev; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->name = name; state->protocol = protocol; state->filter_type = filter_type; state->noexist_delete = noexist_delete; - - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_MINOR_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto error; - } + state->test = true; switch(filter_type) { case BE_FILTER_NAME: @@ -149,7 +140,8 @@ minimal_services_get_send(TALLOC_CTX *mem_ctx, &state->attrs, NULL); if (ret != EOK) goto error; - ret = services_get_retry(req); + ret = sss_failover_transaction_send(state, ev, fctx, req, + minimal_services_get_connect_done); if (ret != EOK) goto error; return req; @@ -160,47 +152,36 @@ minimal_services_get_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t -services_get_retry(struct tevent_req *req) -{ - errno_t ret; - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - struct tevent_req *subreq; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, services_get_connect_done, req); - return EOK; -} - static void -services_get_connect_done(struct tevent_req *subreq) +minimal_services_get_connect_done(struct tevent_req *subreq) { - errno_t ret; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - int dp_error = DP_ERR_FATAL; + struct minimal_services_get_state *state = + tevent_req_data(req, struct minimal_services_get_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - state->dp_error = dp_error; - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } + /* Uncomment if you want to fail the first attempt. */ + // if (state->test) { + // state->test = false; + // tevent_req_error(req, ERR_SERVER_FAILURE); + // return; + // } + subreq = sdap_get_services_send(state, state->ev, state->domain, state->sysdb, state->id_ctx->opts, state->sdom->service_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -209,20 +190,19 @@ services_get_connect_done(struct tevent_req *subreq) tevent_req_error(req, ENOMEM); return; } - tevent_req_set_callback(subreq, services_get_done, req); + tevent_req_set_callback(subreq, minimal_services_get_done, req); } static void -services_get_done(struct tevent_req *subreq) +minimal_services_get_done(struct tevent_req *subreq) { errno_t ret; uint16_t port; char *endptr; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - int dp_error = DP_ERR_FATAL; + struct minimal_services_get_state *state = + tevent_req_data(req, struct minimal_services_get_state); ret = sdap_get_services_recv(NULL, subreq, NULL); talloc_zfree(subreq); @@ -230,26 +210,27 @@ services_get_done(struct tevent_req *subreq) /* Check whether we need to try again with another * failover server. */ - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = services_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* Return to the mainloop to retry */ - return; - } - state->sdap_ret = ret; - - /* An error occurred. */ - if (ret && ret != ENOENT) { - state->dp_error = dp_error; - tevent_req_error(req, ret); - return; - } + // TODO handle how to yield ERR_SERVER_FAILED + // ret = sdap_id_op_done(state->op, ret, &dp_error); + // if (dp_error == DP_ERR_OK && ret != EOK) { + // /* retry */ + // ret = minimal_services_get_retry(req); + // if (ret != EOK) { + // tevent_req_error(req, ret); + // return; + // } + + // /* Return to the mainloop to retry */ + // return; + // } + // state->sdap_ret = ret; + + // /* An error occurred. */ + // if (ret && ret != ENOENT) { + // state->dp_error = dp_error; + // tevent_req_error(req, ret); + // return; + //} if (ret == ENOENT && state->noexist_delete == true) { /* Ensure that this entry is removed from the sysdb */ @@ -284,24 +265,12 @@ services_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } errno_t -minimal_services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +minimal_services_get_recv(struct tevent_req *req) { - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/minimal/minimal_id_services.h b/src/providers/minimal/minimal_id_services.h new file mode 100644 index 00000000000..6f82b2e3ac2 --- /dev/null +++ b/src/providers/minimal/minimal_id_services.h @@ -0,0 +1,52 @@ +/* + SSSD + + minimal Identity Backend Module + + Authors: + Justin Stephenson + + Copyright (C) 2025 Red Hat + + 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 . +*/ + + +#ifndef _MINIMAL_ID_SERVICES_H_ +#define _MINIMAL_ID_SERVICES_H_ + +#include "config.h" +#include +#include + +#include "providers/backend.h" +#include "providers/ldap/ldap_common.h" +#include "util/util.h" +#include "providers/failover/failover.h" + +struct tevent_req * +minimal_services_get_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sdap_id_ctx *id_ctx, + struct sdap_domain *sdom, + const char *name, + const char *protocol, + int filter_type, + bool noexist_delete); + +errno_t +minimal_services_get_recv(struct tevent_req *req); + +#endif diff --git a/src/providers/minimal/minimal_init.c b/src/providers/minimal/minimal_init.c index 500000f78f5..d6f126fc46d 100644 --- a/src/providers/minimal/minimal_init.c +++ b/src/providers/minimal/minimal_init.c @@ -33,6 +33,10 @@ #include "src/providers/minimal/minimal.h" #include "src/providers/minimal/minimal_id.h" +#include "src/providers/minimal/minimal_ldap_auth.h" +#include "src/providers/failover/failover.h" +#include "src/providers/failover/failover_vtable.h" +#include "src/providers/failover/ldap/failover_ldap.h" /* Copied from ldap_init.c with no changes */ static errno_t get_sdap_service(TALLOC_CTX *mem_ctx, @@ -137,6 +141,88 @@ static errno_t minimal_init_auth_ctx(TALLOC_CTX *mem_ctx, return EOK; } +static struct sss_failover_ctx * +sssm_minimal_init_failover(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts) +{ + struct sss_failover_ctx *fctx; + struct sss_failover_group *group; + struct sss_failover_server *server; + errno_t ret; + + /* Setup new failover. */ + fctx = sss_failover_init(mem_ctx, be_ctx->ev, "LDAP", + be_ctx->be_res->resolv, + be_ctx->be_res->family_order); + if (fctx == NULL) { + return NULL; + } + + /* Add primary servers */ + group = sss_failover_group_new(fctx, "primary"); + if (group == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_setup_dns_discovery(group); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_1.ldap.test", + "ldap://fake_1.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_2.ldap.test", + "ldap://fake_2.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "master.ldap.test", + "ldap://master.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + sss_failover_vtable_set_connect(fctx, + sss_failover_ldap_connect_send, + sss_failover_ldap_connect_recv, + opts); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(fctx); + return NULL; + } + + return fctx; +} + errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, @@ -198,6 +284,14 @@ errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx, } } + /* Setup new failover. */ + init_ctx->fctx = sssm_minimal_init_failover(init_ctx, be_ctx, init_ctx->id_ctx->opts); + if (init_ctx->fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + ret = ENOMEM; + goto done; + } + *_module_data = init_ctx; ret = EOK; @@ -226,8 +320,8 @@ errno_t sssm_minimal_id_init(TALLOC_CTX *mem_ctx, /* LDAP provider check online handler */ dp_set_method(dp_methods, DPM_CHECK_ONLINE, - sdap_online_check_handler_send, sdap_online_check_handler_recv, init_ctx, - struct minimal_init_ctx, void, struct dp_reply_std); + sdap_online_check_handler_send, sdap_online_check_handler_recv, init_ctx->id_ctx, + struct sdap_id_ctx, void, struct dp_reply_std); dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, default_account_domain_send, default_account_domain_recv, NULL, @@ -244,14 +338,12 @@ errno_t sssm_minimal_auth_init(TALLOC_CTX *mem_ctx, struct dp_method *dp_methods) { struct minimal_init_ctx *init_ctx; - struct sdap_auth_ctx *auth_ctx; init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); - auth_ctx = init_ctx->auth_ctx; dp_set_method(dp_methods, DPM_AUTH_HANDLER, - sdap_pam_auth_handler_send, sdap_pam_auth_handler_recv, auth_ctx, - struct sdap_auth_ctx, struct pam_data, struct pam_data *); + minimal_sdap_pam_auth_handler_send, minimal_sdap_pam_auth_handler_recv, init_ctx, + struct minimal_init_ctx, struct pam_data, struct pam_data *); return EOK; } diff --git a/src/providers/minimal/minimal_ldap_auth.c b/src/providers/minimal/minimal_ldap_auth.c index 82804271742..3ea0912e002 100644 --- a/src/providers/minimal/minimal_ldap_auth.c +++ b/src/providers/minimal/minimal_ldap_auth.c @@ -29,7 +29,21 @@ #include #include #include +#ifdef HAVE_SHADOW_H #include +#else +struct spwd { + char *sp_namp; + char *sp_pwdp; + long int sp_lstchg; + long int sp_min; + long int sp_max; + long int sp_warn; + long int sp_inact; + long int sp_expire; + unsigned long int sp_flag; +}; +#endif #include @@ -41,6 +55,8 @@ #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/ldap_auth.h" #include "providers/minimal/minimal.h" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/ldap/failover_ldap.h" static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, @@ -410,19 +426,20 @@ int get_user_dn(TALLOC_CTX *memctx, struct minimal_auth_state { struct tevent_context *ev; + struct sss_failover_ctx *fctx; struct sdap_auth_ctx *ctx; const char *username; struct sss_auth_token *authtok; struct sdap_service *sdap_service; - struct sdap_handle *sh; + struct sss_failover_ldap_connection *conn; char *dn; enum pwexpire pw_expire_type; void *pw_expire_data; }; -static struct tevent_req *auth_connect_send(struct tevent_req *req); +static errno_t auth_connect_send(struct tevent_req *req); static void auth_get_dn_done(struct tevent_req *subreq); static void auth_do_bind(struct tevent_req *req); static void auth_connect_done(struct tevent_req *subreq); @@ -431,6 +448,7 @@ static void auth_bind_user_done(struct tevent_req *subreq); static struct tevent_req * minimal_auth_send(TALLOC_CTX *memctx, struct tevent_context *ev, + struct sss_failover_ctx *fctx, struct sdap_auth_ctx *ctx, const char *username, struct sss_auth_token *authtok, @@ -457,6 +475,7 @@ minimal_auth_send(TALLOC_CTX *memctx, } state->ev = ev; + state->fctx = fctx; state->ctx = ctx; state->username = username; state->authtok = authtok; @@ -479,8 +498,8 @@ minimal_auth_send(TALLOC_CTX *memctx, goto fail; } - if (auth_connect_send(req) == NULL) { - ret = ENOMEM; + ret = auth_connect_send(req); + if (ret != EOK) { goto fail; } @@ -492,14 +511,14 @@ minimal_auth_send(TALLOC_CTX *memctx, return req; } -static struct tevent_req *auth_connect_send(struct tevent_req *req) +static errno_t auth_connect_send(struct tevent_req *req) { - struct tevent_req *subreq; struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); bool use_tls; bool skip_conn_auth = false; const char *sasl_mech; + errno_t ret; /* Check for undocumented debugging feature to disable TLS * for authentication. This should never be used in production @@ -539,21 +558,13 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req) use_tls = false; } - subreq = sdap_cli_resolve_and_connect_send(state, state->ev, - state->ctx->opts, - state->ctx->be, - state->sdap_service, false, - use_tls ? CON_TLS_ON : CON_TLS_OFF, - skip_conn_auth); - - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return NULL; - } - - tevent_req_set_callback(subreq, auth_connect_done, req); + ret = sss_failover_transaction_ex_send( + state, state->ev, state->fctx, req, auth_connect_done, false, + !skip_conn_auth, true, + use_tls ? SSS_FAILOVER_TRANSACTION_TLS_ON + : SSS_FAILOVER_TRANSACTION_TLS_OFF); - return subreq; + return ret; } static bool check_encryption_used(LDAP *ldap) @@ -591,33 +602,19 @@ static void auth_connect_done(struct tevent_req *subreq) struct tevent_req); struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); - int ret; - ret = sdap_cli_resolve_and_connect_recv(subreq, state, NULL, &state->sh, - NULL); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - /* As sdap_cli_resolve_and_connect_recv() returns EIO in case all the - * servers are down and we have to go offline, let's treat it - * accordingly here and allow the PAM responder to switch to offline - * authentication. - * - * Unfortunately, there's not much pattern within our code and the way - * to indicate we're going down in this part of the code is returning an - * ETIMEDOUT. - */ - if (ret == EIO) { - tevent_req_error(req, ETIMEDOUT); - } else { - if (auth_connect_send(req) == NULL) { - tevent_req_error(req, ENOMEM); - } - } + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } if (!ldap_is_ldapi_url(state->sdap_service->uri) && - !check_encryption_used(state->sh->ldap) && + !check_encryption_used(state->conn->sh->ldap) && !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS)) { DEBUG(SSSDBG_CRIT_FAILURE, "Aborting the authentication request.\n"); sss_log(SSS_LOG_CRIT, "Aborting the authentication request.\n"); @@ -629,7 +626,7 @@ static void auth_connect_done(struct tevent_req *subreq) /* The cached user entry was missing the bind DN. Need to look * it up based on user name in order to perform the bind */ subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain, - state->sh, state->ctx->opts, state->username); + state->conn->sh, state->ctx->opts, state->username); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -671,7 +668,7 @@ static void auth_do_bind(struct tevent_req *req) SDAP_USE_PPOLICY); int timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT); - subreq = sdap_auth_send(state, state->ev, state->sh, + subreq = sdap_auth_send(state, state->ev, state->conn->sh, NULL, NULL, state->dn, state->authtok, timeout, use_ppolicy, @@ -706,9 +703,7 @@ static void auth_bind_user_done(struct tevent_req *subreq) break; case ETIMEDOUT: case ERR_NETWORK_IO: - if (auth_connect_send(req) == NULL) { - tevent_req_error(req, ENOMEM); - } + tevent_req_error(req, ERR_SERVER_FAILURE); return; default: tevent_req_error(req, ret); @@ -721,23 +716,11 @@ static void auth_bind_user_done(struct tevent_req *subreq) static errno_t minimal_auth_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sdap_handle **sh, - char **dn, enum pwexpire *pw_expire_type, void **pw_expire_data) { struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); - if (sh != NULL) { - *sh = talloc_steal(memctx, state->sh); - if (*sh == NULL) return ENOMEM; - } - - if (dn != NULL) { - *dn = talloc_steal(memctx, state->dn); - if (*dn == NULL) return ENOMEM; - } - if (pw_expire_data != NULL) { *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); } @@ -782,7 +765,7 @@ minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, switch (pd->cmd) { case SSS_PAM_AUTHENTICATE: - subreq = minimal_auth_send(state, params->ev, auth_ctx, + subreq = minimal_auth_send(state, params->ev, init_ctx->fctx, auth_ctx, pd->user, pd->authtok, false); if (subreq == NULL) { pd->pam_status = PAM_SYSTEM_ERR; @@ -829,8 +812,7 @@ static void minimal_sdap_pam_auth_handler_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct minimal_sdap_pam_auth_handler_state); - ret = minimal_auth_recv(subreq, state, NULL, NULL, - &pw_expire_type, &pw_expire_data); + ret = minimal_auth_recv(subreq, state, &pw_expire_type, &pw_expire_data); talloc_free(subreq); if (ret == EOK) { diff --git a/src/providers/minimal/minimal_ldap_auth.h b/src/providers/minimal/minimal_ldap_auth.h index 8bcf1929f32..23b9015fedd 100644 --- a/src/providers/minimal/minimal_ldap_auth.h +++ b/src/providers/minimal/minimal_ldap_auth.h @@ -33,10 +33,11 @@ #include "providers/data_provider/dp.h" #include "providers/ldap/ldap_common.h" #include "util/sss_pam_data.h" +#include "providers/minimal/minimal.h" struct tevent_req * minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_auth_ctx *auth_ctx, + struct minimal_init_ctx *init_ctx, struct pam_data *pd, struct dp_req_params *params); diff --git a/src/util/sss_ini.c b/src/util/sss_ini.c index f20a8148f62..a1d1a1b5111 100644 --- a/src/util/sss_ini.c +++ b/src/util/sss_ini.c @@ -494,7 +494,7 @@ static errno_t check_domain_id_provider(char *cfg_section, struct ini_errobj *errobj) { struct value_obj *vo = NULL; - const char *valid_values[] = { "ad", "ipa", "ldap", "proxy", NULL }; + const char *valid_values[] = { "ad", "ipa", "ldap", "proxy", "minimal", NULL }; const char **valid_value; const char *value; int ret; From 7da4a6f49a574b08a95832b4f2bf3899eb3dfbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Thu, 22 Jan 2026 14:27:20 +0100 Subject: [PATCH 07/39] DO NOT PUSH TO MASTER minimal: update how to use it notes --- minimal-provider-notes.txt | 105 +++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/minimal-provider-notes.txt b/minimal-provider-notes.txt index 1c0157ee1cb..45a5b7bf063 100644 --- a/minimal-provider-notes.txt +++ b/minimal-provider-notes.txt @@ -1,39 +1,88 @@ --- On sssd-ci-containers podman 'ldap' container, create services.ldif +# Minimal SSSD provider - $ vim services.ldif - dn: ou=services,dc=ldap,dc=test - objectClass: top - objectClass: organizationalUnit - ou: services +This is used as a proof of concept for the new failover implementation. It can +also be used to see what changes are required in order to switch to the new +code, however it really does only minimum amount of changes to get it working. +It would be very good to provide more thorough refactoring in the real +providers. - dn: cn=service0,ou=services,dc=ldap,dc=test - objectClass: ipService - cn: service0 - ipServiceProtocol: tcp - ipServicePort: 12345 +The minimal provider supports: +- services lookup (getent services) +- user authentication --- Add services OU and object to LDAP +## Populate LDAP - $ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -f services.ldif -vv +``` +$ vim objects.ldif +dn: ou=users,dc=ldap,dc=test +objectClass: top +objectClass: organizationalUnit +ou: users --- Verify the entries were added +# Password is Secret123 +dn: cn=user-1,ou=users,dc=ldap,dc=test +uid: user-1 +uidNumber: 10000 +homeDirectory: /home/user-1 +gidNumber: 100000 +cn: user-1 +objectClass: posixAccount +objectClass: top +userPassword:: e1BCS0RGMi1TSEE1MTJ9MTAwMDAwJEVZU2lqOFgxTTVFZUIrMXlHQzdvZkhwZzd + XZXpYRGJwJG0vTVUyMUIrTGNNb2tkRVcvUFJ6YWlhc21zdlNDeVJWdGxPU3c3c05YbHk2NUxBcUcz + ODJqQUJWUEp2N1ZnOUtRdXhEamVlbmxEV3V5Ylg5UFdKMW5nPT0= - $ ldapsearch -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -b ou=services,dc=ldap,dc=test +dn: ou=services,dc=ldap,dc=test +objectClass: top +objectClass: organizationalUnit +ou: services ---- On SSSD client with minimal provider installed, add the domain below to sssd.conf: +dn: cn=service0,ou=services,dc=ldap,dc=test +objectClass: ipService +cn: service0 +ipServiceProtocol: tcp +ipServicePort: 12345 - [sssd] - domains = testmin +$ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -f objects.ldif -vv +``` - [domain/testmin] - id_provider = minimal - # failover to backup uri - ldap_uri = ldap://invalid.ldap.test/ - ldap_backup_uri = ldap://master.ldap.test/ - ldap_id_use_start_tls = false - debug_level = 9 +## Verify LDAP contents --- Restart SSSD and test +``` +$ ldapsearch -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -b dc=ldap,dc=test +``` - # getent services -s sss service0 - service0 12345/tcp +## Configure SSSD for services lookup + +``` +[sssd] +domains = minimal + +[domain/minimal] +debug_level = 9 +id_provider = minimal + +$ getent services -s sss service0 +service0 12345/tcp +``` + +## Configure SSSD for user authentication + +Note: user lookup is done by id provider + +``` +[sssd] +services = nss, pam +domains = minimal + +[domain/minimal] +debug_level = 9 +id_provider = ldap +auth_provider = minimal +ldap_uri = _srv_ +dns_discovery_domain = ldap.test +ldap_tls_reqcert = never + +$ su user-1 +Password: Secret123 +``` From 8bb8fd3055c7cc3ba8370e13a4e264791e563d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Mon, 13 Apr 2026 13:37:24 +0200 Subject: [PATCH 08/39] DO NOT PUSH TO MASTER minimal: add sssd-minimal provider package to spec file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the sssd-minimal provider package to the spec file following the same pattern as other providers (ldap, ipa, ad, etc.). This packages the libsss_minimal.so library that was added in recent commits. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- contrib/sssd.spec.in | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index a36182c58f8..4e4c0088f30 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -50,6 +50,7 @@ Requires: sssd-common = %{version}-%{release} Requires: sssd-ipa = %{version}-%{release} Requires: sssd-krb5 = %{version}-%{release} Requires: sssd-ldap = %{version}-%{release} +Requires: sssd-minimal = %{version}-%{release} Requires: sssd-proxy = %{version}-%{release} Suggests: logrotate Suggests: procps-ng @@ -265,6 +266,15 @@ Requires: libsss_certmap = %{version}-%{release} Provides the LDAP back end that the SSSD can utilize to fetch identity data from and authenticate against an LDAP server. +%package minimal +Summary: The minimal back end of the SSSD +License: GPL-3.0-or-later +Requires: sssd-common = %{version}-%{release} + +%description minimal +Provides the minimal back end that the SSSD can utilize as a minimal +identity provider. + %package krb5-common Summary: SSSD helpers needed for Kerberos and GSSAPI authentication License: GPL-3.0-or-later @@ -785,6 +795,10 @@ install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/sssd.conf %{_mandir}/man5/sssd-ldap.5* %{_mandir}/man5/sssd-ldap-attributes.5* +%files minimal +%license COPYING +%{_libdir}/%{name}/libsss_minimal.so + %files krb5-common %license COPYING %attr(775,sssd,sssd) %dir %{pubconfpath}/krb5.include.d From e8028486b3799e01f50979b7c631e00169026df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Sat, 21 Mar 2026 13:33:01 +0100 Subject: [PATCH 09/39] DO NOT PUSH TO MASTER ci: enable failover branch And also disable codeql for the minimal provider. The provider is for testing only, it does not make sense to fix any issue there. --- .github/workflows/analyze-target.yml | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverity.yml | 1 + .github/workflows/static-code-analysis.yml | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/analyze-target.yml b/.github/workflows/analyze-target.yml index 618735849dd..c8f657b3bc1 100644 --- a/.github/workflows/analyze-target.yml +++ b/.github/workflows/analyze-target.yml @@ -1,7 +1,7 @@ name: "Analyze (target)" on: pull_request_target: - branches: [master] + branches: [master, failover] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73e7b34fbe1..81c0c2ab753 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ name: "ci" on: push: - branches: [master] + branches: [master, failover] pull_request: - branches: [master] + branches: [master, failover] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index deb6f0c0e16..ec456809131 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -10,6 +10,7 @@ on: pull_request_target: branches: - master + - failover types: - labeled workflow_dispatch: diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index 11c6b840c03..9df2a5118fa 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -1,9 +1,9 @@ name: "Static code analysis" on: push: - branches: [master] + branches: [master, failover] pull_request: - branches: [master] + branches: [master, failover] schedule: # Everyday at midnight - cron: '0 0 * * *' @@ -28,6 +28,8 @@ jobs: with: languages: cpp, python queries: +security-and-quality + paths-ignore: | + src/providers/minimal/** - name: Configure sssd uses: ./.github/actions/configure From cc5620f9965789e01b5e5e84642c9831fbad78dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Tue, 5 May 2026 11:06:16 +0200 Subject: [PATCH 10/39] DO NOT PUSH TO MASTER tests: add failover test with minimal provider --- src/tests/system/tests/test_failover_new.py | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/tests/system/tests/test_failover_new.py diff --git a/src/tests/system/tests/test_failover_new.py b/src/tests/system/tests/test_failover_new.py new file mode 100644 index 00000000000..9e6afae6e91 --- /dev/null +++ b/src/tests/system/tests/test_failover_new.py @@ -0,0 +1,49 @@ +""" +This module contains tests for the new failover implementation utilizing +the minimal provider. These tests should not be merged to master. +""" + +from __future__ import annotations + +import pytest +from sssd_test_framework.roles.ldap import LDAP +from sssd_test_framework.roles.client import Client +from pytest_mh import Topology, TopologyDomain +from sssd_test_framework.config import SSSDTopologyMark +from sssd_test_framework.topology_controllers import LDAPTopologyController + +MINIMAL = SSSDTopologyMark( + name="minimal", + topology=Topology(TopologyDomain("sssd", client=1, ldap=1, nfs=1, kdc=1)), + controller=LDAPTopologyController(), + domains=dict(test="sssd.ldap[0]"), + fixtures=dict( + client="sssd.client[0]", ldap="sssd.ldap[0]", provider="sssd.ldap[0]", nfs="sssd.nfs[0]", kdc="sssd.kdc[0]" + ), +) + +@pytest.mark.topology(MINIMAL) +def test_failover_new__getent_services( + client: Client, ldap: LDAP +): + """ + :title: Test new failover with minimal provider + :setup: + 1. Add service + 2. Update sssd.conf + :steps: + 1. Lookup service + :expectedresults: + 1. Lookup is successful + :customerscenario: False + """ + ldap.services("my-service").add(protocol="tcp", port="9999") + + client.sssd.domain["id_provider"] = "minimal" + client.sssd.start() + + svc = client.tools.getent.services("my-service", service="sss") + assert svc is not None + assert svc.name == "my-service" + assert svc.port == 9999 + assert svc.protocol == "tcp" From 587c37ad0fb954ff277ed95c483736a69c03bcf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 1 Oct 2025 14:30:40 +0200 Subject: [PATCH 11/39] failover: implement new failover interface This crafts and implements the new failover interface, it does not provide complete implementation of the failover mechanism yet. It brings the code to a state were the public and private interfaces are stable, working and testable so the following tasks can be split and work on in parallel. What is missing at this state: - server configuration and discovery (failover_server_group/batch/vtable_op) - server selection mechanism (sss_failover_vtable_op_server_next) - kerberos authentication - sharing servers between IPA/AD LDAP and KDC - online/offline callbacks (resolve callback should not be needed) But especially it is possible to start refactoring SSSD code to start using the new failover implementation. --- Makefile.am | 47 ++ src/providers/failover/failover.c | 214 +++++ src/providers/failover/failover.h | 151 ++++ src/providers/failover/failover_callback.c | 22 + src/providers/failover/failover_group.c | 384 +++++++++ src/providers/failover/failover_group.h | 116 +++ .../failover/failover_refresh_candidates.c | 771 ++++++++++++++++++ .../failover/failover_refresh_candidates.h | 42 + src/providers/failover/failover_server.c | 354 ++++++++ src/providers/failover/failover_server.h | 189 +++++ .../failover/failover_server_resolve.c | 178 ++++ .../failover/failover_server_resolve.h | 64 ++ src/providers/failover/failover_srv.c | 178 ++++ src/providers/failover/failover_srv.h | 66 ++ src/providers/failover/failover_transaction.c | 467 +++++++++++ src/providers/failover/failover_transaction.h | 92 +++ src/providers/failover/failover_vtable.c | 46 ++ src/providers/failover/failover_vtable.h | 97 +++ src/providers/failover/failover_vtable_op.c | 596 ++++++++++++++ src/providers/failover/failover_vtable_op.h | 131 +++ src/providers/failover/ldap/failover_ldap.h | 66 ++ .../failover/ldap/failover_ldap_connect.c | 158 ++++ .../failover/ldap/failover_ldap_kinit.c | 199 +++++ src/providers/failover/readme.md | 185 +++++ src/tests/cmocka/test_failover_server.c | 570 +++++++++++++ src/util/util_errors.c | 1 + src/util/util_errors.h | 1 + 27 files changed, 5385 insertions(+) create mode 100644 src/providers/failover/failover.c create mode 100644 src/providers/failover/failover.h create mode 100644 src/providers/failover/failover_callback.c create mode 100644 src/providers/failover/failover_group.c create mode 100644 src/providers/failover/failover_group.h create mode 100644 src/providers/failover/failover_refresh_candidates.c create mode 100644 src/providers/failover/failover_refresh_candidates.h create mode 100644 src/providers/failover/failover_server.c create mode 100644 src/providers/failover/failover_server.h create mode 100644 src/providers/failover/failover_server_resolve.c create mode 100644 src/providers/failover/failover_server_resolve.h create mode 100644 src/providers/failover/failover_srv.c create mode 100644 src/providers/failover/failover_srv.h create mode 100644 src/providers/failover/failover_transaction.c create mode 100644 src/providers/failover/failover_transaction.h create mode 100644 src/providers/failover/failover_vtable.c create mode 100644 src/providers/failover/failover_vtable.h create mode 100644 src/providers/failover/failover_vtable_op.c create mode 100644 src/providers/failover/failover_vtable_op.h create mode 100644 src/providers/failover/ldap/failover_ldap.h create mode 100644 src/providers/failover/ldap/failover_ldap_connect.c create mode 100644 src/providers/failover/ldap/failover_ldap_kinit.c create mode 100644 src/providers/failover/readme.md create mode 100644 src/tests/cmocka/test_failover_server.c diff --git a/Makefile.am b/Makefile.am index 90803eafdc9..8b29d6c5cc2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -301,6 +301,7 @@ if HAVE_CMOCKA test_sbus_message \ test_sbus_opath \ test_fo_srv \ + test_failover_server \ pam-srv-tests \ ssh-srv-tests \ test_ipa_subdom_util \ @@ -662,6 +663,24 @@ SSSD_FAILOVER_OBJ = \ src/providers/fail_over_srv.c \ $(SSSD_RESOLV_OBJ) +# Make sure to build new failover code to test compilation even though it is +# not used anywhere yet. +SSSD_NEW_FAILOVER_OBJ = \ + src/providers/failover/failover.c \ + src/providers/failover/failover_callback.c \ + src/providers/failover/failover_refresh_candidates.c \ + src/providers/failover/failover_group.c \ + src/providers/failover/failover_server_resolve.c \ + src/providers/failover/failover_server.c \ + src/providers/failover/failover_srv.c \ + src/providers/failover/failover_transaction.c \ + src/providers/failover/failover_vtable_op.c \ + src/providers/failover/failover_vtable.c \ + src/providers/failover/ldap/failover_ldap_connect.c \ + src/providers/failover/ldap/failover_ldap_kinit.c \ + $(SSSD_RESOLV_OBJ) \ + $(NULL) + SSSD_LIBS = \ $(TALLOC_LIBS) \ $(TEVENT_LIBS) \ @@ -854,6 +873,16 @@ dist_noinst_HEADERS = \ src/providers/be_refresh.h \ src/providers/fail_over.h \ src/providers/fail_over_srv.h \ + src/providers/failover/failover.h \ + src/providers/failover/failover_group.h \ + src/providers/failover/failover_refresh_candidates.h \ + src/providers/failover/failover_server.h \ + src/providers/failover/failover_server_resolve.h \ + src/providers/failover/failover_srv.h \ + src/providers/failover/failover_transaction.h \ + src/providers/failover/failover_vtable.h \ + src/providers/failover/failover_vtable_op.h \ + src/providers/failover/ldap/failover_ldap.h \ src/util/child_common.h \ src/util/child_bootstrap.h \ src/providers/simple/simple_access.h \ @@ -3518,6 +3547,24 @@ test_fo_srv_LDADD = \ libsss_test_common.la \ $(NULL) +test_failover_server_SOURCES = \ + src/tests/cmocka/test_failover_server.c \ + src/providers/failover/failover_server.c \ + $(SSSD_RESOLV_TESTS_OBJ) \ + $(NULL) +test_failover_server_CFLAGS = \ + $(AM_CFLAGS) \ + $(CMOCKA_CFLAGS) \ + $(NULL) +test_failover_server_LDADD = \ + $(CARES_LIBS) \ + $(CMOCKA_LIBS) \ + $(POPT_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + $(TALLOC_LIBS) \ + libsss_test_common.la \ + $(NULL) + test_sdap_initgr_SOURCES = \ src/tests/cmocka/common_mock_sdap.c \ src/tests/cmocka/common_mock_sysdb_objects.c \ diff --git a/src/providers/failover/failover.c b/src/providers/failover/failover.c new file mode 100644 index 00000000000..c42d9c81cba --- /dev/null +++ b/src/providers/failover/failover.c @@ -0,0 +1,214 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_group.h" +#include "util/util.h" +#include "util/sss_ptr_list.h" + +static struct sss_failover_candidates_ctx * +sss_failover_candidates_init(TALLOC_CTX *mem_ctx, + unsigned int max_servers, + unsigned int min_refresh_time) +{ + struct sss_failover_candidates_ctx *ctx; + errno_t ret; + + ctx = talloc_zero(mem_ctx, struct sss_failover_candidates_ctx); + if (ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return NULL; + } + + ctx->refresh_req = NULL; + ctx->last_refresh_time = 0; + ctx->min_refresh_time = min_refresh_time; + + /* Setup list of candidate servers. */ + ctx->servers = talloc_zero_array(ctx, struct sss_failover_server *, + max_servers + 1); + if (ctx->servers == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + ctx->notify_queue = tevent_queue_create(ctx, "candidates_notify_queue"); + if (ctx->notify_queue == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + /* Stop the queue. It will be started when candidates are refreshed. */ + tevent_queue_stop(ctx->notify_queue); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(ctx); + return NULL; + } + + return ctx; +} + +static int +sss_failover_destructor(struct sss_failover_ctx *fctx) +{ + return 0; +} + +struct sss_failover_ctx * +sss_failover_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + struct resolv_ctx *resolver_ctx, + enum restrict_family family_order) +{ + struct sss_failover_ctx *fctx; + errno_t ret; + + DEBUG(SSSDBG_TRACE_FUNC, "Creating failover context for service %s\n", + name); + + fctx = talloc_zero(mem_ctx, struct sss_failover_ctx); + if (fctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return NULL; + } + + /* TODO init */ + fctx->ev = ev; + fctx->name = talloc_strdup(fctx, name); + fctx->resolver_ctx = resolver_ctx; + fctx->family_order = family_order; + fctx->kinit_ctx = NULL; + + if (fctx->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + /* Configuration. TODO make it configurable. */ + fctx->opts.max_candidates = 5; + fctx->opts.min_refresh_time = 60; + fctx->opts.ping_timeout = 3; + fctx->opts.negative_dns_srv_ttl = 3600; + fctx->opts.min_candidates_lookup_time = 1; + + /* Setup server groups. We expect at least two groups: primary and backup */ + fctx->current_group = 0; + fctx->groups = talloc_zero_array(fctx, struct sss_failover_group *, 3); + if (fctx->groups == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + /* Setup list of candidate servers. */ + fctx->candidates = sss_failover_candidates_init( + fctx, fctx->opts.max_candidates, fctx->opts.min_refresh_time); + if (fctx->candidates == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + /* We are not connected to any server yet. */ + fctx->active_server = NULL; + + fctx->vtable = talloc_zero(fctx, struct sss_failover_vtable); + if (fctx->vtable == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + fctx->vtable_op_queue = tevent_queue_create(fctx, "vtable_op_queue"); + if (fctx->vtable_op_queue == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + talloc_set_destructor(fctx, sss_failover_destructor); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_zfree(fctx); + } + + return fctx; +} + +void +sss_failover_set_active_server(struct sss_failover_ctx *fctx, + struct sss_failover_server *server) +{ + if (fctx->active_server != NULL) { + if (server == fctx->active_server) { + /* it is the same server, nothing to do */ + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Releasing old active server %s\n", + fctx->active_server->name); + + talloc_unlink(fctx, fctx->active_server); + } + + DEBUG(SSSDBG_TRACE_FUNC, "Setting new active server %s\n", server->name); + fctx->active_server = talloc_reference(fctx, server); +} + +void +sss_failover_set_connection(struct sss_failover_ctx *fctx, void *connection) +{ + if (fctx->connection != NULL) { + if (connection == fctx->connection) { + /* it is the same connection, nothing to do */ + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Releasing old connection %p\n", + fctx->connection); + + talloc_unlink(fctx, fctx->connection); + } + + DEBUG(SSSDBG_TRACE_FUNC, "Setting new connection %p\n", connection); + fctx->connection = talloc_steal(fctx, connection); +} + +void * +sss_failover_get_connection(TALLOC_CTX *mem_ctx, struct sss_failover_ctx *fctx) +{ + if (fctx->connection == NULL) { + return NULL; + } + + return talloc_reference(mem_ctx, fctx->connection); +} diff --git a/src/providers/failover/failover.h b/src/providers/failover/failover.h new file mode 100644 index 00000000000..91d34b2610b --- /dev/null +++ b/src/providers/failover/failover.h @@ -0,0 +1,151 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_H_ +#define _FAILOVER_H_ + +#include +#include + +#include "config.h" +#include "resolv/async_resolv.h" +#include "providers/failover/failover_server.h" +#include "providers/failover/failover_group.h" +#include "providers/failover/failover_vtable.h" +#include "util/util.h" + +struct sss_failover_candidates_ctx { + /* List of servers that were found as working. */ + struct sss_failover_server **servers; + + /* Active refresh request. NULL if there is no ongoing refresh. */ + struct tevent_req *refresh_req; + + /* This queue serves as a notification mechanism. It is started when + * candidates list were refreshed and is stopped when the list is being + * refreshed. + */ + struct tevent_queue *notify_queue; + + /* Last refresh time. */ + unsigned int last_refresh_time; + + /* Do not issue new refresh if now < last_refresh_time + min_refresh_time */ + unsigned int min_refresh_time; +}; + +struct sss_failover_options { + /* Maximum number of candidate servers. */ + unsigned int max_candidates; + + /* Minimum time that has to elapse before refreshing candidates again. */ + unsigned int min_refresh_time; + + /* Minimum amount of time that will wait for candidates servers to respond + to a ping. If any server is found within this time, we do not wait for other + servers to respond and return what we have. */ + unsigned int min_candidates_lookup_time; + + /* How long do we want to wait for a server ping to succeed. */ + unsigned int ping_timeout; + + /* TTL for missing DNS SRV records. */ + unsigned int negative_dns_srv_ttl; +}; + +struct sss_failover_ctx { + struct tevent_context *ev; + char *name; + struct resolv_ctx *resolver_ctx; + struct sss_failover_vtable *vtable; + enum restrict_family family_order; + + struct sss_failover_options opts; + + /* NULL-terminated list of failover server groups. The first group has the + * highest priority. */ + struct sss_failover_group **groups; + + /* Currently selected group that provided server candidates. */ + unsigned int current_group; + + /* Non-NULL if kinit is required to connect to the server. The context may + * be the same to make sure the same server is used for KDC and connection + * or different. */ + struct sss_failover_ctx *kinit_ctx; + + /* Candidate servers. */ + struct sss_failover_candidates_ctx *candidates; + + /* Currently active server. */ + struct sss_failover_server *active_server; + + /* Backend specific established connection. */ + void *connection; + + /* Queue of sss_vtable_op tevent requests. These requests are used to + * connect to the server and the queue serializes the requests to ensure + * that we establish only one connection that is then reused. */ + struct tevent_queue *vtable_op_queue; +}; + +/** + * @brief Initialize failover context. + * + * @param mem_ctx + * @param ev + * @param resolver_ctx + * @param family_order + * @return struct sss_failover_ctx* + */ +struct sss_failover_ctx * +sss_failover_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + struct resolv_ctx *resolver_ctx, + enum restrict_family family_order); + +/** + * @brief Set active server. + * + * This is a noop if @server and @fctx->active_server is identical. + */ +void +sss_failover_set_active_server(struct sss_failover_ctx *fctx, + struct sss_failover_server *server); + +/** + * @brief Set new connection, release old one. + * + * This is a noop if @connection and @fctx->connection is identical. + */ +void +sss_failover_set_connection(struct sss_failover_ctx *fctx, void *connection); + +/** + * @brief Get connection. + * + * The connection is talloc_reference to mem_ctx. + * + * @param mem_ctx + * @param fctx + * @return void* + */ +void * +sss_failover_get_connection(TALLOC_CTX *mem_ctx, struct sss_failover_ctx *fctx); + +#endif /* _FAILOVER_H_ */ diff --git a/src/providers/failover/failover_callback.c b/src/providers/failover/failover_callback.c new file mode 100644 index 00000000000..1d43351bbee --- /dev/null +++ b/src/providers/failover/failover_callback.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "util/util.h" diff --git a/src/providers/failover/failover_group.c b/src/providers/failover/failover_group.c new file mode 100644 index 00000000000..02a1ddf6680 --- /dev/null +++ b/src/providers/failover/failover_group.c @@ -0,0 +1,384 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include + +#include "config.h" +#include "providers/failover/failover_group.h" +#include "providers/failover/failover_server.h" +#include "providers/failover/failover_srv.h" +#include "providers/failover/failover.h" +#include "util/util.h" + +static errno_t +sss_failover_group_allocate_slot(struct sss_failover_ctx *fctx, + unsigned int *_slot) +{ + size_t count; + unsigned int slot; + + count = talloc_array_length(fctx->groups); + + for (slot = 0; fctx->groups[slot] != NULL && slot < count; slot++) { + /* Find the first NULL slot. slot < count is just for safety */ + } + + /* We need to allocate more items? */ + if (slot >= count - 1) { + fctx->groups = talloc_realloc(fctx, fctx->groups, + struct sss_failover_group *, count + 1); + if (fctx->groups == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + fctx->groups[count] = NULL; + fctx->groups[count - 1] = NULL; + slot = count - 1; + } + + *_slot = slot; + + return EOK; +} + +struct sss_failover_group * +sss_failover_group_new(struct sss_failover_ctx *fctx, + const char *name) +{ + struct sss_failover_group *group; + unsigned int slot; + errno_t ret; + + if (name == NULL || fctx == NULL || fctx->groups == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid parameters!\n"); + return NULL; + } + + ret = sss_failover_group_allocate_slot(fctx, &slot); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate slot [%d]: %s\n", ret, + sss_strerror(ret)); + return NULL; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Creating failover group %s:%u\n", name, slot); + + group = talloc_zero(fctx->groups, struct sss_failover_group); + if (group == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return NULL; + } + + group->name = talloc_strdup(group, name); + if (group->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + group->slot = slot; + + group->configured_servers = talloc_zero_array(group, struct sss_failover_server *, 1); + if (group->configured_servers == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + } + + group->dns_discovery_enabled = false; + group->discovered_servers = talloc_zero_array(group, struct sss_failover_server *, 1); + if (group->discovered_servers == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + } + + group->servers = talloc_zero_array(group, struct sss_failover_server *, 1); + if (group->servers == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + } + + fctx->groups[slot] = group; + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(group); + return NULL; + } + + return group; +} + +errno_t +sss_failover_group_setup_dns_discovery(struct sss_failover_group *group) +{ + group->dns_discovery_enabled = true; + + return EOK; +} + +errno_t +sss_failover_group_add_server(struct sss_failover_group *group, + struct sss_failover_server *server) +{ + struct sss_failover_server **new_array; + size_t count; + + if (group == NULL || group->configured_servers == NULL || server == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid arguments\n"); + return EINVAL; + } + + count = talloc_array_length(group->configured_servers); + + new_array = talloc_realloc(group, group->configured_servers, + struct sss_failover_server *, count + 1); + if (new_array == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + group->configured_servers = new_array; + group->configured_servers[count - 1] = talloc_steal(group->configured_servers, server); + group->configured_servers[count] = NULL; + + return EOK; +} + +struct sss_failover_group_resolve_state { + struct sss_failover_ctx *fctx; + struct sss_failover_group *group; +}; + +static void sss_failover_group_resolve_done(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_group_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_group *group) +{ + struct sss_failover_group_resolve_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; + time_t now; + + DEBUG(SSSDBG_TRACE_FUNC, "Resolving server group %s:%d\n", group->name, + group->slot); + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_group_resolve_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->fctx = fctx; + state->group = group; + + now = time(NULL); + if (group->dns_discovery_enabled && group->dns_expiration_time < now) { + /* Refresh SRV records. */ + const char *domains[] = {"ldap.test", NULL}; + const char *protocol = "tcp"; + const char *service = "ldap"; + + // TODO handle protocol, service, domains and plugin + subreq = sss_failover_srv_resolve_send(state, ev, fctx, service, + protocol, domains); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_group_resolve_done, req); + + ret = EAGAIN; + } else { + /* We have what we need. */ + ret = EOK; + } + +done: + if (ret == EOK) { + tevent_req_done(req); + tevent_req_post(req, ev); + } else if (ret != EAGAIN) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void sss_failover_group_resolve_done(struct tevent_req *subreq) +{ + struct sss_failover_group_resolve_state *state; + struct sss_failover_server **servers; + struct tevent_req *req; + uint32_t ttl; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_group_resolve_state); + + ret = sss_failover_srv_resolve_recv(state, subreq, &ttl, + &servers); + talloc_zfree(subreq); + if (ret == ENOENT) { + ttl = state->fctx->opts.negative_dns_srv_ttl; + servers = talloc_zero_array(state, struct sss_failover_server *, 1); + if (servers == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + ret = EOK; + } else if (ret != EOK) { + goto done; + } + + talloc_zfree(state->group->discovered_servers); + state->group->discovered_servers = talloc_steal(state->group, servers); + state->group->dns_expiration_time = time(NULL) + ttl; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_group_resolve_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server ***_servers) +{ + struct sss_failover_group_resolve_state *state; + struct sss_failover_server *current; + struct sss_failover_server **out; + size_t count_conf; + size_t count_dns; + size_t count; + int i, j, k; + bool found; + + state = tevent_req_data(req, struct sss_failover_group_resolve_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + count_conf = talloc_array_length(state->group->configured_servers) - 1; + count_dns = talloc_array_length(state->group->discovered_servers) - 1; + count = count_conf + count_dns; + + DEBUG(SSSDBG_TRACE_FUNC, + "There are %zu configured servers inside group %d:%s:\n", + count_conf, state->group->slot, state->group->name); + + if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { + for (i = 0; state->group->configured_servers[i] != NULL; i++) { + current = state->group->configured_servers[i]; + DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", current->name, current->port); + } + } + + if (state->group->dns_discovery_enabled) { + DEBUG(SSSDBG_TRACE_FUNC, + "Discovered %zu servers from DNS inside group %d:%s:\n", + count_dns, state->group->slot, state->group->name); + + if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { + for (i = 0; state->group->discovered_servers[i] != NULL; i++) { + current = state->group->discovered_servers[i]; + DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", current->name, + current->port); + } + } + } + + out = talloc_zero_array(mem_ctx, struct sss_failover_server *, count + 1); + if (out == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + /* Add configured servers first. */ + for (i = 0; state->group->configured_servers[i] != NULL; i++) { + out[i] = talloc_reference(out, state->group->configured_servers[i]); + if (out[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + talloc_free(out); + return ENOMEM; + } + } + + /* Now add discovered servers. But avoid adding duplicates. */ + for (j = 0; state->group->discovered_servers[j] != NULL; j++) { + found = false; + current = state->group->discovered_servers[j]; + for (k = 0; out[k] != NULL; k++) { + if (sss_failover_server_equal(out[k], current)) { + found = true; + break; + } + } + + if (found) { + continue; + } + + out[i] = talloc_reference(out, current); + if (out[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + talloc_free(out); + return ENOMEM; + } + i++; + } + + + // TODO sort by priority and weight + + for (count = 0; out[count] != NULL; count++); + out = talloc_realloc(mem_ctx, out, struct sss_failover_server *, count + 1); + if (out == NULL) { + talloc_free(out); + return ENOMEM; + } + + if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { + DEBUG(SSSDBG_TRACE_ALL, "Sorted server list without duplicates:\n"); + for (i = 0; out[i] != NULL; i++) { + DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", out[i]->name, out[i]->port); + } + } + + DEBUG(SSSDBG_TRACE_FUNC, "Returning %zu servers from group %d:%s\n", count, + state->group->slot, state->group->name); + + *_servers = out; + + return EOK; +} diff --git a/src/providers/failover/failover_group.h b/src/providers/failover/failover_group.h new file mode 100644 index 00000000000..0527109d6e6 --- /dev/null +++ b/src/providers/failover/failover_group.h @@ -0,0 +1,116 @@ +;/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_GROUP_H_ +#define _FAILOVER_GROUP_H_ + +#include + +#include "config.h" +#include "util/util.h" +#include "providers/failover/failover_server.h" + +struct sss_failover_ctx; + +struct sss_failover_group { + struct sss_failover_ctx *fctx; + + /* Group name. */ + char *name; + + /* Priority. 0 = highest priority (primary servers). */ + unsigned int slot; + + /* DNS SRV plugin information */ + bool dns_discovery_enabled; + time_t dns_expiration_time; + void *dns_plugin_data; + void *dns_plugin; + + /* Configured or discovered servers. */ + struct sss_failover_server **configured_servers; + struct sss_failover_server **discovered_servers; + + /* Servers inside this group. Sorted by priority and weight. */ + struct sss_failover_server **servers; +}; + +/** + * @brief Create new server group @name. + * + * Add new static servers to it with @sss_failover_server_group_add_server. + * + * @param fctx + * @param name + * @return struct sss_failover_group* + */ +struct sss_failover_group * +sss_failover_group_new(struct sss_failover_ctx *fctx, + const char *name); + +/** + * @brief Enable DNS discovery within this group. + * + * @param group + * @return errno_t + */ +errno_t +sss_failover_group_setup_dns_discovery(struct sss_failover_group *group); + +/** + * @brief Add new server to the failover group. + * + * @param group + * @param server + * @return errno_t + */ +errno_t +sss_failover_group_add_server(struct sss_failover_group *group, + struct sss_failover_server *server); + +/** + * @brief Resolve servers within this group. + * + * It does not resolve servers to IP address, it resolves the DNS SRV record + * (if required) and combine SRV servers with those statically configured. + * + * @param mem_ctx + * @param ev + * @param fctx + * @param group + * @return struct tevent_req* + */ +struct tevent_req * +sss_failover_group_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_group *group); + +/** + * @brief Return list of servers within this group. + * + * @param mem_ctx + * @param req + * @param _servers + * @return errno_t + */ +errno_t +sss_failover_group_resolve_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server ***_servers); + +#endif /* _FAILOVER_GROUP_H_ */ diff --git a/src/providers/failover/failover_refresh_candidates.c b/src/providers/failover/failover_refresh_candidates.c new file mode 100644 index 00000000000..bc387a4c602 --- /dev/null +++ b/src/providers/failover/failover_refresh_candidates.c @@ -0,0 +1,771 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include +#include + +#include "config.h" +#include "util/util.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_group.h" +#include "providers/failover/failover_refresh_candidates.h" +#include "providers/failover/failover_server_resolve.h" +#include "util/sss_sockets.h" + +struct sss_failover_ping_state { + struct tevent_context *ev; + struct sss_failover_ctx *fctx; + struct sss_failover_server *server; + unsigned int timeout; + + struct timeval ping_start; +}; + +static void +sss_failover_ping_resolved(struct tevent_req *subreq); + +static void +sss_failover_ping_done(struct tevent_req *subreq); + +static struct tevent_req * +sss_failover_ping_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + unsigned int timeout) +{ + struct sss_failover_ping_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_ping_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->ev = ev; + state->fctx = fctx; + state->server = server; + state->timeout = timeout; + + subreq = sss_failover_server_resolve_send(state, ev, + state->fctx->resolver_ctx, + state->fctx->family_order, + state->server); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_ping_resolved, req); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void +sss_failover_ping_resolved(struct tevent_req *subreq) +{ + struct sss_failover_ping_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ping_state); + + ret = sss_failover_server_resolve_recv(subreq, NULL); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Pinging %s:%d (%s)\n", state->server->name, + state->server->port, state->server->addr->human); + + state->ping_start = tevent_timeval_current(); + + subreq = sssd_async_socket_init_send(state, state->ev, false, + state->server->addr->sockaddr, + state->server->addr->sockaddr_len, + state->timeout); + if (subreq == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_ping_done, req); + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } +} + +static void sss_failover_ping_done(struct tevent_req *subreq) +{ + struct sss_failover_ping_state *state; + struct timeval ping_duration; + struct timeval ping_end; + struct tevent_req *req; + errno_t ret; + int fd; + + ping_end = tevent_timeval_current(); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ping_state); + + ret = sssd_async_socket_init_recv(subreq, &fd); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Server %s:%d is not reachable within %d seconds [%d]: %s\n", + state->server->name, state->server->port, state->timeout, ret, + sss_strerror(ret)); + goto done; + } + + close(fd); + + ping_duration = tevent_timeval_until(&state->ping_start, &ping_end); + DEBUG(SSSDBG_TRACE_FUNC, "Server %s:%d responded in %lds:%ldus\n", + state->server->name, state->server->port, ping_duration.tv_sec, + ping_duration.tv_usec); + + sss_failover_server_mark_reachable(state->server); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +static errno_t +sss_failover_ping_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server) +{ + struct sss_failover_ping_state *state; + + TEVENT_REQ_RETURN_ON_ERROR(req); + + state = tevent_req_data(req, struct sss_failover_ping_state); + *_server = talloc_reference(mem_ctx, state->server); + + return EOK; +} + +struct sss_failover_ping_parallel_state { + struct tevent_context *ev; + struct sss_failover_ctx *fctx; + struct sss_failover_server **servers; + unsigned int shortcut_time; + unsigned int max_servers; + + TALLOC_CTX *reqs_ctx; + struct tevent_timer *shortcut_te; + struct tevent_timer *batch_te; + unsigned int shortcut_attempts; + unsigned int active_requests; + unsigned int batch; + size_t next_server; + size_t count; + + struct sss_failover_server **candidates; + size_t candidates_index; +}; + +static void +sss_failover_ping_parallel_cleanup(struct tevent_req *req, + enum tevent_req_state req_state); + +static struct tevent_timer * +sss_failover_ping_parallel_shortcut_setup(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + unsigned int delay, + struct tevent_req *req); +static void +sss_failover_ping_parallel_shortcut(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *data); + +static void +sss_failover_ping_parallel_batch(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *data); + +static void +sss_failover_ping_parallel_done(struct tevent_req *subreq); + +static struct tevent_req * +sss_failover_ping_parallel_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server **servers, + unsigned int max_servers, + unsigned int shortcut_time) +{ + struct sss_failover_ping_parallel_state *state; + struct timeval tv = {0, 0}; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_ping_parallel_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->ev = ev; + state->fctx = fctx; + state->servers = servers; + state->max_servers = max_servers; + state->shortcut_time = shortcut_time; + + state->batch = 1; + state->next_server = 0; + state->count = talloc_array_length(servers) - 1; + + state->reqs_ctx = talloc_new(state); + if (state->reqs_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + state->candidates_index = 0; + state->candidates = talloc_zero_array(state, struct sss_failover_server *, + max_servers + 1); + if (state->candidates == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + tevent_req_set_cleanup_fn(req, sss_failover_ping_parallel_cleanup); + + state->shortcut_attempts = 0; + state->shortcut_te = sss_failover_ping_parallel_shortcut_setup( + state, state->ev, state->shortcut_time, req); + + sss_failover_ping_parallel_batch(ev, NULL, tv, req); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void +sss_failover_ping_parallel_cleanup(struct tevent_req *req, + enum tevent_req_state req_state) +{ + struct sss_failover_ping_parallel_state *state; + + state = tevent_req_data(req, struct sss_failover_ping_parallel_state); + + /* This request is done. Terminate any remaining timers and pings. */ + talloc_zfree(state->shortcut_te); + talloc_zfree(state->batch_te); + talloc_zfree(state->reqs_ctx); + state->active_requests = 0; +} + +static struct tevent_timer * +sss_failover_ping_parallel_shortcut_setup(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + unsigned int delay, + struct tevent_req *req) +{ + struct tevent_timer *te; + struct timeval tv; + + tv = tevent_timeval_current_ofs(delay, 0); + te = tevent_add_timer(ev, mem_ctx, tv, + sss_failover_ping_parallel_shortcut, req); + if (te == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule next shortcut!\n"); + } + + return te; +} + +static void +sss_failover_ping_parallel_shortcut(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *data) +{ + struct sss_failover_ping_parallel_state *state; + struct tevent_req *req; + + req = talloc_get_type(data, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ping_parallel_state); + + state->shortcut_te = NULL; + state->shortcut_attempts++; + + /* There is at least one candidate server available. Return it. */ + if (state->candidates[0] != NULL) { + DEBUG(SSSDBG_TRACE_FUNC, + "Some candidates were already found in %d seconds, do not wait " + "for others\n", + state->shortcut_time * state->shortcut_attempts); + tevent_req_done(req); + return; + } + + state->shortcut_te = sss_failover_ping_parallel_shortcut_setup( + state, state->ev, state->shortcut_time, req); +} + +static void +sss_failover_ping_parallel_batch(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *data) +{ + struct sss_failover_ping_parallel_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + uint32_t delay; + size_t limit; + size_t i; + + req = talloc_get_type(data, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ping_parallel_state); + + state->batch_te = NULL; + + /* Issue three batches in total to avoid pinging too many servers if not + * necessary. We want to find @max_servers working servers. The first batch + * (@max_servers pings) is issued immediately and we will wait 400ms for it + * to finish. If we don't get a reply in time we issue next batch + * (@max_servers pings) and wait 200ms. If we still have no reply, we ping + * remaining servers. + */ + switch (state->batch) { + case 1: + case 2: + limit = MIN(state->count, state->max_servers + state->next_server); + delay = 400000 / state->batch; + break; + default: + limit = state->count; + delay = 0; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Sending ping to servers from batch %d\n", + state->batch); + + for (i = state->next_server; i < limit; i++) { + DEBUG(SSSDBG_TRACE_ALL, "Batch %d: %s:%d\n", state->batch, + state->servers[i]->name, state->servers[i]->port); + } + + for (; state->next_server < limit; state->next_server++) { + subreq = sss_failover_ping_send(state->reqs_ctx, ev, state->fctx, + state->servers[state->next_server], + state->fctx->opts.ping_timeout); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to create new ping request\n"); + goto fail; + } + + state->active_requests++; + tevent_req_set_callback(subreq, sss_failover_ping_parallel_done, req); + } + + state->batch++; + if (delay > 0) { + tv = tevent_timeval_current_ofs(0, delay); + state->batch_te = tevent_add_timer(ev, state, tv, + sss_failover_ping_parallel_batch, req); + if (state->batch_te == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule next batch!\n"); + goto fail; + } + } + + return; + +fail: + if (state->active_requests == 0) { + tevent_req_error(req, ENOMEM); + if (state->batch == 1) { + tevent_req_post(req, ev); + } + } +} + +static void +sss_failover_ping_parallel_done(struct tevent_req *subreq) +{ + struct sss_failover_ping_parallel_state *state; + struct timeval tv = {0, 0}; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ping_parallel_state); + + ret = sss_failover_ping_recv(state->candidates, subreq, + &state->candidates[state->candidates_index]); + talloc_zfree(subreq); + state->active_requests--; + + if (ret == EOK) { + state->candidates_index++; + } + + /* Are we done? */ + if (state->candidates_index == state->max_servers) { + tevent_req_done(req); + return; + } + + if (state->active_requests == 0) { + /* There are still servers to try, don't wait for the timer. */ + if (state->next_server < state->count) { + talloc_zfree(state->batch_te); + sss_failover_ping_parallel_batch(state->ev, NULL, tv, req); + return; + } + + /* All servers were tried. */ + tevent_req_done(req); + return; + } + + /* Wait for another ping to finish. */ +} + +static errno_t +sss_failover_ping_parallel_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + size_t *_num_servers, + struct sss_failover_server ***_servers) +{ + struct sss_failover_ping_parallel_state *state; + + state = tevent_req_data(req, struct sss_failover_ping_parallel_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *_num_servers = state->candidates_index; + *_servers = talloc_steal(mem_ctx, state->candidates); + + return EOK; +} + +struct sss_failover_refresh_candidates_state { + struct tevent_context *ev; + struct sss_failover_ctx *fctx; + + unsigned int current_group; + struct sss_failover_group *group; + struct sss_failover_server **group_servers; +}; + +static errno_t +sss_failover_refresh_candidates_group_next(struct tevent_req *req); + +static void +sss_failover_refresh_candidates_group_resolved(struct tevent_req *subreq); + +static void +sss_failover_refresh_candidates_done(struct tevent_req *subreq); + +errno_t +sss_failover_refresh_candidates_recv(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_refresh_candidates_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx) +{ + struct sss_failover_refresh_candidates_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_refresh_candidates_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->ev = ev; + state->fctx = fctx; + state->current_group = 0; + state->group = state->fctx->groups[0]; + + state->fctx->candidates->last_refresh_time = time(NULL); + state->fctx->candidates->refresh_req = req; + + DEBUG(SSSDBG_TRACE_FUNC, "Refreshing failover server candidates\n"); + + /* Stop the queue as we are refreshing the candidates list now. */ + DEBUG(SSSDBG_TRACE_FUNC, "Stopping candidates notification queue\n"); + tevent_queue_stop(fctx->candidates->notify_queue); + + ret = sss_failover_refresh_candidates_group_next(req); + + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static errno_t +sss_failover_refresh_candidates_group_next(struct tevent_req *req) +{ + struct sss_failover_refresh_candidates_state *state; + struct tevent_req *subreq; + + state = tevent_req_data(req, struct sss_failover_refresh_candidates_state); + state->group = state->fctx->groups[state->current_group]; + + if (state->group == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "No more groups to try\n"); + return ENOENT; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Trying failover group: %s:%u\n", + state->group->name, state->group->slot); + + subreq = sss_failover_group_resolve_send(state, state->ev, state->fctx, + state->group); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, + sss_failover_refresh_candidates_group_resolved, + req); + + return EOK; +} + +static void +sss_failover_refresh_candidates_group_resolved(struct tevent_req *subreq) +{ + struct sss_failover_refresh_candidates_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_refresh_candidates_state); + + talloc_zfree(state->group_servers); + ret = sss_failover_group_resolve_recv(state, subreq, &state->group_servers); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + /* No servers found, try next group. */ + if (state->group_servers[0] == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, "No servers found, trying next group\n"); + + state->current_group++; + ret = sss_failover_refresh_candidates_group_next(req); + if (ret != EOK) { + goto done; + } + + return; + } + + /* Servers found. Ping them in multiple batches. */ + subreq = sss_failover_ping_parallel_send(state, state->ev, state->fctx, + state->group_servers, + state->fctx->opts.max_candidates, + state->fctx->opts.min_candidates_lookup_time); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_refresh_candidates_done, req); + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + } +} + +static void +sss_failover_refresh_candidates_done(struct tevent_req *subreq) +{ + struct sss_failover_refresh_candidates_state *state; + struct sss_failover_server **candidates; + struct tevent_req *req; + size_t count; + errno_t ret; + int i; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_refresh_candidates_state); + + ret = sss_failover_ping_parallel_recv(state, subreq, &count, &candidates); + talloc_zfree(subreq); + if (ret != EOK) { + /* This is system error like ENOMEM. Not functional. */ + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to ping any server [%d]: %s\n", ret, + sss_strerror(ret)); + goto done; + } + + if (count == 0) { + DEBUG(SSSDBG_TRACE_FUNC, "No servers found, trying next group\n"); + + state->current_group++; + ret = sss_failover_refresh_candidates_group_next(req); + if (ret != EOK) { + goto done; + } + + /* Pinging next group. */ + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Found %zu candidate servers in group %s:%u\n", + count, state->group->name, state->group->slot); + + if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { + for (i = 0; candidates[i] != NULL; i++) { + DEBUG(SSSDBG_TRACE_ALL, "Found candidate server: %s:%u\n", + candidates[i]->name, candidates[i]->port); + } + } + + talloc_unlink(state->fctx->candidates, state->fctx->candidates->servers); + state->fctx->candidates->servers = talloc_steal(state->fctx->candidates, + candidates); + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_refresh_candidates_recv(struct tevent_req *req) +{ + struct sss_failover_refresh_candidates_state *state; + + state = tevent_req_data(req, struct sss_failover_refresh_candidates_state); + + state->fctx->candidates->last_refresh_time = time(NULL); + state->fctx->candidates->refresh_req = NULL; + + /* Notify listeners that refresh is finished. */ + DEBUG(SSSDBG_TRACE_FUNC, "Starting candidates notification queue\n"); + tevent_queue_start(state->fctx->candidates->notify_queue); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +bool +sss_failover_refresh_candidates_oob_can_run(struct sss_failover_ctx *fctx) +{ + time_t now; + + now = time(NULL); + + /* There is ongoing active request? */ + if (fctx->candidates->refresh_req != NULL) { + return false; + } + + /* Has enough time elapsed? */ + if (now <= fctx->candidates->last_refresh_time + + fctx->candidates->min_refresh_time) { + return false; + } + + return true; +} + +static void +sss_failover_refresh_candidates_oob_done(struct tevent_req *subreq); + +void +sss_failover_refresh_candidates_oob_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx) +{ + struct tevent_req *subreq; + + if (!sss_failover_refresh_candidates_oob_can_run(fctx)) { + DEBUG(SSSDBG_TRACE_FUNC, "Minimum refresh time has not elapsed yet or " + "there is an active refresh request.\n"); + return; + } + + subreq = sss_failover_refresh_candidates_send(mem_ctx, ev, fctx); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return; + } + + tevent_req_set_callback(subreq, sss_failover_refresh_candidates_oob_done, + NULL); +} + +static void +sss_failover_refresh_candidates_oob_done(struct tevent_req *subreq) +{ + sss_failover_refresh_candidates_recv(subreq); + talloc_free(subreq); +} diff --git a/src/providers/failover/failover_refresh_candidates.h b/src/providers/failover/failover_refresh_candidates.h new file mode 100644 index 00000000000..1bbdaa1abe5 --- /dev/null +++ b/src/providers/failover/failover_refresh_candidates.h @@ -0,0 +1,42 @@ +;/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_REFRESH_CANDIDATES_H_ +#define _FAILOVER_REFRESH_CANDIDATES_H_ + +#include + +#include "config.h" +#include "providers/failover/failover.h" + +struct tevent_req * +sss_failover_refresh_candidates_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx); + +errno_t +sss_failover_refresh_candidates_recv(struct tevent_req *req); + +bool +sss_failover_refresh_candidates_oob_can_run(struct sss_failover_ctx *fctx); + +void +sss_failover_refresh_candidates_oob_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx); + +#endif /* _FAILOVER_REFRESH_CANDIDATES_H_ */ diff --git a/src/providers/failover/failover_server.c b/src/providers/failover/failover_server.c new file mode 100644 index 00000000000..e0fe901d3e3 --- /dev/null +++ b/src/providers/failover/failover_server.c @@ -0,0 +1,354 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include +#include + +#include "config.h" +#include "providers/failover/failover_server.h" +#include "util/util.h" + +static struct sss_failover_server_address * +sss_failover_server_address_new(TALLOC_CTX *mem_ctx, + const uint16_t port, + const int family, + const time_t expire, + const uint8_t *addr_binary) +{ + struct sss_failover_server_address *out; + char buf[INET6_ADDRSTRLEN] = {0}; + const char *ntop_result; + struct sockaddr_in *in4; + struct sockaddr_in6 *in6; + errno_t ret; + + if (addr_binary == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Empty IP address!\n"); + return NULL; + } + + out = talloc_zero(mem_ctx, struct sss_failover_server_address); + if (out == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + out->family = family; + out->expire = expire; + + switch (family) { + case AF_INET: + out->binary_len = sizeof(struct in_addr); + out->sockaddr_len = sizeof(struct sockaddr_in); + + in4 = talloc_zero(out, struct sockaddr_in); + if (in4 == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + in4->sin_family = AF_INET; + in4->sin_port = (in_port_t)htons(port); + memcpy(&in4->sin_addr, addr_binary, out->binary_len); + out->sockaddr = (struct sockaddr *)in4; + break; + case AF_INET6: + out->binary_len = sizeof(struct in6_addr); + out->sockaddr_len = sizeof(struct sockaddr_in6); + + in6 = talloc_zero(out, struct sockaddr_in6); + if (in6 == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + in6->sin6_family = AF_INET6; + in6->sin6_port = (in_port_t)htons(port); + memcpy(&in6->sin6_addr, addr_binary, out->binary_len); + out->sockaddr = (struct sockaddr *)in6; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unknown IP family: %d\n", out->family); + ret = EINVAL; + goto done; + } + + out->binary = talloc_memdup(out, addr_binary, out->binary_len); + if (out->binary == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + ntop_result = inet_ntop(family, addr_binary, buf, INET6_ADDRSTRLEN); + if (ntop_result == NULL) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "Unable to convert IP address to string [%d]: %s\n", ret, + sss_strerror(ret)); + goto done; + } + + out->human = talloc_strdup(out, ntop_result); + if (out->human == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(out); + return NULL; + } + + return out; +} + +struct sss_failover_server * +sss_failover_server_new(TALLOC_CTX *mem_ctx, + const char *hostname, + const char *uri, + const uint16_t port, + const int priority, + const int weight) +{ + struct sss_failover_server *srv; + + if (hostname == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Hostname is not set!\n"); + return NULL; + } + + srv = talloc_zero(mem_ctx, struct sss_failover_server); + if (srv == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return NULL; + } + + srv->name = talloc_strdup(srv, hostname); + if (srv->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + talloc_free(srv); + return NULL; + } + + srv->uri = talloc_strdup(srv, uri); + if (srv->uri == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + talloc_free(srv); + return NULL; + } + + srv->port = port; + srv->priority = priority; + srv->weight = weight; + + return srv; +} + +errno_t +sss_failover_server_set_address(struct sss_failover_server *srv, + int family, + int ttl, + const uint8_t *addr) +{ + struct sss_failover_server_address *new_addr; + time_t expire; + + if (family != AF_INET && family != AF_INET6) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid family given: %d\n", family); + return EINVAL; + } + + if (addr == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Empty addr given\n"); + return EINVAL; + } + + expire = time(NULL) + ttl; + new_addr = sss_failover_server_address_new(srv, srv->port, family, expire, + addr); + if (new_addr == NULL) { + return ENOMEM; + } + + if (srv->addr != NULL) { + talloc_free(srv->addr); + } + + srv->addr = new_addr; + + DEBUG(SSSDBG_TRACE_FUNC, "Server %s resolved to %s, ttl %d\n", + srv->name, srv->addr->human, ttl); + + return EOK; +} + +struct sss_failover_server * +sss_failover_server_clone(TALLOC_CTX *mem_ctx, + const struct sss_failover_server *srv) +{ + struct sss_failover_server *out; + errno_t ret; + + if (srv == NULL || srv->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Empty failover server information!\n"); + return NULL; + } + + if (srv->addr != NULL + && (srv->addr->binary == NULL || srv->addr->human == NULL)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Address is not complete!\n"); + return NULL; + } + + out = talloc_zero(mem_ctx, struct sss_failover_server); + if (out == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return NULL; + } + + out->priority = srv->priority; + out->weight = srv->weight; + out->port = srv->port; + out->state = srv->state; + + out->name = talloc_strdup(out, srv->name); + if (out->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + if (srv->uri != NULL) { + out->uri = talloc_strdup(out, srv->uri); + if (out->uri == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + } + + if (srv->addr == NULL) { + ret = EOK; + goto done; + } + + out->addr = sss_failover_server_address_new(out, srv->port, + srv->addr->family, + srv->addr->expire, + srv->addr->binary); + if (out->addr == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create new server address!\n"); + ret = ENOMEM; + goto done; + } + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(out); + return NULL; + } + + return out; +} + +bool +sss_failover_server_maybe_working(struct sss_failover_server *srv) +{ + switch (srv->state) { + case SSS_FAILOVER_SERVER_STATE_OFFLINE: + case SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR: + return false; + case SSS_FAILOVER_SERVER_STATE_UNKNOWN: + case SSS_FAILOVER_SERVER_STATE_REACHABLE: + case SSS_FAILOVER_SERVER_STATE_WORKING: + return true; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: unknown state [%d]!\n", srv->state); + return false; + } +} + +void +sss_failover_server_mark_unknown(struct sss_failover_server *srv) +{ + DEBUG(SSSDBG_TRACE_FUNC, + "Marking server [%s] as state unknown\n", srv->name); + srv->state = SSS_FAILOVER_SERVER_STATE_UNKNOWN; +} + +void +sss_failover_server_mark_reachable(struct sss_failover_server *srv) +{ + DEBUG(SSSDBG_TRACE_FUNC, + "Marking server [%s] as reachable\n", srv->name); + srv->state = SSS_FAILOVER_SERVER_STATE_REACHABLE; +} + +void +sss_failover_server_mark_working(struct sss_failover_server *srv) +{ + DEBUG(SSSDBG_TRACE_FUNC, + "Marking server [%s] as functional\n", srv->name); + srv->state = SSS_FAILOVER_SERVER_STATE_WORKING; +} + +void +sss_failover_server_mark_offline(struct sss_failover_server *srv) +{ + DEBUG(SSSDBG_TRACE_FUNC, "Marking server [%s] as offline\n", srv->name); + srv->state = SSS_FAILOVER_SERVER_STATE_OFFLINE; +} + +void +sss_failover_server_mark_resolver_error(struct sss_failover_server *srv) +{ + DEBUG(SSSDBG_TRACE_FUNC, + "Marking server [%s] as unable to resolve hostname\n", srv->name); + srv->state = SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR; +} + +bool +sss_failover_server_equal(const struct sss_failover_server *a, + const struct sss_failover_server *b) +{ + if (a->name == NULL || b->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: server with no name?\n"); + return false; + } + + if (strcmp(a->name, b->name) != 0) { + return false; + } + + if (a->port != b->port) { + return false; + } + + return true; +} diff --git a/src/providers/failover/failover_server.h b/src/providers/failover/failover_server.h new file mode 100644 index 00000000000..98b9d4ddf73 --- /dev/null +++ b/src/providers/failover/failover_server.h @@ -0,0 +1,189 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_SERVER_H_ +#define _FAILOVER_SERVER_H_ + +#include + +#include "config.h" +#include "util/util.h" + +enum sss_failover_server_state { + /** + * @brief State of the server is unknown. + */ + SSS_FAILOVER_SERVER_STATE_UNKNOWN, + + /** + * @brief The server is responding but there is no active connection. + * + * E.g. ping succeeded, but full connection was not done. + */ + SSS_FAILOVER_SERVER_STATE_REACHABLE, + + /** + * @brief The server is fully functional. + */ + SSS_FAILOVER_SERVER_STATE_WORKING, + + /** + * @brief The server is currently offline. + */ + SSS_FAILOVER_SERVER_STATE_OFFLINE, + + /** + * @brief The server host name can not be resolved. + */ + SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR, +}; + +struct sss_failover_server_address { + /* AF_INET or AF_INET6 */ + int family; + + /* Human readable IP address. */ + char *human; + + /* IP address in binary format. */ + uint8_t *binary; + + /* Length of @binary */ + size_t binary_len; + + /* Generic sockaddr record. */ + struct sockaddr *sockaddr; + + /* @sockaddr length */ + socklen_t sockaddr_len; + + /* Time when the address will be expired and needs to be resolved again. */ + time_t expire; +}; + +struct sss_failover_server { + /* DNS hostname */ + char *name; + + /* Server URI */ + char *uri; + + /* Service port. */ + uint16_t port; + + /* DNS priority */ + int priority; + + /* DNS weight */ + int weight; + + /* Host IP address. */ + struct sss_failover_server_address *addr; + + /* Current state. */ + enum sss_failover_server_state state; + + /* Connection handle if state is CONNECTED. */ + void *connection; +}; + +/** + * @brief Create new failover server record. + * + * @return struct sss_failover_server * + */ +struct sss_failover_server * +sss_failover_server_new(TALLOC_CTX *mem_ctx, + const char *hostname, + const char *uri, + const uint16_t port, + const int priority, + const int weight); + +/** + * @brief Set resolved IP address of the server hostname. + * + * @param srv + * @param family + * @param ttl + * @param addr + * @return errno_t + */ +errno_t +sss_failover_server_set_address(struct sss_failover_server *srv, + int family, + int ttl, + const uint8_t *addr); + +/** + * @brief Clone failover server record. + * + * @param mem_ctx + * @param srv + * @return struct sss_failover_server * + */ +struct sss_failover_server * +sss_failover_server_clone(TALLOC_CTX *mem_ctx, + const struct sss_failover_server *srv); + + +/** + * @brief Return true if server state suggest that the server may work. + */ +bool +sss_failover_server_maybe_working(struct sss_failover_server *srv); + +/** + * @brief Mark server as state unknown + */ +void +sss_failover_server_mark_unknown(struct sss_failover_server *srv); + +/** + * @brief Mark server as reachable. + */ +void +sss_failover_server_mark_reachable(struct sss_failover_server *srv); + +/** + * @brief Mark server as fully functional and working. + */ +void +sss_failover_server_mark_working(struct sss_failover_server *srv); + +/** + * @brief Mark server as offline. + */ +void +sss_failover_server_mark_offline(struct sss_failover_server *srv); + +/** + * @brief Mark server as unable to resolve hostname. + */ +void +sss_failover_server_mark_resolver_error(struct sss_failover_server *srv); + +/** + * @brief Compare two servers and return true if they are equal. + * + * Note: this only compares name and port. + */ +bool +sss_failover_server_equal(const struct sss_failover_server *a, + const struct sss_failover_server *b); + +#endif /* _FAILOVER_SERVER_H_ */ diff --git a/src/providers/failover/failover_server_resolve.c b/src/providers/failover/failover_server_resolve.c new file mode 100644 index 00000000000..2836e09dbf0 --- /dev/null +++ b/src/providers/failover/failover_server_resolve.c @@ -0,0 +1,178 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include + +#include "config.h" +#include "providers/failover/failover_server.h" +#include "resolv/async_resolv.h" +#include "util/util.h" + +static bool +sss_failover_server_resolve_address_changed(struct sss_failover_server *server, + struct resolv_hostent *hostent) +{ + if (server->addr == NULL) { + /* this is the first resolution */ + return true; + } + + if (server->addr->family != hostent->family) { + /* new address has different family */ + return true; + } + + return memcmp(server->addr->binary, hostent->addr_list[0]->ipaddr, + server->addr->binary_len) != 0; +} + +struct sss_failover_server_resolve_state { + struct sss_failover_server *server; + bool changed; +}; + +static void +sss_failover_server_resolve_done(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_server_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resolv_ctx *resolv_ctx, + enum restrict_family family_order, + struct sss_failover_server *server) +{ + struct sss_failover_server_resolve_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; + time_t now; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_server_resolve_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); + return NULL; + } + + state->changed = false; + state->server = talloc_reference(mem_ctx, server); + if (state->server == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + + now = time(NULL); + if (state->server->addr != NULL && state->server->addr->expire > now) { + /* Address is still valid. */ + tevent_req_done(req); + tevent_req_post(req, ev); + return req; + } + + subreq = resolv_gethostbyname_send(state, ev, resolv_ctx, server->name, + family_order, default_host_dbs); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_server_resolve_done, req); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void +sss_failover_server_resolve_done(struct tevent_req *subreq) +{ + struct sss_failover_server_resolve_state *state; + struct resolv_hostent *hostent; + struct tevent_req *req; + int resolv_status; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_server_resolve_state); + + ret = resolv_gethostbyname_recv(subreq, req, &resolv_status, NULL, + &hostent); + talloc_zfree(subreq); + if (ret != EOK) { + if (resolv_status == ARES_EFILE) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to resolve server '%s': %s [local hosts file]\n", + state->server->name, resolv_strerror(resolv_status)); + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to resolve server '%s': %s\n", + state->server->name, resolv_strerror(resolv_status)); + } + + tevent_req_error(req, ret); + return; + } + + if (hostent->addr_list == NULL || hostent->addr_list[0] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "No IP address found\n"); + tevent_req_error(req, ENOENT); + return; + } + + /* check if address has changed */ + state->changed = sss_failover_server_resolve_address_changed(state->server, + hostent); + + ret = sss_failover_server_set_address(state->server, hostent->family, + hostent->addr_list[0]->ttl, + hostent->addr_list[0]->ipaddr); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set server address [%d]: %s\n", + ret, sss_strerror(ret)); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_server_resolve_recv(struct tevent_req *req, + bool *_changed) +{ + struct sss_failover_server_resolve_state *state; + + state = tevent_req_data(req, struct sss_failover_server_resolve_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (_changed != NULL) { + *_changed = state->changed; + } + + return EOK; +} diff --git a/src/providers/failover/failover_server_resolve.h b/src/providers/failover/failover_server_resolve.h new file mode 100644 index 00000000000..54032915aa1 --- /dev/null +++ b/src/providers/failover/failover_server_resolve.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_SERVER_RESOLVE_H_ +#define _FAILOVER_SERVER_RESOLVE_H_ + +#include +#include + +#include "config.h" +#include "resolv/async_resolv.h" +#include "util/util.h" + +/** + * @brief Resolve server hostname into an IP address. + * + * When IP address is resolved, it calls @sss_failover_server_set_address to + * store the address in the @sss_failover_server record. Otherwise it keeps it + * intact. + * + * @param mem_ctx + * @param ev + * @param resolv_ctx + * @param family_order + * @param server + * @return struct tevent_req* + */ +struct tevent_req * +sss_failover_server_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resolv_ctx *resolv_ctx, + enum restrict_family family_order, + struct sss_failover_server *server); + +/** + * @brief Receives the return code. + * + * If EOK, IP address has been stored inside the server record. @_changed is + * true if the IP address of the host has changed, false if it is still the + * same. + * + * @param req + * @param _changed + * @return errno_t + */ +errno_t +sss_failover_server_resolve_recv(struct tevent_req *req, + bool *_changed); + +#endif /* _FAILOVER_SERVER_RESOLVE_H_ */ diff --git a/src/providers/failover/failover_srv.c b/src/providers/failover/failover_srv.c new file mode 100644 index 00000000000..1f72ec574d4 --- /dev/null +++ b/src/providers/failover/failover_srv.c @@ -0,0 +1,178 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_server.h" +#include "resolv/async_resolv.h" +#include "util/util.h" + +struct sss_failover_resolve_srv_state { + struct sss_failover_server **servers; + char *final_discovery_domain; + uint32_t ttl; +}; + +static void sss_failover_resolve_srv_done(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_srv_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + const char *service, + const char *protocol, + const char * const * discovery_domains) +{ + struct sss_failover_resolve_srv_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + const char **domains_dup; + size_t count; + size_t i; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_resolve_srv_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + for (count = 0; discovery_domains[count] != NULL; count++); + domains_dup = talloc_zero_array(state, const char *, count + 1); + for (i = 0; discovery_domains[i] != NULL; i++) { + domains_dup[i] = talloc_strdup(domains_dup, discovery_domains[i]); + if (domains_dup[i] == NULL) { + ret = ENOMEM; + goto done; + } + } + + DEBUG(SSSDBG_TRACE_FUNC, "Discovering servers for %s/%s from DNS\n", + service, protocol); + + subreq = resolv_discover_srv_send(state, ev, fctx->resolver_ctx, service, + protocol, domains_dup); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_resolve_srv_done, req); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void sss_failover_resolve_srv_done(struct tevent_req *subreq) +{ + struct sss_failover_resolve_srv_state *state; + struct ares_srv_reply *reply_list; + struct ares_srv_reply *record; + struct tevent_req *req; + size_t num_servers; + errno_t ret; + int i; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_resolve_srv_state); + + ret = resolv_discover_srv_recv(state, subreq, &reply_list, &state->ttl, + &state->final_discovery_domain); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Got answer. Processing...\n"); + + /* sort and store the answer */ + ret = resolv_sort_srv_reply(&reply_list); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Could not sort the answers from DNS " + "[%d]: %s\n", ret, strerror(ret)); + goto done; + } + + num_servers = 0; + for (record = reply_list; record != NULL; record = record->next) { + num_servers++; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Got %zu servers\n", num_servers); + + state->servers = talloc_zero_array(state, struct sss_failover_server *, + num_servers + 1); + if (state->servers == NULL) { + ret = ENOMEM; + goto done; + } + + for (record = reply_list, i = 0; + record != NULL; + record = record->next, i++) { + // TODO handle uri + state->servers[i] = sss_failover_server_new( + state->servers, record->host, "ldap://master.ldap.test", record->port, record->priority, + record->weight); + if (state->servers[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + } + } + + talloc_zfree(reply_list); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_srv_resolve_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + uint32_t *_ttl, + struct sss_failover_server ***_servers) +{ + struct sss_failover_resolve_srv_state *state; + + state = tevent_req_data(req, struct sss_failover_resolve_srv_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *_servers = talloc_steal(mem_ctx, state->servers); + + return EOK; +} diff --git a/src/providers/failover/failover_srv.h b/src/providers/failover/failover_srv.h new file mode 100644 index 00000000000..3b944a37aaa --- /dev/null +++ b/src/providers/failover/failover_srv.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_SRV_H_ +#define _FAILOVER_SRV_H_ + +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_server.h" +#include "util/util.h" + +/** + * @brief Resolve DNS SRV record using selected discovery domains. + * + * If the first discovery domain yields no servers, we proceed with the next + * domain. + * + * @param mem_ctx + * @param ev + * @param fctx + * @param service + * @param protocol + * @param discovery_domains + * @return struct tevent_req* + */ +struct tevent_req * +sss_failover_srv_resolve_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + const char *service, + const char *protocol, + const char * const * discovery_domains); + +/** + * @brief Get TTL and discovered servers. + * + * @param mem_ctx + * @param req + * @param _ttl + * @param _servers + * @return errno_t + */ +errno_t +sss_failover_srv_resolve_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + uint32_t *_ttl, + struct sss_failover_server ***_servers); + +#endif /* _FAILOVER_SRV_H_ */ diff --git a/src/providers/failover/failover_transaction.c b/src/providers/failover/failover_transaction.c new file mode 100644 index 00000000000..e5f4a3bd740 --- /dev/null +++ b/src/providers/failover/failover_transaction.c @@ -0,0 +1,467 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include + +#include "config.h" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/failover_vtable_op.h" +#include "util/util.h" + +errno_t +sss_failover_transaction_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct tevent_req *caller_req, + tevent_req_fn connected_callback) +{ + return sss_failover_transaction_ex_send(mem_ctx, ev, fctx, caller_req, + connected_callback, true, true, true, + SSS_FAILOVER_TRANSACTION_TLS_DEFAULT); +} + +struct sss_failover_transaction_connected_state { + struct sss_failover_ctx *fctx; +}; + +struct sss_failover_transaction_state { + struct tevent_context *ev; + struct sss_failover_ctx *fctx; + + bool reuse_connection; + bool authenticate_connection; + bool read_rootdse; + enum sss_failover_transaction_tls force_tls; + + /* Top level tevent request. Finished when this transaction is done. */ + struct tevent_req *caller_req; + void *caller_data; + size_t caller_data_size; + const char *caller_data_type; + + /* Connection request. Finished when we have a connection and + * connected_callback is fired. */ + struct tevent_req *connected_req; + tevent_req_fn connected_callback; + + /* Single transaction attempt. If successful, the main transaction request + * is finished. Otherwise, we try next server. */ + struct tevent_req *attempt_req; + + /* How many times was this transaction restarted. */ + unsigned int attempts; + + /* Connection information. */ + struct sss_failover_server *current_server; + time_t kinit_expiration_time; + void *connection; +}; + +static errno_t +sss_failover_transaction_restart(struct tevent_req *req); + +static errno_t +sss_failover_transaction_next(struct tevent_req *req); + +static errno_t +sss_failover_transaction_kinit(struct tevent_req *req); + +static void +sss_failover_transaction_kinit_done(struct tevent_req *subreq); + +static errno_t +sss_failover_transaction_connect(struct tevent_req *req); + +static void +sss_failover_transaction_connect_done(struct tevent_req *subreq); + +static void +sss_failover_transaction_attempt_done(struct tevent_req *attempt_req); + +static void +sss_failover_transaction_done(struct tevent_req *subreq); + +errno_t +sss_failover_transaction_ex_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct tevent_req *caller_req, + tevent_req_fn connected_callback, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls) +{ + struct sss_failover_transaction_state *state; + struct tevent_req *req; + errno_t ret; + + DEBUG(SSSDBG_TRACE_FUNC, + "Creating new failover transaction for service %s\n", fctx->name); + + req = tevent_req_create(mem_ctx, &state, struct sss_failover_transaction_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return ENOMEM; + } + + state->ev = ev; + state->fctx = fctx; + state->reuse_connection = reuse_connection; + state->authenticate_connection = authenticate_connection; + state->read_rootdse = read_rootdse; + + state->caller_req = caller_req; + state->caller_data = _tevent_req_data(caller_req); + state->caller_data_size = talloc_get_size(state->caller_data); + state->caller_data_type = talloc_get_name(state->caller_data); + state->connected_callback = connected_callback; + state->attempts = 0; + + tevent_req_set_callback(req, sss_failover_transaction_done, caller_req); + + ret = sss_failover_transaction_restart(req); + if (ret != EOK) { + /* We cannot get any working server. Just cancel this request. */ + talloc_free(req); + } + + return ret; +} + +static errno_t +sss_failover_transaction_restart(struct tevent_req *req) +{ + struct sss_failover_transaction_connected_state *connected_state; + struct sss_failover_transaction_state *state; + void *attempt_state; + errno_t ret; + + state = tevent_req_data(req, struct sss_failover_transaction_state); + state->attempts++; + + DEBUG(SSSDBG_TRACE_FUNC, "Transaction attempt %u\n", state->attempts); + + /* This request is what fires up the connected_callback - we have active + * connection to a server and the user can start querying it. */ + state->connected_req = tevent_req_create(state, + &connected_state, struct sss_failover_transaction_connected_state); + if (state->connected_req == NULL) { + ret = ENOMEM; + goto done; + } + connected_state->fctx = state->fctx; + + /* Create attempt req, this is used by the user as a replacement for + * caller_req. The user will seamlessly call + * tevent_req_done/error(attempt_req). */ + state->attempt_req = __tevent_req_create(state, &attempt_state, + state->caller_data_size, state->caller_data_type, + __func__, __location__); + if (state->attempt_req == NULL) { + ret = ENOMEM; + goto done; + } + + /* Switch the attempt_req state to caller_req state so it is used seamlessly + * by the user. This is quite a hack and the attempt_state must stay + * attached to attempt_req otherwise tevent_req_destructor will cause double + * free. We also cannot free req nor attempt_req to make sure all data is + * available to the caller_req recv function. This is not nice, but OK as + * there should not be many retry attempts and the memory is freed when + * caller_req is freed. */ + memcpy(attempt_state, state->caller_data, state->caller_data_size); + + tevent_req_set_callback(state->attempt_req, + sss_failover_transaction_attempt_done, req); + + tevent_req_set_callback(state->connected_req, state->connected_callback, + state->attempt_req); + + ret = sss_failover_transaction_next(req); + +done: + if (ret != EOK && state->attempts > 1) { + /* The failover transaction was restarted due to server error but we + * cannot retrieve any new server. Terminate the main request since we + * are already in an async loop. This in turn will finish the + * caller_req. */ + tevent_req_error(req, ret); + } + + return ret; +} + +static errno_t +sss_failover_transaction_next(struct tevent_req *req) +{ + struct sss_failover_transaction_state *state; + errno_t ret; + + state = tevent_req_data(req, struct sss_failover_transaction_state); + + /* Unlink current server to decrease refcount. */ + if (state->current_server != NULL) { + talloc_unlink(state, state->current_server); + state->current_server = NULL; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Trying to find a working server\n"); + if (state->fctx->kinit_ctx != NULL && state->authenticate_connection) { + ret = sss_failover_transaction_kinit(req); + } else { + ret = sss_failover_transaction_connect(req); + } + + return ret; +} + +static errno_t +sss_failover_transaction_kinit(struct tevent_req *req) +{ + struct sss_failover_transaction_state *state; + struct tevent_req *subreq; + + state = tevent_req_data(req, struct sss_failover_transaction_state); + + DEBUG(SSSDBG_TRACE_FUNC, "Attempting to kinit\n"); + + subreq = sss_failover_vtable_op_kinit_send(state, state->ev, + state->fctx->kinit_ctx); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, sss_failover_transaction_kinit_done, req); + return EOK; +} + +static void +sss_failover_transaction_kinit_done(struct tevent_req *subreq) +{ + struct sss_failover_transaction_state *state; + struct sss_failover_server *server; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_transaction_state); + + ret = sss_failover_vtable_op_kinit_recv(state, subreq, &server, + &state->kinit_expiration_time); + talloc_zfree(subreq); + if (ret == ERR_NO_MORE_SERVERS) { + DEBUG(SSSDBG_OP_FAILURE, + "There are no more servers to try, cancelling operation\n"); + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Error while attempting to kinit, cancelling operation [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "kinit against KDC %s was successful\n", + server->name); + + /* We do not need this server anymore. */ + talloc_unlink(state, server); + + ret = sss_failover_transaction_connect(req); + +done: + if (ret != EOK) { + /* We cannot get TGT. Terminate main request. */ + tevent_req_error(req, ret); + return; + } +} + +static errno_t +sss_failover_transaction_connect(struct tevent_req *req) +{ + struct sss_failover_transaction_state *state; + struct tevent_req *subreq; + + state = tevent_req_data(req, struct sss_failover_transaction_state); + + DEBUG(SSSDBG_TRACE_FUNC, "Trying to establish connection\n"); + + subreq = sss_failover_vtable_op_connect_send(state, state->ev, state->fctx, + state->reuse_connection, + state->authenticate_connection, + state->read_rootdse, + state->force_tls, + state->kinit_expiration_time); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, sss_failover_transaction_connect_done, req); + return EOK; +} + +static void +sss_failover_transaction_connect_done(struct tevent_req *subreq) +{ + struct sss_failover_transaction_state *state; + struct tevent_req *req; + void *connection; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_transaction_state); + + /* If successful, state->current_server is additional talloc_reference + * to an active, connected server. */ + ret = sss_failover_vtable_op_connect_recv(state, subreq, + &state->current_server, + &connection); + talloc_zfree(subreq); + if (ret == ERR_NO_MORE_SERVERS) { + DEBUG(SSSDBG_OP_FAILURE, + "There are no more servers to try, cancelling operation\n"); + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Error while attempting to connect, cancelling operation [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Connected to %s, connection %p\n", + state->current_server->name, connection); + + sss_failover_set_active_server(state->fctx, state->current_server); + sss_failover_set_connection(state->fctx, connection); + + /* We are connected. Now continue with connected_callback. */ + tevent_req_done(state->connected_req); + +done: + if (ret != EOK) { + /* We cannot establish connection. Terminate main request. */ + tevent_req_error(req, ret); + return; + } +} + +/* Finish the main failover transaction request or try next server. */ +static void sss_failover_transaction_attempt_done(struct tevent_req *attempt_req) +{ + struct sss_failover_transaction_state *state; + struct tevent_req *req; + void *attempt_state; + enum tevent_req_state treq_state; + uint64_t treq_error; + + req = tevent_req_callback_data(attempt_req, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_transaction_state); + attempt_state = _tevent_req_data(attempt_req); + + /* Copy the transaction_req state back to the caller_req state. We can not + * free the transaction state as there is no way to move possible new data + * to the caller state context. If the transaction is restarted we will + * allocate new transaction state, keeping this one hanging. It is OK as + * there is only finite number of possible restarts and eventually all the + * memory will be freed when the caller_req state is freed. */ + memcpy(state->caller_data, attempt_state, state->caller_data_size); + + if (tevent_req_is_error(attempt_req, &treq_state, &treq_error)) { + switch (treq_state) { + case TEVENT_REQ_USER_ERROR: + /* Try next server. */ + if (treq_error == ERR_SERVER_FAILURE) { + sss_failover_server_mark_offline(state->current_server); + sss_failover_transaction_restart(req); + return; + } + + tevent_req_error(req, treq_error); + return; + case TEVENT_REQ_TIMED_OUT: + tevent_req_error(req, ETIMEDOUT); + return; + case TEVENT_REQ_NO_MEMORY: + tevent_req_oom(req); + return; + default: + tevent_req_error(req, ERR_INTERNAL); + return; + } + } + + tevent_req_done(req); +} + +/* The failover transaction is done. Finish the caller request. */ +static void sss_failover_transaction_done(struct tevent_req *req) +{ + struct tevent_req *caller_req; + enum tevent_req_state req_state; + uint64_t req_error; + + caller_req = tevent_req_callback_data(req, struct tevent_req); + + /* Terminate the caller req. */ + if (tevent_req_is_error(req, &req_state, &req_error)) { + switch (req_state) { + case TEVENT_REQ_USER_ERROR: + DEBUG(SSSDBG_TRACE_FUNC, + "Failover transaction end up with error " + "[%" PRIu64 "]: %s\n", req_error, sss_strerror(req_error)); + tevent_req_error(caller_req, req_error); + return; + case TEVENT_REQ_TIMED_OUT: + DEBUG(SSSDBG_TRACE_FUNC, "Failover transaction timed out\n"); + tevent_req_error(caller_req, ETIMEDOUT); + return; + case TEVENT_REQ_NO_MEMORY: + tevent_req_oom(caller_req); + return; + default: + DEBUG(SSSDBG_TRACE_FUNC, "Bug: Unexpected state %d\n", req_state); + tevent_req_error(caller_req, ERR_INTERNAL); + return; + } + } + + DEBUG(SSSDBG_TRACE_FUNC, "Failover transaction was successful\n"); + tevent_req_done(caller_req); +} + +/* Return connection. This is only called if we have a successful connection. */ +void * +_sss_failover_transaction_connected_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req) +{ + struct sss_failover_transaction_connected_state *state; + void *connection; + + state = tevent_req_data(req, + struct sss_failover_transaction_connected_state); + + connection = sss_failover_get_connection(mem_ctx, state->fctx); + if (connection == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: connection should not be NULL!\n"); + } + + return connection; +} diff --git a/src/providers/failover/failover_transaction.h b/src/providers/failover/failover_transaction.h new file mode 100644 index 00000000000..7c1f1227a2b --- /dev/null +++ b/src/providers/failover/failover_transaction.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +/** + * The failover transaction code is responsible for choosing and connecting to a + * server and retrying the whole operation if the server stops working in the + * middle of the request. + * + * The operation is wrapped by @sss_failover_transaction_send and it should make + * sure to fetch all required data from the server before writing them to the + * sysdb. If the operation fails due to the server failure, the operation tevent + * request must fail with ERR_SERVER_FAILURE to indicate the failure to the + * failover transaction code. In this case, the failover mechanism marks the + * server as offline, picks the next available server and restarts the whole + * operation. Neither the caller nor the operation has to deal with any failover + * mechanics. + * + * The result of the operation can be received by + * @sss_failover_transaction_recv. + */ + +#ifndef _FAILOVER_TRANSACTION_H_ +#define _FAILOVER_TRANSACTION_H_ + +#include +#include + +#include "config.h" +#include "resolv/async_resolv.h" +#include "util/util.h" + +struct sss_failover_ctx; + +enum sss_failover_transaction_tls { + SSS_FAILOVER_TRANSACTION_TLS_DEFAULT, + SSS_FAILOVER_TRANSACTION_TLS_ON, + SSS_FAILOVER_TRANSACTION_TLS_OFF +}; + +errno_t +sss_failover_transaction_ex_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct tevent_req *caller_req, + tevent_req_fn connected_callback, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls); + +errno_t +sss_failover_transaction_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct tevent_req *caller_req, + tevent_req_fn connected_callback); + +/** + * @brief Submit a failover transaction. + * + * The failover code will pick a working server and submit a working connection + * to the underlying @req_send tevent request, passing @input_data along. + * + * If the receive @req_recv function returns ERR_SERVER_FAILURE, the transaction + * is repeated with another server as long as there is a server available. The + * transaction is cancelled if there are no more servers to try. + * + * The callback and data types are checked during compilation. + */ + +void * +_sss_failover_transaction_connected_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req); + +#define sss_failover_transaction_connected_recv(mem_ctx, req, type) \ + talloc_get_type_abort(_sss_failover_transaction_connected_recv((mem_ctx), (req)), type) + +#endif /* _FAILOVER_TRANSACTION_H_ */ diff --git a/src/providers/failover/failover_vtable.c b/src/providers/failover/failover_vtable.c new file mode 100644 index 00000000000..52c5067cb1c --- /dev/null +++ b/src/providers/failover/failover_vtable.c @@ -0,0 +1,46 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include + +#include "config.h" +#include "providers/failover/failover_vtable.h" +#include "providers/failover/failover.h" +#include "util/util.h" + +void +sss_failover_vtable_set_connect(struct sss_failover_ctx *fctx, + sss_failover_vtable_connect_send_t send_fn, + sss_failover_vtable_connect_recv_t recv_fn, + void *data) +{ + fctx->vtable->connect.send = send_fn; + fctx->vtable->connect.recv = recv_fn; + fctx->vtable->connect.data = data; +} + +void +sss_failover_vtable_set_kinit(struct sss_failover_ctx *fctx, + sss_failover_vtable_kinit_send_t send_fn, + sss_failover_vtable_kinit_recv_t recv_fn, + void *data) +{ + fctx->vtable->kinit.send = send_fn; + fctx->vtable->kinit.recv = recv_fn; + fctx->vtable->kinit.data = data; +} diff --git a/src/providers/failover/failover_vtable.h b/src/providers/failover/failover_vtable.h new file mode 100644 index 00000000000..cd7733e5be0 --- /dev/null +++ b/src/providers/failover/failover_vtable.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_VTABLE_H_ +#define _FAILOVER_VTABLE_H_ + +#include +#include + +#include "config.h" +#include "resolv/async_resolv.h" +#include "providers/failover/failover_server.h" +#include "util/util.h" + +struct sss_failover_ctx; +enum sss_failover_transaction_tls; + +struct sss_failover_vtable_kinit_output_data { + time_t expiration_time; +}; + +typedef struct tevent_req * +(*sss_failover_vtable_kinit_send_t)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + void *pvt); + +typedef errno_t +(*sss_failover_vtable_kinit_recv_t)(TALLOC_CTX *mem_ctx, + struct tevent_req *, + time_t *_expiration_time); + +struct sss_failover_vtable_kinit { + sss_failover_vtable_kinit_send_t send; + sss_failover_vtable_kinit_recv_t recv; + void *data; +}; + +typedef struct tevent_req * +(*sss_failover_vtable_connect_send_t)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls, + time_t kinit_expiration_time, + void *pvt); + +typedef errno_t +(*sss_failover_vtable_connect_recv_t)(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + void **_connection); + + +struct sss_failover_vtable_connect { + sss_failover_vtable_connect_send_t send; + sss_failover_vtable_connect_recv_t recv; + void *data; +}; + +struct sss_failover_vtable { + struct sss_failover_vtable_kinit kinit; + struct sss_failover_vtable_connect connect; +}; + +void +sss_failover_vtable_set_connect(struct sss_failover_ctx *fctx, + sss_failover_vtable_connect_send_t send_fn, + sss_failover_vtable_connect_recv_t recv_fn, + void *data); + +void +sss_failover_vtable_set_kinit(struct sss_failover_ctx *fctx, + sss_failover_vtable_kinit_send_t send_fn, + sss_failover_vtable_kinit_recv_t recv_fn, + void *data); + +#endif /* _FAILOVER_VTABLE_H_ */ diff --git a/src/providers/failover/failover_vtable_op.c b/src/providers/failover/failover_vtable_op.c new file mode 100644 index 00000000000..735c9a67678 --- /dev/null +++ b/src/providers/failover/failover_vtable_op.c @@ -0,0 +1,596 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/failover_server.h" +#include "providers/failover/failover_server_resolve.h" +#include "providers/failover/failover_refresh_candidates.h" +#include "providers/failover/failover_vtable_op.h" +#include "util/util.h" + +static struct sss_failover_server * +sss_failover_vtable_op_pick_server(TALLOC_CTX *mem_ctx, + struct sss_failover_ctx *fctx) +{ + struct sss_failover_server *server; + size_t index; + size_t start; + size_t count; + + /* Total count of elements. */ + count = talloc_array_length(fctx->candidates->servers) - 1; + + start = sss_rand() % count; + for (size_t i = 0; i < count; i++) { + index = (start + i) % count; + + server = fctx->candidates->servers[index]; + + /* This slot is empty. Continue. */ + if (server == NULL) { + continue; + } + + if (sss_failover_server_maybe_working(server)) { + return talloc_reference(mem_ctx, server); + } + } + + /* We iterated over all candidates and none is working. */ + return NULL; +} + +enum sss_failover_vtable_op { + /* Perform kinit against given KDC. */ + SSS_FAILOVER_VTABLE_OP_KINIT, + + /* Connect to the server. */ + SSS_FAILOVER_VTABLE_OP_CONNECT, +}; + +/** + * @brief Issue vtable operation against specific server. + * + * The operation should check the @server state and shortcut if possible (for + * example if the server is already connected and working). @addr_changed is + * true if the server hostname resolved to different address then what is stored + * (it was previously unresolved, or the DNS record has changed). The operation + * should take this information into consideration (e.g. reconnect to the server + * with new address). + * + * The server state can be unknown, reachable or working. The server address + * is guaranteed to be resolved. + */ +typedef struct tevent_req * +(*sss_failover_vtable_op_send_t)(TALLOC_CTX *mem_ctx, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed); + +/** + * @brief Receive operation result and point to its private data. + * + * The private data is then stored on the server structure by caller. + */ +typedef errno_t +(*sss_failover_vtable_op_recv_t)(TALLOC_CTX *mem_ctx, + struct tevent_req *, + void **_op_private_data); + +struct sss_failover_vtable_op_args { + union { + struct { + bool reuse_connection; + bool authenticate_connection; + bool read_rootdse; + enum sss_failover_transaction_tls force_tls; + time_t expiration_time; + } connect; + } input; + + union { + struct { + time_t expiration_time; + } kinit; + + struct { + void *connection; + } connect; + } output; +}; + +struct sss_failover_vtable_op_state { + struct tevent_context *ev; + struct sss_failover_ctx *fctx; + enum sss_failover_vtable_op operation; + struct sss_failover_vtable_op_args *args; + + struct sss_failover_server *current_server; + bool candidates_refreshed; +}; + +static void +sss_failover_vtable_op_trigger(struct tevent_req *req, + void *pvt); + +static errno_t +sss_failover_vtable_op_server_next(struct tevent_req *req); + +static errno_t +sss_failover_vtable_op_refresh_candidates(struct tevent_req *req); + +static void +sss_failover_vtable_op_refresh_candidates_done(struct tevent_req *subreq); + +static void +sss_failover_vtable_op_server_resolved(struct tevent_req *subreq); + +static struct tevent_req * +sss_failover_vtable_op_subreq_send(struct sss_failover_vtable_op_state *state, + bool addr_changed); + +static errno_t +sss_failover_vtable_op_subreq_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *subreq); + +static void +sss_failover_vtable_op_done(struct tevent_req *subreq); + +static struct tevent_req * +sss_failover_vtable_op_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + enum sss_failover_vtable_op operation, + struct sss_failover_vtable_op_args *args) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_req *req; + errno_t ret; + bool bret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_vtable_op_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + + /* Free args to simplify logic in the caller. */ + talloc_free(args); + return NULL; + } + + state->ev = ev; + state->fctx = fctx; + state->operation = operation; + state->args = talloc_steal(state, args); + + switch (state->operation) { + case SSS_FAILOVER_VTABLE_OP_KINIT: + case SSS_FAILOVER_VTABLE_OP_CONNECT: + /* Correct operation. */ + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid operation: [%d]\n", state->operation); + ret = EINVAL; + goto done; + } + + /* Queuing the requests ensures that there is only one request that does + * actual server selection and resolution. All subsequent requests will just + * shortcut and pick the last selected server, if it is still working. */ + bret = tevent_queue_add(fctx->vtable_op_queue, fctx->ev, req, + sss_failover_vtable_op_trigger, NULL); + if (!bret) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to add request to tevent queue\n"); + ret = ENOMEM; + goto done; + } + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void +sss_failover_vtable_op_trigger(struct tevent_req *req, + void *pvt) +{ + errno_t ret; + + ret = sss_failover_vtable_op_server_next(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } +} + +static errno_t +sss_failover_vtable_op_server_next(struct tevent_req *req) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_req *subreq; + + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + + if (state->current_server == NULL) { + /* Select first server to try.*/ + if (state->fctx->active_server != NULL + && sss_failover_server_maybe_working(state->fctx->active_server)) { + /* Try active server first. */ + state->current_server = state->fctx->active_server; + DEBUG(SSSDBG_TRACE_FUNC, "Trying current active server: %s\n", + state->current_server->name); + } else { + /* Pick a first server from candidates. */ + state->current_server = sss_failover_vtable_op_pick_server(state, state->fctx); + if (state->current_server == NULL) { + /* No candidates are available, schedule a refresh. */ + return sss_failover_vtable_op_refresh_candidates(req); + } + + DEBUG(SSSDBG_TRACE_FUNC, "Trying candidate server: %s\n", + state->current_server->name); + } + } else { + /* We already tried this server and it is not working. Submit an out of + * band request of server candidates and try the next available + * server. */ + + DEBUG(SSSDBG_TRACE_FUNC, "Server %s does not work\n", + state->current_server->name); + + DEBUG(SSSDBG_TRACE_FUNC, "Issuing out of band refresh of candidates\n"); + + if (sss_failover_refresh_candidates_oob_can_run(state->fctx)) { + sss_failover_refresh_candidates_oob_send(state->fctx, state->ev, + state->fctx); + } + + state->current_server = sss_failover_vtable_op_pick_server(state, state->fctx); + if (state->current_server == NULL) { + /* No candidates are available. Wait for new ones. */ + return sss_failover_vtable_op_refresh_candidates(req); + } + + DEBUG(SSSDBG_TRACE_FUNC, "Trying next candidate server: %s\n", + state->current_server->name); + } + + /* TODO shortcut if already connected */ + + /* First resolve the hostname. */ + DEBUG(SSSDBG_TRACE_FUNC, "Resolving hostname of %s\n", + state->current_server->name); + + subreq = sss_failover_server_resolve_send(state, state->ev, + state->fctx->resolver_ctx, + state->fctx->family_order, + state->current_server); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, sss_failover_vtable_op_server_resolved, + req); + + return EOK; +} + +static errno_t +sss_failover_vtable_op_refresh_candidates(struct tevent_req *req) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_queue *queue; + struct tevent_req *subreq; + + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + queue = state->fctx->candidates->notify_queue; + + if (state->candidates_refreshed) { + /* We already refreshed the candidates. */ + DEBUG(SSSDBG_TRACE_FUNC, "Refresh did not find any working server\n"); + return ERR_NO_MORE_SERVERS; + } + + DEBUG(SSSDBG_TRACE_FUNC, + "No more candidate servers are available, wait for a refresh\n"); + + state->candidates_refreshed = true; + + /* Issue refresh request if there is none. */ + if (sss_failover_refresh_candidates_oob_can_run(state->fctx)) { + sss_failover_refresh_candidates_oob_send(state->fctx, state->ev, + state->fctx); + } + + /* Register for notification. */ + subreq = tevent_queue_wait_send(state, state->ev, queue); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, + sss_failover_vtable_op_refresh_candidates_done, + req); + + return EOK; +} + +static void +sss_failover_vtable_op_refresh_candidates_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + + ret = sss_failover_vtable_op_server_next(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } +} + +static void +sss_failover_vtable_op_server_resolved(struct tevent_req *subreq) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_req *req; + bool addr_changed; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + + ret = sss_failover_server_resolve_recv(subreq, &addr_changed); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Unable to resolve server hostname %s [%d]: %s\n", + state->current_server->name, ret, sss_strerror(ret)); + sss_failover_server_mark_resolver_error(state->current_server); + ret = sss_failover_vtable_op_server_next(req); + goto done; + } + + /* Trigger the operation. */ + DEBUG(SSSDBG_TRACE_FUNC, "Name resolved, starting vtable operation\n"); + + subreq = sss_failover_vtable_op_subreq_send(state, addr_changed); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_vtable_op_done, req); + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } +} + +static struct tevent_req * +sss_failover_vtable_op_subreq_send(struct sss_failover_vtable_op_state *state, + bool addr_changed) +{ + switch (state->operation) { + case SSS_FAILOVER_VTABLE_OP_KINIT: + return state->fctx->vtable->kinit.send( + state, state->ev, state->fctx, state->current_server, addr_changed, + state->fctx->vtable->kinit.data); + case SSS_FAILOVER_VTABLE_OP_CONNECT: + return state->fctx->vtable->connect.send( + state, state->ev, state->fctx, state->current_server, addr_changed, + state->args->input.connect.reuse_connection, + state->args->input.connect.authenticate_connection, + state->args->input.connect.read_rootdse, + state->args->input.connect.force_tls, + state->args->input.connect.expiration_time, + state->fctx->vtable->connect.data); + } + + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: Unknown operation\n"); + return NULL; +} + +static errno_t +sss_failover_vtable_op_subreq_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *subreq) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_req *req; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + + switch (state->operation) { + case SSS_FAILOVER_VTABLE_OP_KINIT: + return state->fctx->vtable->kinit.recv(state, subreq, + &state->args->output.kinit.expiration_time); + case SSS_FAILOVER_VTABLE_OP_CONNECT: + return state->fctx->vtable->connect.recv(state, subreq, + &state->args->output.connect.connection); + } + + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: Unknown operation\n"); + return ENOTSUP; +} + +static void sss_failover_vtable_op_done(struct tevent_req *subreq) +{ + struct sss_failover_vtable_op_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + + ret = sss_failover_vtable_op_subreq_recv(state, subreq); + talloc_zfree(subreq); + + switch (ret) { + case EOK: + /* The operation was successful. */ + sss_failover_server_mark_working(state->current_server); + + /* Remember this server. */ + talloc_unlink(state->fctx, state->fctx->active_server); + state->fctx->active_server = talloc_reference(state->fctx, + state->current_server); + break; + case ENOMEM: + /* There is no reason to retry if we our out of memory. */ + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + goto done; + default: + /* Server is not working. */ + sss_failover_server_mark_offline(state->current_server); + ret = sss_failover_vtable_op_server_next(req); + if (ret == EOK) { + return; + } + } + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +static errno_t +sss_failover_vtable_op_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server, + struct sss_failover_vtable_op_args **_args) +{ + struct sss_failover_vtable_op_state *state = NULL; + state = tevent_req_data(req, struct sss_failover_vtable_op_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (_server != NULL) { + *_server = talloc_reference(mem_ctx, state->current_server); + } + + if (_args != NULL) { + *_args = talloc_steal(mem_ctx, state->args); + } + + return EOK; +} + +struct tevent_req * +sss_failover_vtable_op_kinit_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx) +{ + struct sss_failover_vtable_op_args *args; + + args = talloc_zero(NULL, struct sss_failover_vtable_op_args); + if (args == NULL) { + return NULL; + } + + return sss_failover_vtable_op_send(mem_ctx, ev, fctx, + SSS_FAILOVER_VTABLE_OP_KINIT, args); +} + +errno_t +sss_failover_vtable_op_kinit_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server, + time_t *_expiration_time) +{ + struct sss_failover_vtable_op_args *args; + errno_t ret; + + ret = sss_failover_vtable_op_recv(mem_ctx, req, _server, &args); + if (ret != EOK) { + return ret; + } + + if (_expiration_time != NULL) { + *_expiration_time = args->output.kinit.expiration_time; + } + + talloc_free(args); + return EOK; +} + +struct tevent_req * +sss_failover_vtable_op_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls, + time_t kinit_expiration_time) +{ + struct sss_failover_vtable_op_args *args; + + args = talloc_zero(NULL, struct sss_failover_vtable_op_args); + if (args == NULL) { + return NULL; + } + + args->input.connect.reuse_connection = reuse_connection; + args->input.connect.authenticate_connection = authenticate_connection; + args->input.connect.read_rootdse = read_rootdse; + args->input.connect.force_tls = force_tls; + args->input.connect.expiration_time = kinit_expiration_time; + return sss_failover_vtable_op_send(mem_ctx, ev, fctx, + SSS_FAILOVER_VTABLE_OP_CONNECT, args); +} + +errno_t +sss_failover_vtable_op_connect_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server, + void **_connection) +{ + struct sss_failover_vtable_op_args *args; + errno_t ret; + + ret = sss_failover_vtable_op_recv(mem_ctx, req, _server, &args); + if (ret != EOK) { + return ret; + } + + if (_connection != NULL) { + *_connection = talloc_steal(mem_ctx, args->output.connect.connection); + } + + talloc_free(args); + return EOK; +} diff --git a/src/providers/failover/failover_vtable_op.h b/src/providers/failover/failover_vtable_op.h new file mode 100644 index 00000000000..d244e62a724 --- /dev/null +++ b/src/providers/failover/failover_vtable_op.h @@ -0,0 +1,131 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_VTABLE_OP_H_ +#define _FAILOVER_VTABLE_OP_H_ + +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_server.h" +#include "util/util.h" + +/** + * @defgroup Failover vtable operations. + * + * The purpose of sss_failover_vtable_op_* requests is to find a working server + * on which the operation succeeds. + * + * - If there is already working and active server, use it. + * - Otherwise find first available server, resolve its hostname and use it. + * - If the operation succeeds, mark the server as working and store operation + * data. + * - If the operation fails, mark the server as not working and try next server. + * + * Note that this request does not decide if the operation should be started or + * not (e.g. if the server is already connected or not). To simplify the logic, + * this is the responsibility of the operation it self (e.g. check if the server + * is already connected in the @send_fn and then shortcut, otherwise try to + * establish connection). + * + * The requests are serialized in @fctx->vtable_op_queue to ensure that we + * always talk to a single server at the same time. + * + * @{ + */ + +/** + * @brief Select a KDC and attempt to kinit with the host credentials. + * + * @param mem_ctx + * @param ev + * @param fctx + * @return struct tevent_req * + */ +struct tevent_req * +sss_failover_vtable_op_kinit_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx); + +/** + * @brief Receive result of the operation. + * + * If @_server is not NULL and EOK is returned, it contains the server that was + * successfully used to finish the operation. The server reference count is + * increased and linked to @mem_ctx. + * + * @param mem_ctx + * @param req + * @param _server + * @param _expiration_time Host TGT expiration time. + * @return errno_t + */ +errno_t +sss_failover_vtable_op_kinit_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server, + time_t *_expiration_time); + +/** + * @brief Select a server and attempt to establish a working connection. + * + * @param mem_ctx + * @param ev + * @param fctx + * @param reuse_connection + * @param authenticate_connection + * @param read_rootdse + * @param force_tls + * @param kinit_expiration_time + * @return struct tevent_req * + */ +struct tevent_req * +sss_failover_vtable_op_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls, + time_t kinit_expiration_time); + +/** + * @brief Receive result of the operation. + * + * If @_server is not NULL and EOK is returned, it contains the server that was + * successfully used to finish the operation. The server reference count is + * increased and linked to @mem_ctx. + * + * @param mem_ctx + * @param req + * @param _server + * @param _connection Established connection data. + * @return errno_t + */ +errno_t +sss_failover_vtable_op_connect_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct sss_failover_server **_server, + void **_connection); + +/** + * @} + */ + +#endif /* _FAILOVER_VTABLE_OP_H_ */ diff --git a/src/providers/failover/ldap/failover_ldap.h b/src/providers/failover/ldap/failover_ldap.h new file mode 100644 index 00000000000..ba90f6eeac8 --- /dev/null +++ b/src/providers/failover/ldap/failover_ldap.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _FAILOVER_LDAP_H_ +#define _FAILOVER_LDAP_H_ + +#include +#include + +#include "config.h" +#include "resolv/async_resolv.h" +#include "providers/failover/failover_server.h" +#include "util/util.h" + +struct sss_failover_ldap_connection { + struct sdap_server_opts *srv_opts; + struct sdap_handle *sh; + char *uri; +}; + +struct tevent_req * +sss_failover_ldap_kinit_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + void *pvt); + +errno_t +sss_failover_ldap_kinit_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + time_t *_expiration_time); + +struct tevent_req * +sss_failover_ldap_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls, + time_t kinit_expiration_time, + void *pvt); + +errno_t +sss_failover_ldap_connect_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + void **_connection); + +#endif /* _FAILOVER_LDAP_H_ */ diff --git a/src/providers/failover/ldap/failover_ldap_connect.c b/src/providers/failover/ldap/failover_ldap_connect.c new file mode 100644 index 00000000000..6799c68b3ad --- /dev/null +++ b/src/providers/failover/ldap/failover_ldap_connect.c @@ -0,0 +1,158 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/failover_server.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/ldap/sdap_async_private.h" +#include "util/util.h" + +struct sss_failover_ldap_connect_state { + struct sss_failover_ldap_connection *connection; +}; + +static void sss_failover_ldap_connect_done(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_ldap_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + bool reuse_connection, + bool authenticate_connection, + bool read_rootdse, + enum sss_failover_transaction_tls force_tls, + time_t kinit_expiration_time, + void *pvt) +{ + struct sss_failover_ldap_connect_state *state; + struct sdap_options *opts; + struct tevent_req *subreq; + struct tevent_req *req; + enum connect_tls tls; + errno_t ret; + + /* TODO handle active connection */ + + opts = talloc_get_type_abort(pvt, struct sdap_options); + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_ldap_connect_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->connection = talloc_zero(state, struct sss_failover_ldap_connection); + if (state->connection == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); + ret = ENOMEM; + goto done; + } + + state->connection->uri = talloc_strdup(state->connection, server->uri); + if (state->connection->uri == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); + ret = ENOMEM; + goto done; + } + + switch (force_tls) { + case SSS_FAILOVER_TRANSACTION_TLS_DEFAULT: + tls = CON_TLS_DFL; + break; + case SSS_FAILOVER_TRANSACTION_TLS_ON: + tls = CON_TLS_ON; + break; + case SSS_FAILOVER_TRANSACTION_TLS_OFF: + tls = CON_TLS_OFF; + break; + } + + subreq = sdap_cli_connect_send(state, ev, opts, server->uri, + server->addr->sockaddr, + server->addr->sockaddr_len, !read_rootdse, + tls, !authenticate_connection, + kinit_expiration_time); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_ldap_connect_done, req); + + return req; + +done: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + + return req; +} + +static void +sss_failover_ldap_connect_done(struct tevent_req *subreq) +{ + struct sss_failover_ldap_connect_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ldap_connect_state); + + ret = sdap_cli_connect_recv(subreq, state, &state->connection->sh, + &state->connection->srv_opts); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + talloc_steal(state->connection, state->connection->sh); + talloc_steal(state->connection, state->connection->srv_opts); + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_ldap_connect_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + void **_connection) +{ + struct sss_failover_ldap_connect_state *state; + state = tevent_req_data(req, struct sss_failover_ldap_connect_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (_connection != NULL) { + *_connection = (void*)talloc_steal(mem_ctx, state->connection); + } + + return EOK; +} diff --git a/src/providers/failover/ldap/failover_ldap_kinit.c b/src/providers/failover/ldap/failover_ldap_kinit.c new file mode 100644 index 00000000000..3d7d4bbfc06 --- /dev/null +++ b/src/providers/failover/ldap/failover_ldap_kinit.c @@ -0,0 +1,199 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include + +#include "config.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_server.h" +#include "providers/failover/failover_server_resolve.h" +#include "providers/failover/failover_vtable_op.h" +#include "providers/ldap/sdap_async_private.h" +#include "providers/ldap/ldap_common.h" +#include "util/util.h" + +static void +sss_failover_ldap_kinit_options(struct sdap_options *opts, + const char **_keytab, + const char **_realm, + const char **_principal, + bool *_canonicalize, + int *_lifetime, + int *_timeout) +{ + *_keytab = dp_opt_get_string(opts->basic, SDAP_KRB5_KEYTAB); + *_realm = sdap_gssapi_realm(opts->basic); + *_principal = dp_opt_get_string(opts->basic, SDAP_SASL_AUTHID); + *_canonicalize = dp_opt_get_bool(opts->basic, SDAP_KRB5_CANONICALIZE); + *_lifetime = dp_opt_get_int(opts->basic, SDAP_KRB5_TICKET_LIFETIME); + *_timeout = dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT); +} + +struct sss_failover_ldap_kinit_state { + time_t expiration_time; +}; + +static void sss_failover_ldap_kinit_done(struct tevent_req *subreq); + +struct tevent_req * +sss_failover_ldap_kinit_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx, + struct sss_failover_server *server, + bool addr_changed, + void *pvt) +{ + struct sss_failover_ldap_kinit_state *state; + struct sdap_options *opts; + struct tevent_req *subreq; + struct tevent_req *req; + const char *keytab; + const char *principal; + const char *realm; + bool canonicalize; + int timeout; + int lifetime; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sss_failover_ldap_kinit_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + opts = talloc_get_type_abort(pvt, struct sdap_options); + + sss_failover_ldap_kinit_options(opts, &keytab, &realm, &principal, + &canonicalize, &lifetime, &timeout); + + ret = setenv("KRB5_CANONICALIZE", canonicalize ? "true" : "false", 1); + if (ret != 0) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to set KRB5_CANONICALIZE to %s\n", + canonicalize ? "true" : "false"); + ret = errno; + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Attempting kinit (%s, %s, %s, %d, %s)\n", + keytab != NULL ? keytab : "default", principal, realm, lifetime, + server->name); + + /* TODO write kdcinfo */ + + subreq = sdap_get_tgt_send(state, ev, realm, principal, keytab, lifetime, + timeout); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sss_failover_ldap_kinit_done, req); + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, ev); + } + + return req; +} + +static void +sss_failover_ldap_kinit_done(struct tevent_req *subreq) +{ + struct sss_failover_ldap_kinit_state *state; + struct tevent_req *req; + krb5_error_code kerr; + char *ccname; + int result; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sss_failover_ldap_kinit_state); + + ret = sdap_get_tgt_recv(subreq, state, &result, &kerr, &ccname, + &state->expiration_time); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + /* ret is request error, result is child error, kerr is kerberos error */ + switch (ret) { + case EOK: + if (result == EOK) { + /* TGT acquired. */ + ret = setenv("KRB5CCNAME", ccname, 1); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_OP_FAILURE, + "Unable to set env. variable KRB5CCNAME!\n"); + goto done; + } + ret = EOK; + goto done; + } else if (kerr == KRB5_KDC_UNREACH) { + ret = ERR_SERVER_FAILURE; + goto done; + } else if (result == EFAULT || result == EIO || result == EPERM) { + ret = ERR_AUTH_FAILED; + goto done; + } else { + ret = ERR_AUTH_FAILED; + goto done; + } + break; + case ETIMEDOUT: + /* The child did not responds. Try another KDC. */ + ret = ERR_SERVER_FAILURE; + goto done; + default: + /* Child did not execute correctly. Terminate. */ + goto done; + } + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +sss_failover_ldap_kinit_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + time_t *_expiration_time) +{ + struct sss_failover_ldap_kinit_state *state = NULL; + state = tevent_req_data(req, struct sss_failover_ldap_kinit_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (_expiration_time != NULL) { + *_expiration_time = state->expiration_time; + } + + return EOK; +} diff --git a/src/providers/failover/readme.md b/src/providers/failover/readme.md new file mode 100644 index 00000000000..315045dc376 --- /dev/null +++ b/src/providers/failover/readme.md @@ -0,0 +1,185 @@ +# SSSD Failover High-Level Documentation + +This document provides high-level view on the implementation of the failover +mechanism. The code abstracts automatic server selection, connection management +a retry logic from the backend code. The backend should not touch failover +internals. The main entry port for an operation that needs to contact a remote +server is `sss_failover_transaction_send()`. + +## Backend API + +### Failover Context + +* [failover.c]() +* [failover.h]() + +Previously, we had one failover context per backend and the context then +contained "services" (LDAP, AD, AD_GC, ...). Now there is a single failover +context for each required service or domain. This shifts the logic a bit from +pattern "resolve_service(fctx, AD)" to "connect_to(fctx_ad)". + +* `sss_failover_init()` - Initialize new failover context + +### Server and Group Management + +* [failover_group.c]() +* [failover_group.h]() + +Servers are organized into prioritized groups (e.g., primary, backup). Each +group is created when the backend starts - the backend will add the hard-coded +servers and enabled DNS discovery when required. + +When the failover tries to find a working server it tries to find servers +withing each group in order (group 0 has the highest priority). If no servers +are found within the group it tries the next group. + +- `sss_failover_group_new()` - Create a new server group +- `sss_failover_group_add_server()` - Add static servers to group +- `sss_failover_group_setup_dns_discovery()` - Enable DNS SRV discovery for group + +### Failover Transaction + +* [failover_transaction.c]() +* [failover_transaction.h]() + +The failover transaction hides the complicated logic of retrying an operation +the server fails in the middle of the operation. This replaces `sdap_id_op` code +and logic that was used previously, by hiding the logic inside a tevent request +wrapper. + +#### Usage Pattern + +```c +struct my_operation_state { + struct sss_failover_ldap_connection *conn; +}; + +static void my_operation_done(struct tevent_req *subreq); + +struct tevent_req *my_operation_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_failover_ctx *fctx) +{ + struct my_operation_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct my_operation_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + /* ...setup state... */ + + ret = sss_failover_transaction_send(state, ev, fctx, req, + my_operation_done); + if (ret != EOK) { + goto done; + } + + return req; + +done: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + + return req; +} + +static void my_operation_done(struct tevent_req *subreq) +{ + struct my_operation_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct my_operation_state); + + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + + /* Do what needs to be done and then call tevent_req_done(req) or + * tevent_req_error(req, ret) */ + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t my_operation_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} +``` + +- The operation **must** return `ERR_SERVER_FAILURE` if the failure is + server-related +- The failover code will then mark the server offline and retry with the next + server +- Fetch all data from the server **before** writing to sysdb to ensure atomicity + on retry + +### Errors + +* `ERR_SERVER_FAILURE` - Returning this error withing a failover transaction + will retry the transaction with another server + +* `ERR_NO_MORE_SERVERS` - This is returned from the transaction if there are no + more servers to try + +## Internals + +### Virtual Table + +* [failover_vtable.c]() +* [failover_vtable.h]() + +Provides setters and getters of providers custom function to connect, kinit, ... + +### Virtual Table Operations + +* [failover_vtable_op.c]() +* [failover_vtable_op.h]() + +This code is responsible for establishing server connection and kinit. It wraps the call to the given vtable function with server selection and resolution mechanism. + +- **`sss_failover_vtable_op_kinit_send/recv()`** - Selects a KDC and obtains host credentials +- **`sss_failover_vtable_op_connect_send/recv()`** - Selects a server and establishes connection + +These operations: +- Select servers from the candidate pool +- Resolve hostnames to IP addresses +- Call backend-specific vtable functions (kinit/connect) +- Mark servers as working/offline based on results +- Serialize through `vtable_op_queue` to ensure single active connection + +### Server Candidates + +* [failover_refresh_candidates.c]() +* [failover_refresh_candidates.h]() + +Instead of trying to connect to a server one by one, the new failover +implementation maintains a list of "candidate servers". The list is refreshed +periodically or when needed by pining servers from a server group in parallel +batches so it can quickly find the working servers, significantly reducing +operation time. + +The list of candidates is stored inside the failover context. Only one refresh +is triggered at the same time. diff --git a/src/tests/cmocka/test_failover_server.c b/src/tests/cmocka/test_failover_server.c new file mode 100644 index 00000000000..842179bb46e --- /dev/null +++ b/src/tests/cmocka/test_failover_server.c @@ -0,0 +1,570 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tests/cmocka/common_mock.h" +#include "providers/failover/failover_server.h" +#include "resolv/async_resolv.h" + +static int setup(void **state) +{ + TALLOC_CTX *test_ctx = NULL; + + assert_true(leak_check_setup()); + test_ctx = talloc_new(global_talloc_context); + assert_non_null(test_ctx); + check_leaks_push(test_ctx); + + *state = test_ctx; + + return 0; +} + +static int teardown(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + assert_true(check_leaks_pop(test_ctx)); + talloc_free(test_ctx); + assert_true(leak_check_teardown()); + + return 0; +} + +static uint8_t *mock_ip4_addr(TALLOC_CTX *mem_ctx, const char *addr) +{ + struct in_addr net_addr; + uint8_t *buf; + int ret; + + if (addr == NULL) { + return NULL; + } + + ret = inet_pton(AF_INET, addr, &net_addr); + assert_int_equal(ret, 1); + buf = talloc_memdup(mem_ctx, &net_addr, sizeof(struct in_addr)); + assert_non_null(buf); + + return buf; +} + +static uint8_t *mock_ip6_addr(TALLOC_CTX *mem_ctx, const char *addr) +{ + struct in6_addr net_addr; + uint8_t *buf; + int ret; + + if (addr == NULL) { + return NULL; + } + + ret = inet_pton(AF_INET6, addr, &net_addr); + assert_int_equal(ret, 1); + buf = talloc_memdup(mem_ctx, &net_addr, sizeof(struct in6_addr)); + assert_non_null(buf); + + return buf; +} + +/* Test: Successfully create a failover server */ +static void test_sss_failover_server_new(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + + srv = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldap://server.ipa.test", 389, 10, 100); + assert_non_null(srv); + assert_non_null(srv->name); + assert_string_equal(srv->name, "server.ipa.test"); + assert_non_null(srv->uri); + assert_string_equal(srv->uri, "ldap://server.ipa.test"); + assert_int_equal(srv->port, 389); + + assert_null(srv->addr); + assert_int_equal(srv->priority, 10); + assert_int_equal(srv->weight, 100); + + talloc_free(srv); +} + +/* Test: NULL hostname does not crash */ +static void test_sss_failover_server_new__null(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + + srv = sss_failover_server_new(test_ctx, NULL, "ldap://server.ipa.test", 389, + 10, 100); + assert_null(srv); +} + +/* Test: Successfully create a failover server with IPv4 address */ +static void test_sss_failover_server_set_address__ipv4(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + struct in_addr expected_addr; + struct sockaddr_in *sa_in; + const char *hostname = "server.ipa.test"; + const char *addr = "192.168.1.100"; + uint8_t *net_addr; + errno_t ret; + time_t now; + + net_addr = mock_ip4_addr(test_ctx, addr); + assert_non_null(net_addr); + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + now = time(NULL); + ret = sss_failover_server_set_address(srv, AF_INET, 10, net_addr); + assert_int_equal(ret, EOK); + + assert_non_null(srv->addr); + assert_int_equal(srv->addr->family, AF_INET); + assert_non_null(srv->addr->human); + assert_string_equal(srv->addr->human, addr); + assert_true(srv->addr->expire - now >= 10); + + ret = inet_pton(AF_INET, addr, &expected_addr); + assert_int_equal(ret, 1); + assert_non_null(srv->addr->binary); + assert_ptr_not_equal(srv->addr->binary, net_addr); + assert_memory_equal(srv->addr->binary, &expected_addr, + sizeof(struct in_addr)); + assert_int_equal(srv->addr->binary_len, sizeof(struct in_addr)); + + /* Verify sockaddr is properly set */ + assert_non_null(srv->addr->sockaddr); + assert_int_equal(srv->addr->sockaddr_len, sizeof(struct sockaddr_in)); + sa_in = (struct sockaddr_in *)srv->addr->sockaddr; + assert_int_equal(sa_in->sin_family, AF_INET); + assert_int_equal(ntohs(sa_in->sin_port), 389); + assert_memory_equal(&sa_in->sin_addr, &expected_addr, sizeof(struct in_addr)); + + talloc_free(net_addr); + talloc_free(srv); +} + +/* Test: Successfully create a failover server with IPv6 address */ +static void test_sss_failover_server_set_address__ipv6(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + struct in6_addr expected_addr; + struct sockaddr_in6 *sa_in6; + const char *hostname = "server.ipa.test"; + const char *addr = "2a00:102a:403a:c7a7:e05e:11e6:3189:3326"; + uint8_t *net_addr; + errno_t ret; + time_t now; + + net_addr = mock_ip6_addr(test_ctx, addr); + assert_non_null(net_addr); + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + now = time(NULL); + ret = sss_failover_server_set_address(srv, AF_INET6, 10, net_addr); + assert_int_equal(ret, EOK); + + assert_non_null(srv->addr); + assert_int_equal(srv->addr->family, AF_INET6); + assert_non_null(srv->addr->human); + assert_string_equal(srv->addr->human, addr); + assert_true(srv->addr->expire - now >= 10); + + ret = inet_pton(AF_INET6, addr, &expected_addr); + assert_int_equal(ret, 1); + assert_non_null(srv->addr->binary); + assert_ptr_not_equal(srv->addr->binary, net_addr); + assert_memory_equal(srv->addr->binary, &expected_addr, + sizeof(struct in6_addr)); + assert_int_equal(srv->addr->binary_len, sizeof(struct in6_addr)); + + /* Verify sockaddr is properly set */ + assert_non_null(srv->addr->sockaddr); + assert_int_equal(srv->addr->sockaddr_len, sizeof(struct sockaddr_in6)); + sa_in6 = (struct sockaddr_in6 *)srv->addr->sockaddr; + assert_int_equal(sa_in6->sin6_family, AF_INET6); + assert_int_equal(ntohs(sa_in6->sin6_port), 389); + assert_memory_equal(&sa_in6->sin6_addr, &expected_addr, sizeof(struct in6_addr)); + + talloc_free(net_addr); + talloc_free(srv); +} + +/* Test: Error out if invalid family is given */ +static void test_sss_failover_server_set_address__invalid_family(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + const char *hostname = "server.ipa.test"; + const char *addr = "192.168.1.100"; + uint8_t *net_addr; + errno_t ret; + + net_addr = mock_ip4_addr(test_ctx, addr); + assert_non_null(net_addr); + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + ret = sss_failover_server_set_address(srv, AF_UNIX, 10, net_addr); + assert_int_equal(ret, EINVAL); + + talloc_free(net_addr); + talloc_free(srv); +} + +/* Test: Error out if invalid address is given */ +static void test_sss_failover_server_set_address__null_addr(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + const char *hostname = "server.ipa.test"; + errno_t ret; + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + ret = sss_failover_server_set_address(srv, AF_INET, 10, NULL); + assert_int_equal(ret, EINVAL); + + talloc_free(srv); +} + +/* Test: Successfully clone a failover server with IPv4 address */ +static void test_sss_failover_server_clone__ipv4(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + struct sss_failover_server *clone; + const char *hostname = "server.ipa.test"; + const char *addr = "192.168.1.100"; + uint8_t *net_addr; + errno_t ret; + + net_addr = mock_ip4_addr(test_ctx, addr); + assert_non_null(net_addr); + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + ret = sss_failover_server_set_address(srv, AF_INET, 10, net_addr); + assert_int_equal(ret, EOK); + + clone = sss_failover_server_clone(test_ctx, srv); + assert_non_null(clone); + + /* Verify name is cloned */ + assert_non_null(clone->name); + assert_string_equal(clone->name, srv->name); + + /* Verify priority and weight are cloned */ + assert_int_equal(clone->priority, srv->priority); + assert_int_equal(clone->weight, srv->weight); + + /* Verify address is cloned */ + assert_non_null(clone->addr); + assert_int_equal(clone->addr->family, srv->addr->family); + assert_int_equal(clone->addr->expire, srv->addr->expire); + assert_non_null(clone->addr->human); + assert_string_equal(clone->addr->human, srv->addr->human); + assert_non_null(clone->addr->binary); + assert_memory_equal(clone->addr->binary, srv->addr->binary, + sizeof(struct in_addr)); + assert_int_equal(clone->addr->binary_len, srv->addr->binary_len); + assert_non_null(clone->addr->sockaddr); + assert_int_equal(clone->addr->sockaddr_len, srv->addr->sockaddr_len); + + /* Verify clone is independent (different memory) */ + assert_ptr_not_equal(clone, srv); + assert_ptr_not_equal(clone->name, srv->name); + assert_ptr_not_equal(clone->addr, srv->addr); + assert_ptr_not_equal(clone->addr->binary, srv->addr->binary); + assert_ptr_not_equal(clone->addr->human, srv->addr->human); + assert_ptr_not_equal(clone->addr->sockaddr, srv->addr->sockaddr); + + talloc_free(net_addr); + talloc_free(srv); + talloc_free(clone); +} + +/* Test: Successfully clone a failover server with IPv6 address */ +static void test_sss_failover_server_clone__ipv6(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + struct sss_failover_server *clone; + const char *hostname = "server1.ipa.test"; + const char *addr = "2a00:102a:403a:c7a7:e05e:11e6:3189:3326"; + uint8_t *net_addr; + errno_t ret; + + net_addr = mock_ip6_addr(test_ctx, addr); + assert_non_null(net_addr); + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server1.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + ret = sss_failover_server_set_address(srv, AF_INET6, 10, net_addr); + assert_int_equal(ret, EOK); + + clone = sss_failover_server_clone(test_ctx, srv); + assert_non_null(clone); + + /* Verify name is cloned */ + assert_non_null(clone->name); + assert_string_equal(clone->name, srv->name); + + /* Verify priority and weight are cloned */ + assert_int_equal(clone->priority, srv->priority); + assert_int_equal(clone->weight, srv->weight); + + /* Verify address is cloned */ + assert_non_null(clone->addr); + assert_int_equal(clone->addr->family, srv->addr->family); + assert_int_equal(clone->addr->expire, srv->addr->expire); + assert_non_null(clone->addr->human); + assert_string_equal(clone->addr->human, srv->addr->human); + assert_non_null(clone->addr->binary); + assert_memory_equal(clone->addr->binary, srv->addr->binary, + sizeof(struct in6_addr)); + assert_int_equal(clone->addr->binary_len, srv->addr->binary_len); + assert_non_null(clone->addr->sockaddr); + assert_int_equal(clone->addr->sockaddr_len, srv->addr->sockaddr_len); + + /* Verify clone is independent (different memory) */ + assert_ptr_not_equal(clone, srv); + assert_ptr_not_equal(clone->name, srv->name); + assert_ptr_not_equal(clone->addr, srv->addr); + assert_ptr_not_equal(clone->addr->binary, srv->addr->binary); + assert_ptr_not_equal(clone->addr->human, srv->addr->human); + assert_ptr_not_equal(clone->addr->sockaddr, srv->addr->sockaddr); + + talloc_free(net_addr); + talloc_free(srv); + talloc_free(clone); +} + +/* Test: Successfully clone a failover server with empty address */ +static void test_sss_failover_server_clone__null_addr(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + struct sss_failover_server *clone; + const char *hostname = "server.ipa.test"; + + srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test", + 389, 10, 100); + assert_non_null(srv); + + clone = sss_failover_server_clone(test_ctx, srv); + assert_non_null(clone); + + /* Verify name is cloned */ + assert_non_null(clone->name); + assert_string_equal(clone->name, srv->name); + + /* Verify priority and weight are cloned */ + assert_int_equal(clone->priority, srv->priority); + assert_int_equal(clone->weight, srv->weight); + + /* Verify address is cloned */ + assert_null(clone->addr); + + /* Verify clone is independent (different memory) */ + assert_ptr_not_equal(clone, srv); + assert_ptr_not_equal(clone->name, srv->name); + + talloc_free(srv); + talloc_free(clone); +} + +/* Test: Fail when cloning NULL server */ +static void test_sss_failover_server_clone__null_server(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *clone; + + clone = sss_failover_server_clone(test_ctx, NULL); + assert_null(clone); +} + +/* Test: Server state transitions */ +static void test_sss_failover_server_state_management(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv; + + srv = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldap://server.ipa.test", 389, 10, 100); + assert_non_null(srv); + + /* Initial state should be UNKNOWN */ + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_UNKNOWN); + assert_true(sss_failover_server_maybe_working(srv)); + + /* Mark as reachable */ + sss_failover_server_mark_reachable(srv); + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_REACHABLE); + assert_true(sss_failover_server_maybe_working(srv)); + + /* Mark as working */ + sss_failover_server_mark_working(srv); + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_WORKING); + assert_true(sss_failover_server_maybe_working(srv)); + + /* Mark as offline */ + sss_failover_server_mark_offline(srv); + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_OFFLINE); + assert_false(sss_failover_server_maybe_working(srv)); + + /* Mark as unknown again */ + sss_failover_server_mark_unknown(srv); + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_UNKNOWN); + assert_true(sss_failover_server_maybe_working(srv)); + + /* Mark as resolver error */ + sss_failover_server_mark_resolver_error(srv); + assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR); + assert_false(sss_failover_server_maybe_working(srv)); + + talloc_free(srv); +} + +/* Test: Compare two equal servers */ +static void test_sss_failover_server_equal__same(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv1; + struct sss_failover_server *srv2; + + srv1 = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldap://server.ipa.test", 389, 10, 100); + assert_non_null(srv1); + + srv2 = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldap://server.ipa.test", 389, 20, 200); + assert_non_null(srv2); + + /* Should be equal (only name and port matter) */ + assert_true(sss_failover_server_equal(srv1, srv2)); + + talloc_free(srv1); + talloc_free(srv2); +} + +/* Test: Compare two servers with different names */ +static void test_sss_failover_server_equal__different_name(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state; + struct sss_failover_server *srv1; + struct sss_failover_server *srv2; + + srv1 = sss_failover_server_new(test_ctx, "server1.ipa.test", + "ldap://server1.ipa.test", 389, 10, 100); + assert_non_null(srv1); + + srv2 = sss_failover_server_new(test_ctx, "server2.ipa.test", + "ldap://server2.ipa.test", 389, 10, 100); + assert_non_null(srv2); + + /* Should not be equal (different names) */ + assert_false(sss_failover_server_equal(srv1, srv2)); + + talloc_free(srv1); + talloc_free(srv2); +} + +/* Test: Compare two servers with different ports */ +static void +test_sss_failover_server_equal__different_port(void **state) +{ + TALLOC_CTX *test_ctx = (TALLOC_CTX *)*state; + struct sss_failover_server *srv1; + struct sss_failover_server *srv2; + + srv1 = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldap://server.ipa.test", 389, 10, 100); + assert_non_null(srv1); + + srv2 = sss_failover_server_new(test_ctx, "server.ipa.test", + "ldaps://server.ipa.test", 636, 10, 100); + assert_non_null(srv2); + + /* Should not be equal (different ports) */ + assert_false(sss_failover_server_equal(srv1, srv2)); + + talloc_free(srv1); + talloc_free(srv2); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_sss_failover_server_new, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_new__null, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__ipv4, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__ipv6, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__invalid_family, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__null_addr, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__ipv4, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__ipv6, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__null_addr, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__null_server, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_state_management, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__same, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__different_name, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__different_port, + setup, teardown) + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/src/util/util_errors.c b/src/util/util_errors.c index 48badb914d7..21eb43f878d 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -157,6 +157,7 @@ struct err_string error_to_str[] = { { "Certificate authority file not found"}, /* ERR_CA_DB_NOT_FOUND */ { "Server failure"}, /* ERR_SERVER_FAILURE */ + { "No more servers to try"}, /* ERR_NO_MORE_SERVERS */ { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index 244ade63341..aa73626343c 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -182,6 +182,7 @@ enum sssd_errors { ERR_CA_DB_NOT_FOUND, ERR_SERVER_FAILURE, + ERR_NO_MORE_SERVERS, ERR_LAST /* ALWAYS LAST */ }; From 89cdd8dc93d9dd434f2bb1430107f48f6131cb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 1 Oct 2025 14:30:40 +0200 Subject: [PATCH 12/39] failover: implement new failover interface This crafts and implements the new failover interface, it does not provide complete implementation of the failover mechanism yet. It brings the code to a state were the public and private interfaces are stable, working and testable so the following tasks can be split and work on in parallel. What is missing at this state: - server configuration and discovery (failover_server_group/batch/vtable_op) - server selection mechanism (sss_failover_vtable_op_server_next) - kerberos authentication - sharing servers between IPA/AD LDAP and KDC - online/offline callbacks (resolve callback should not be needed) But especially it is possible to start refactoring SSSD code to start using the new failover implementation. --- .../failover/failover_refresh_candidates.c | 5 ---- src/providers/failover/readme.md | 24 +++++++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/providers/failover/failover_refresh_candidates.c b/src/providers/failover/failover_refresh_candidates.c index bc387a4c602..d8a12bff96c 100644 --- a/src/providers/failover/failover_refresh_candidates.c +++ b/src/providers/failover/failover_refresh_candidates.c @@ -159,8 +159,6 @@ static void sss_failover_ping_done(struct tevent_req *subreq) state->server->name, state->server->port, ping_duration.tv_sec, ping_duration.tv_usec); - sss_failover_server_mark_reachable(state->server); - ret = EOK; done: @@ -669,9 +667,6 @@ sss_failover_refresh_candidates_done(struct tevent_req *subreq) if (ret != EOK) { goto done; } - - /* Pinging next group. */ - return; } DEBUG(SSSDBG_TRACE_FUNC, "Found %zu candidate servers in group %s:%u\n", diff --git a/src/providers/failover/readme.md b/src/providers/failover/readme.md index 315045dc376..5bef0d3a394 100644 --- a/src/providers/failover/readme.md +++ b/src/providers/failover/readme.md @@ -10,8 +10,8 @@ server is `sss_failover_transaction_send()`. ### Failover Context -* [failover.c]() -* [failover.h]() +* [sss_failover.c]() +* [sss_failover.h]() Previously, we had one failover context per backend and the context then contained "services" (LDAP, AD, AD_GC, ...). Now there is a single failover @@ -22,8 +22,8 @@ pattern "resolve_service(fctx, AD)" to "connect_to(fctx_ad)". ### Server and Group Management -* [failover_group.c]() -* [failover_group.h]() +* [sss_failover_group.c]() +* [sss_failover_group.h]() Servers are organized into prioritized groups (e.g., primary, backup). Each group is created when the backend starts - the backend will add the hard-coded @@ -39,8 +39,8 @@ are found within the group it tries the next group. ### Failover Transaction -* [failover_transaction.c]() -* [failover_transaction.h]() +* [sss_failover_transaction.c]() +* [sss_failover_transaction.h]() The failover transaction hides the complicated logic of retrying an operation the server fails in the middle of the operation. This replaces `sdap_id_op` code @@ -148,15 +148,15 @@ errno_t my_operation_recv(TALLOC_CTX *mem_ctx, ### Virtual Table -* [failover_vtable.c]() -* [failover_vtable.h]() +* [sss_failover_vtable.c]() +* [sss_failover_vtable.h]() Provides setters and getters of providers custom function to connect, kinit, ... ### Virtual Table Operations -* [failover_vtable_op.c]() -* [failover_vtable_op.h]() +* [sss_failover_vtable_op.c]() +* [sss_failover_vtable_op.h]() This code is responsible for establishing server connection and kinit. It wraps the call to the given vtable function with server selection and resolution mechanism. @@ -172,8 +172,8 @@ These operations: ### Server Candidates -* [failover_refresh_candidates.c]() -* [failover_refresh_candidates.h]() +* [sss_failover_refresh_candidates.c]() +* [sss_failover_refresh_candidates.h]() Instead of trying to connect to a server one by one, the new failover implementation maintains a list of "candidate servers". The list is refreshed From 54dacd5373f21091ea66b1a18685938d6431579a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Tue, 24 Feb 2026 14:08:10 +0100 Subject: [PATCH 13/39] utils: add TEVENT_REQ_ERROR_TO_ERRNO --- src/util/util.h | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/util/util.h b/src/util/util.h index ccf0b30ab7e..a7cb9fdad6b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -141,25 +141,39 @@ enum sssd_exit_status { #endif #endif -#define TEVENT_REQ_RETURN_ON_ERROR(req) do { \ - enum tevent_req_state TRROEstate; \ - uint64_t TRROEuint64; \ - errno_t TRROEerr; \ +#define TEVENT_REQ_ERROR_TO_ERRNO(req) ({ \ + enum tevent_req_state __TRETE_state; \ + uint64_t __TRETE_uint64; \ + errno_t __TRETE_err; \ + errno_t __TRETE_ret = EOK; \ \ - if (tevent_req_is_error(req, &TRROEstate, &TRROEuint64)) { \ - TRROEerr = (errno_t)TRROEuint64; \ - switch (TRROEstate) { \ + if (tevent_req_is_error(req, &__TRETE_state, &__TRETE_uint64)) { \ + __TRETE_err = (errno_t)__TRETE_uint64; \ + switch (__TRETE_state) { \ case TEVENT_REQ_USER_ERROR: \ - if (TRROEerr == 0) { \ - return ERR_INTERNAL; \ + if (__TRETE_err == 0) { \ + __TRETE_ret = ERR_INTERNAL; \ } \ - return TRROEerr; \ + __TRETE_ret = __TRETE_err; \ + break; \ case TEVENT_REQ_TIMED_OUT: \ - return ETIMEDOUT; \ + __TRETE_ret = ETIMEDOUT; \ + break; \ + case TEVENT_REQ_NO_MEMORY: \ + __TRETE_ret = ENOMEM; \ + break; \ default: \ - return ERR_INTERNAL; \ + __TRETE_ret = ERR_INTERNAL; \ } \ } \ + __TRETE_ret; \ +}) + +#define TEVENT_REQ_RETURN_ON_ERROR(req) do { \ + errno_t TRROEret = TEVENT_REQ_ERROR_TO_ERRNO(req); \ + if (TRROEret != EOK) { \ + return TRROEret; \ + } \ } while (0) #define OUT_OF_ID_RANGE(id, min, max) \ From 9c0cd7d0b2d4937f73779735204259b1b62d9dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Wed, 1 Oct 2025 14:30:40 +0200 Subject: [PATCH 14/39] failover: implement new failover interface This crafts and implements the new failover interface, it does not provide complete implementation of the failover mechanism yet. It brings the code to a state were the public and private interfaces are stable, working and testable so the following tasks can be split and work on in parallel. What is missing at this state: - server configuration and discovery (failover_server_group/batch/vtable_op) - server selection mechanism (sss_failover_vtable_op_server_next) - kerberos authentication - sharing servers between IPA/AD LDAP and KDC - online/offline callbacks (resolve callback should not be needed) But especially it is possible to start refactoring SSSD code to start using the new failover implementation. --- Makefile.am | 1 - src/util/typeof.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/util/typeof.h diff --git a/Makefile.am b/Makefile.am index 8b29d6c5cc2..313aa874a90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -882,7 +882,6 @@ dist_noinst_HEADERS = \ src/providers/failover/failover_transaction.h \ src/providers/failover/failover_vtable.h \ src/providers/failover/failover_vtable_op.h \ - src/providers/failover/ldap/failover_ldap.h \ src/util/child_common.h \ src/util/child_bootstrap.h \ src/providers/simple/simple_access.h \ diff --git a/src/util/typeof.h b/src/util/typeof.h new file mode 100644 index 00000000000..89f499d560e --- /dev/null +++ b/src/util/typeof.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2025 Red Hat + + 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 . +*/ + +#ifndef _SSS_TYPEOF_H_ +#define _SSS_TYPEOF_H_ + +/** + * Provide a compile-time type safety for callbacks and handlers. + * + * We use GCC __typeof__ extension to achieve this. We retrieve the private + * data type and create the expected handler function type with it. If the + * method accepts parsed D-Bus arguments, they are appended with variadic + * parameters. We check that the handler type matches the expected type + * and return the sbus_handler structure value. + * + * We also use __attribute__((unused)) to suppress compiler warning about + * unused __fn. + * + * We do not perform this check on platforms where this extension is not + * available and just create a generic handler. This does not matter since + * we test compilation with GCC anyway. + */ +#if (__GNUC__ >= 3) + +#define SSS_CHECK_FUNCTION_TYPE(fn, return_type, ...) ({ \ + __attribute__((unused)) return_type (*__fn)(__VA_ARGS__) = (fn); \ +}) + +#define SSS_TYPEOF(data) __typeof__(data) + +#else +#define SSS_CHECK_FUNCTION_TYPE(handler, return_type, ...) +#define SSS_TYPEOF(data) (void*) +#endif + +#endif /* _SSS_TYPEOF_H_ */ From fe96ad5b93551757146701a6d5b49e1e8f17621a Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 17 Mar 2026 16:41:12 -0400 Subject: [PATCH 15/39] failover: minor header fixes --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 313aa874a90..8b29d6c5cc2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -882,6 +882,7 @@ dist_noinst_HEADERS = \ src/providers/failover/failover_transaction.h \ src/providers/failover/failover_vtable.h \ src/providers/failover/failover_vtable_op.h \ + src/providers/failover/ldap/failover_ldap.h \ src/util/child_common.h \ src/util/child_bootstrap.h \ src/providers/simple/simple_access.h \ From 35226c15c72ed1dbb138726835ac9a20d42fb0fe Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Fri, 13 Mar 2026 14:27:30 -0400 Subject: [PATCH 16/39] dp: Remove sdap_ret and sdap_error Assisted by: Claude code (Sonnet 4.6) --- src/providers/ad/ad_gpo.c | 5 +- src/providers/ad/ad_id.c | 12 ++- src/providers/ad/ad_pac.c | 8 +- src/providers/ad/ad_pac.h | 3 +- src/providers/ipa/ipa_id.c | 2 +- src/providers/ipa/ipa_subdomains_ext_groups.c | 2 +- src/providers/ldap/ldap_common.h | 14 ++-- src/providers/ldap/ldap_id.c | 79 ++++++------------- src/providers/ldap/ldap_id_netgroup.c | 8 +- src/providers/ldap/ldap_id_services.c | 8 +- src/providers/ldap/ldap_id_subid.c | 13 +-- src/providers/ldap/sdap_async_initgroups.c | 2 +- src/providers/ldap/sdap_async_initgroups_ad.c | 11 ++- src/providers/ldap/sdap_iphost.c | 11 +-- src/providers/ldap/sdap_ipnetwork.c | 11 +-- src/providers/ldap/sdap_refresh.c | 7 +- 16 files changed, 59 insertions(+), 137 deletions(-) diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index 5c2f117a51c..e2eeb2692be 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -2283,7 +2283,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) struct ad_gpo_access_state *state; int ret; int dp_error; - int sdap_ret; const char *target_dn = NULL; uint32_t uac; static const char *host_attrs[] = { SYSDB_ORIG_DN, SYSDB_AD_USER_ACCOUNT_CONTROL, SYSDB_SID_STR, NULL }; @@ -2293,10 +2292,10 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); - ret = groups_by_user_recv(subreq, &dp_error, &sdap_ret); + ret = groups_by_user_recv(subreq, &dp_error); talloc_zfree(subreq); if (ret != EOK) { - if (sdap_ret == EAGAIN && dp_error == DP_ERR_OFFLINE) { + if (ret == EAGAIN && dp_error == DP_ERR_OFFLINE) { DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); ret = process_offline_gpos(state, state->user, diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 73cdd5994b2..272aea0ad74 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -241,7 +241,6 @@ ad_handle_acct_info_done(struct tevent_req *subreq) { errno_t ret; int dp_error; - int sdap_err; const char *err; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); @@ -249,9 +248,9 @@ ad_handle_acct_info_done(struct tevent_req *subreq) struct ad_handle_acct_info_state); if (state->using_pac) { - ret = ad_handle_pac_initgr_recv(subreq, &dp_error, &err, &sdap_err); + ret = ad_handle_pac_initgr_recv(subreq, &dp_error, &err); } else { - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err, &sdap_err); + ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err); } if (dp_error == DP_ERR_OFFLINE && state->conn[state->cindex+1] != NULL @@ -259,8 +258,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq) /* This is a special case: GC does not work. * We need to Fall back to ldap */ - ret = EOK; - sdap_err = ENOENT; + ret = ENOENT; } talloc_zfree(subreq); if (ret != EOK) { @@ -271,10 +269,10 @@ ad_handle_acct_info_done(struct tevent_req *subreq) goto fail; } - if (sdap_err == EOK) { + if (ret == EOK) { tevent_req_done(req); return; - } else if (sdap_err != ENOENT) { + } else if (ret != ENOENT) { ret = EIO; goto fail; } diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c index 73bc192b68d..e5642f5a1d1 100644 --- a/src/providers/ad/ad_pac.c +++ b/src/providers/ad/ad_pac.c @@ -230,7 +230,6 @@ struct ad_handle_pac_initgr_state { struct dp_id_data *ar; const char *err; int dp_error; - int sdap_ret; struct sdap_options *opts; size_t num_missing_sids; @@ -277,7 +276,6 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, * lookup path. */ state->err = NULL; state->dp_error = DP_ERR_OK; - state->sdap_ret = EOK; ret = ad_get_pac_data_from_user_entry(state, msg, id_ctx->opts->idmap_ctx->map, @@ -433,8 +431,7 @@ static void ad_handle_pac_initgr_lookup_sids_done(struct tevent_req *subreq) } errno_t ad_handle_pac_initgr_recv(struct tevent_req *req, - int *_dp_error, const char **_err, - int *sdap_ret) + int *_dp_error, const char **_err) { struct ad_handle_pac_initgr_state *state; @@ -448,9 +445,6 @@ errno_t ad_handle_pac_initgr_recv(struct tevent_req *req, *_err = state->err; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ad/ad_pac.h b/src/providers/ad/ad_pac.h index 405d1c3af1b..93f31ceda5b 100644 --- a/src/providers/ad/ad_pac.h +++ b/src/providers/ad/ad_pac.h @@ -77,8 +77,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct ldb_message *msg); errno_t ad_handle_pac_initgr_recv(struct tevent_req *req, - int *_dp_error, const char **_err, - int *sdap_ret); + int *_dp_error, const char **_err); errno_t check_upn_and_sid_from_user_and_pac(struct ldb_message *msg, struct sss_idmap_ctx *ctx, diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c index d1a655de0c3..4409fed72bf 100644 --- a/src/providers/ipa/ipa_id.c +++ b/src/providers/ipa/ipa_id.c @@ -781,7 +781,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) SYSDB_HOMEDIR, NULL }; - ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL, NULL); + ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret); diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c index 50b95bb3791..eb0691439cb 100644 --- a/src/providers/ipa/ipa_subdomains_ext_groups.c +++ b/src/providers/ipa/ipa_subdomains_ext_groups.c @@ -1098,7 +1098,7 @@ static void ipa_add_trusted_memberships_get_group_done(struct tevent_req *subreq struct add_trusted_membership_state); int ret; - ret = groups_get_recv(subreq, &state->dp_error, NULL); + ret = groups_get_recv(subreq, &state->dp_error); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to read group [%s] from LDAP [%d](%s)\n", diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 6f7486278a4..24fcec78913 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -157,8 +157,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, bool noexist_delete); errno_t sdap_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err, - int *sdap_ret); + int *_dp_error, const char **_err); struct tevent_req * sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, @@ -302,7 +301,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, bool noexist_delete, bool no_members, bool set_non_posix); -int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +int groups_get_recv(struct tevent_req *req, int *dp_error_out); struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -318,7 +317,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, bool noexist_delete, bool set_non_posix); -int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +int groups_by_user_recv(struct tevent_req *req, int *dp_error_out); struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -327,7 +326,7 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct sdap_id_conn_ctx *conn, const char *name, bool noexist_delete); -int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out); struct tevent_req * services_get_send(TALLOC_CTX *mem_ctx, @@ -341,7 +340,7 @@ services_get_send(TALLOC_CTX *mem_ctx, bool noexist_delete); errno_t -services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +services_get_recv(struct tevent_req *req, int *dp_error_out); struct tevent_req * sdap_iphost_handler_send(TALLOC_CTX *mem_ctx, @@ -491,8 +490,7 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, struct sdap_id_conn_ctx *conn, const char* filter_value); -int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out, - int *sdap_ret); +int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out); #endif #endif /* _LDAP_COMMON_H_ */ diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index bdde2a6c230..e842fd9eeb0 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -147,7 +147,6 @@ struct users_get_state { bool non_posix; int dp_error; - int sdap_ret; bool noexist_delete; struct sysdb_attrs *extra_attrs; }; @@ -377,7 +376,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, } ret = EOK; - state->sdap_ret = ENOENT; state->dp_error = DP_ERR_OK; goto done; } @@ -601,7 +599,6 @@ static void users_get_done(struct tevent_req *subreq) } } } - state->sdap_ret = ret; if (ret && ret != ENOENT) { state->dp_error = dp_error; @@ -623,7 +620,7 @@ static void users_get_done(struct tevent_req *subreq) tevent_req_done(req); } -int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +int users_get_recv(struct tevent_req *req, int *dp_error_out) { struct users_get_state *state = tevent_req_data(req, struct users_get_state); @@ -632,10 +629,6 @@ int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -661,7 +654,6 @@ struct groups_get_state { bool non_posix; int dp_error; - int sdap_ret; bool noexist_delete; bool no_members; }; @@ -984,7 +976,6 @@ static void groups_get_done(struct tevent_req *subreq) return; } - state->sdap_ret = ret; if (ret && ret != ENOENT) { state->dp_error = dp_error; @@ -1039,7 +1030,7 @@ static void groups_get_mpg_done(struct tevent_req *subreq) struct groups_get_state *state = tevent_req_data(req, struct groups_get_state); - ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = users_get_recv(subreq, &state->dp_error); talloc_zfree(subreq); if (ret != EOK) { @@ -1047,7 +1038,7 @@ static void groups_get_mpg_done(struct tevent_req *subreq) return; } - if (state->sdap_ret == ENOENT && state->noexist_delete == true) { + if (ret == ENOENT && state->noexist_delete == true) { ret = groups_get_handle_no_group(state, state->domain, state->filter_type, state->filter_value); @@ -1123,7 +1114,7 @@ errno_t groups_get_handle_no_group(TALLOC_CTX *mem_ctx, return ret; } -int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +int groups_get_recv(struct tevent_req *req, int *dp_error_out) { struct groups_get_state *state = tevent_req_data(req, struct groups_get_state); @@ -1132,10 +1123,6 @@ int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1163,7 +1150,6 @@ struct groups_by_user_state { bool non_posix; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -1314,9 +1300,8 @@ static void groups_by_user_done(struct tevent_req *subreq) return; } - state->sdap_ret = ret; - switch (state->sdap_ret) { + switch (ret) { case ENOENT: if (state->noexist_delete == true) { const char *cname; @@ -1354,7 +1339,7 @@ static void groups_by_user_done(struct tevent_req *subreq) tevent_req_done(req); } -int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +int groups_by_user_recv(struct tevent_req *req, int *dp_error_out) { struct groups_by_user_state *state = tevent_req_data(req, struct groups_by_user_state); @@ -1363,10 +1348,6 @@ int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1387,7 +1368,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, bool noexist_delete); errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out, int *sdap_ret); + int *dp_error_out); bool sdap_is_enum_request(struct dp_id_data *ar) { @@ -1408,7 +1389,6 @@ struct sdap_handle_acct_req_state { struct dp_id_data *ar; const char *err; int dp_error; - int sdap_ret; }; static void sdap_handle_acct_req_done(struct tevent_req *subreq); @@ -1627,31 +1607,31 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ err = "User lookup failed"; - ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = users_get_recv(subreq, &state->dp_error); break; case BE_REQ_GROUP: /* group */ err = "Group lookup failed"; - ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = groups_get_recv(subreq, &state->dp_error); break; case BE_REQ_INITGROUPS: /* init groups for user */ err = "Init group lookup failed"; - ret = groups_by_user_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = groups_by_user_recv(subreq, &state->dp_error); break; case BE_REQ_SUBID_RANGES: err = "Subid ranges lookup failed"; #ifdef BUILD_SUBID - ret = subid_ranges_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = subid_ranges_get_recv(subreq, &state->dp_error); #else ret = EINVAL; #endif break; case BE_REQ_NETGROUP: err = "Netgroup lookup failed"; - ret = ldap_netgroup_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = ldap_netgroup_get_recv(subreq, &state->dp_error); break; case BE_REQ_SERVICES: err = "Service lookup failed"; - ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = services_get_recv(subreq, &state->dp_error); break; case BE_REQ_BY_SECID: /* Fall through */ @@ -1659,12 +1639,11 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) /* Fall through */ case BE_REQ_USER_AND_GROUP: err = "Lookup by SID failed"; - ret = sdap_get_user_and_group_recv(subreq, &state->dp_error, - &state->sdap_ret); + ret = sdap_get_user_and_group_recv(subreq, &state->dp_error); break; case BE_REQ_BY_CERT: err = "User lookup by certificate failed"; - ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = users_get_recv(subreq, &state->dp_error); break; default: /* fail */ ret = EINVAL; @@ -1684,8 +1663,7 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) errno_t sdap_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err, - int *sdap_ret) + int *_dp_error, const char **_err) { struct sdap_handle_acct_req_state *state; @@ -1704,10 +1682,6 @@ sdap_handle_acct_req_recv(struct tevent_req *req, *_err = state->err; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -1728,7 +1702,6 @@ struct get_user_and_group_state { const char **attrs; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -1803,7 +1776,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) int ret; struct sdap_id_conn_ctx *user_conn; - ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = groups_get_recv(subreq, &state->dp_error); talloc_zfree(subreq); if (ret != EOK) { /* Fatal error while looking up group */ @@ -1811,10 +1784,10 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) return; } - if (state->sdap_ret == EOK) { /* Matching group found */ + if (ret == EOK) { /* Matching group found */ tevent_req_done(req); return; - } else if (state->sdap_ret != ENOENT) { + } else if (ret != ENOENT) { tevent_req_error(req, EIO); return; } @@ -1849,14 +1822,14 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) struct get_user_and_group_state); int ret; - ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + ret = users_get_recv(subreq, &state->dp_error); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - if (state->sdap_ret == ENOENT) { + if (ret == ENOENT) { if (state->noexist_delete == true) { /* The search ran to completion, but nothing was found. * Delete the existing entry, if any. */ @@ -1868,7 +1841,7 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) return; } } - } else if (state->sdap_ret != EOK) { + } else if (ret != EOK) { tevent_req_error(req, EIO); return; } @@ -1879,7 +1852,7 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) } errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out, int *sdap_ret) + int *dp_error_out) { struct get_user_and_group_state *state = tevent_req_data(req, struct get_user_and_group_state); @@ -1888,10 +1861,6 @@ errno_t sdap_get_user_and_group_recv(struct tevent_req *req, *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1959,7 +1928,7 @@ static void sdap_account_info_handler_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_account_info_handler_state); - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL); + ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ diff --git a/src/providers/ldap/ldap_id_netgroup.c b/src/providers/ldap/ldap_id_netgroup.c index 1fb01cf1fb3..d17396ed9b7 100644 --- a/src/providers/ldap/ldap_id_netgroup.c +++ b/src/providers/ldap/ldap_id_netgroup.c @@ -49,7 +49,6 @@ struct ldap_netgroup_get_state { struct sysdb_attrs **netgroups; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -199,7 +198,6 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) return; } - state->sdap_ret = ret; if (ret && ret != ENOENT) { state->dp_error = dp_error; @@ -228,7 +226,7 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) return; } -int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out) { struct ldap_netgroup_get_state *state = tevent_req_data(req, struct ldap_netgroup_get_state); @@ -237,10 +235,6 @@ int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c index 52a15631842..2c75ba8bebc 100644 --- a/src/providers/ldap/ldap_id_services.c +++ b/src/providers/ldap/ldap_id_services.c @@ -48,7 +48,6 @@ struct sdap_services_get_state { int filter_type; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -242,7 +241,6 @@ services_get_done(struct tevent_req *subreq) /* Return to the mainloop to retry */ return; } - state->sdap_ret = ret; /* An error occurred. */ if (ret && ret != ENOENT) { @@ -289,7 +287,7 @@ services_get_done(struct tevent_req *subreq) } errno_t -services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) +services_get_recv(struct tevent_req *req, int *dp_error_out) { struct sdap_services_get_state *state = tevent_req_data(req, struct sdap_services_get_state); @@ -298,10 +296,6 @@ services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret) *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c index f6353d75c10..4084d20684d 100644 --- a/src/providers/ldap/ldap_id_subid.c +++ b/src/providers/ldap/ldap_id_subid.c @@ -36,7 +36,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, const char *extra_value, bool noexist_delete, bool set_non_posix); -int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +int users_get_recv(struct tevent_req *req, int *dp_error_out); static int subid_ranges_get_retry(struct tevent_req *req); static void subid_ranges_get_connect_done(struct tevent_req *subreq); @@ -60,7 +60,6 @@ struct subid_ranges_get_state { const char **attrs; int dp_error; - int sdap_ret; }; struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, @@ -221,7 +220,7 @@ static void subid_ranges_resolve_owner_done(struct tevent_req *subreq) int dp_error = DP_ERR_FATAL; int ret; - ret = users_get_recv(subreq, &dp_error, NULL); + ret = users_get_recv(subreq, &dp_error); talloc_zfree(subreq); if (ret != EOK) { @@ -314,7 +313,6 @@ static void subid_ranges_get_done(struct tevent_req *subreq) } return; } - state->sdap_ret = ret; if (ret && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve subid ranges.\n"); @@ -343,8 +341,7 @@ static void subid_ranges_get_done(struct tevent_req *subreq) tevent_req_done(req); } -int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out, - int *sdap_ret) +int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out) { struct subid_ranges_get_state *state = tevent_req_data(req, struct subid_ranges_get_state); @@ -353,10 +350,6 @@ int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out, *dp_error_out = state->dp_error; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 3d1137f6638..d9348aba453 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -3442,7 +3442,7 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); errno_t ret; - ret = groups_get_recv(subreq, NULL, NULL); + ret = groups_get_recv(subreq, NULL); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index c8f82d7ed5f..a82b5b80a2e 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -361,26 +361,25 @@ static void sdap_ad_resolve_sids_done(struct tevent_req *subreq) struct sdap_ad_resolve_sids_state *state = NULL; struct tevent_req *req = NULL; int dp_error; - int sdap_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_resolve_sids_state); - ret = groups_get_recv(subreq, &dp_error, &sdap_error); + ret = groups_get_recv(subreq, &dp_error); talloc_zfree(subreq); - if (ret == EOK && sdap_error == ENOENT && dp_error == DP_ERR_OK) { + if (ret == ENOENT && dp_error == DP_ERR_OK) { /* Group was not found, we will ignore the error and continue with * next group. This may happen for example if the group is built-in, * but a custom search base is provided. */ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to resolve SID %s - will try next sid.\n", state->current_sid); - } else if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) { + } else if (ret != EOK || dp_error != DP_ERR_OK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s [dp_error: %d, " - "sdap_error: %d, ret: %d]: %s\n", state->current_sid, dp_error, - sdap_error, ret, strerror(ret)); + "ret: %d]: %s\n", state->current_sid, dp_error, + ret, strerror(ret)); goto done; } diff --git a/src/providers/ldap/sdap_iphost.c b/src/providers/ldap/sdap_iphost.c index 79c707b6d71..ccf94a068f9 100644 --- a/src/providers/ldap/sdap_iphost.c +++ b/src/providers/ldap/sdap_iphost.c @@ -40,7 +40,6 @@ struct sdap_ip_host_get_state { const char **attrs; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -222,7 +221,6 @@ sdap_ip_host_get_done(struct tevent_req *subreq) /* Return to the mainloop to retry */ return; } - state->sdap_ret = ret; /* An error occurred. */ if (ret && ret != ENOENT) { @@ -264,8 +262,7 @@ sdap_ip_host_get_done(struct tevent_req *subreq) static errno_t sdap_ip_host_get_recv(struct tevent_req *req, - int *dp_error_out, - int *sdap_ret) + int *dp_error_out) { struct sdap_ip_host_get_state *state; @@ -275,10 +272,6 @@ sdap_ip_host_get_recv(struct tevent_req *req, *dp_error_out = state->dp_error; } - if (sdap_ret != NULL) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -350,7 +343,7 @@ static void sdap_ip_host_handler_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ip_host_handler_state); - ret = sdap_ip_host_get_recv(subreq, &dp_error, NULL); + ret = sdap_ip_host_get_recv(subreq, &dp_error); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ diff --git a/src/providers/ldap/sdap_ipnetwork.c b/src/providers/ldap/sdap_ipnetwork.c index b78f50b787d..eb7bbc4e66d 100644 --- a/src/providers/ldap/sdap_ipnetwork.c +++ b/src/providers/ldap/sdap_ipnetwork.c @@ -40,7 +40,6 @@ struct sdap_ipnetwork_get_state { const char **attrs; int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -222,7 +221,6 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) /* Return to the mainloop to retry */ return; } - state->sdap_ret = ret; /* An error occurred. */ if (ret && ret != ENOENT) { @@ -265,8 +263,7 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) static errno_t sdap_ipnetwork_get_recv(struct tevent_req *req, - int *dp_error_out, - int *sdap_ret) + int *dp_error_out) { struct sdap_ipnetwork_get_state *state; @@ -276,10 +273,6 @@ sdap_ipnetwork_get_recv(struct tevent_req *req, *dp_error_out = state->dp_error; } - if (sdap_ret != NULL) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -353,7 +346,7 @@ sdap_ipnetwork_handler_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ipnetwork_handler_state); - ret = sdap_ipnetwork_get_recv(subreq, &dp_error, NULL); + ret = sdap_ipnetwork_get_recv(subreq, &dp_error); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c index 402db53a986..da7359d5135 100644 --- a/src/providers/ldap/sdap_refresh.c +++ b/src/providers/ldap/sdap_refresh.c @@ -151,19 +151,18 @@ static void sdap_refresh_done(struct tevent_req *subreq) struct tevent_req *req = NULL; const char *err_msg = NULL; errno_t dp_error; - int sdap_ret; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_refresh_state); - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err_msg, &sdap_ret); + ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err_msg); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, " - "sdap_ret: %d, errno: %d]: %s\n", + "errno: %d]: %s\n", be_req2str(state->account_req->entry_type), - dp_error, sdap_ret, ret, err_msg); + dp_error, ret, err_msg); goto done; } From d1f12972d46593ea684f9ecda5e65f1f564c02b2 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Mon, 30 Mar 2026 13:51:14 -0400 Subject: [PATCH 17/39] ldap: Replace EIO/ETIMEDOUT with ERR_SERVER_FAILURE In low level ldap search functions --- src/providers/ldap/sdap_async.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index b8256580ce2..766def326ec 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -1590,7 +1590,7 @@ sdap_get_generic_ext_send(TALLOC_CTX *memctx, if (state->sh == NULL || state->sh->ldap == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Trying LDAP search while not connected.\n"); - tevent_req_error(req, EIO); + tevent_req_error(req, ERR_SERVER_FAILURE); tevent_req_post(req, ev); return req; } @@ -1684,12 +1684,12 @@ static errno_t sdap_get_generic_ext_step(struct tevent_req *req) lret = ldap_create_page_control(state->sh->ldap, state->sh->page_size, state->cookie.bv_val ? - &state->cookie : - NULL, + &state->cookie : + NULL, false, &page_control); if (lret != LDAP_SUCCESS) { - ret = EIO; + ret = ERR_SERVER_FAILURE; goto done; } state->serverctrls[state->nserverctrls] = page_control; @@ -1708,14 +1708,14 @@ static errno_t sdap_get_generic_ext_step(struct tevent_req *req) DEBUG(SSSDBG_MINOR_FAILURE, "ldap_search_ext failed: %s\n", sss_ldap_err2string(lret)); if (lret == LDAP_SERVER_DOWN) { - ret = ETIMEDOUT; + ret = ERR_SERVER_FAILURE; sss_ldap_error_debug(SSSDBG_MINOR_FAILURE, "Connection error", state->sh->ldap, lret); sss_log(SSS_LOG_ERR, "LDAP connection error"); } else if (lret == LDAP_FILTER_ERROR) { ret = ERR_INVALID_FILTER; } else { - ret = EIO; + ret = ERR_SERVER_FAILURE; } goto done; } @@ -2012,6 +2012,7 @@ static void generic_ext_search_handler(struct tevent_req *subreq, "sdap_get_generic_ext_recv failed: [%d]: %s " "[ldap_search_timeout]\n", ret, sss_strerror(ret)); + ret = ERR_SERVER_FAILURE; } else { DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_ext_recv request failed: [%d]: %s\n", @@ -2876,6 +2877,7 @@ static void sdap_sd_search_done(struct tevent_req *subreq) "sdap_get_generic_ext_recv request failed: [%d]: %s " "[ldap_network_timeout]\n", ret, sss_strerror(ret)); + ret = ERR_SERVER_FAILURE; } else { DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_ext_recv request failed: [%d]: %s\n", From d2edbc93ddb10c0726119b3d35607fb2045ce299 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Mon, 16 Mar 2026 15:25:49 -0400 Subject: [PATCH 18/39] dp: Reduce sssd.dataprovider methods to single return code The data provider handler methods now return a single output argument. Remove 'dp_error/dp_err' and 'error_message' usage across provider code. The getAccountDomain method still needs to return 'domain_name' string. Assisted by: Claude code (Sonnet 4.6) --- src/providers/ad/ad_dyndns.c | 11 +- src/providers/ad/ad_gpo.c | 33 +- src/providers/ad/ad_id.c | 55 +-- src/providers/ad/ad_id.h | 3 +- src/providers/ad/ad_pac.c | 8 +- src/providers/ad/ad_pac.h | 2 +- src/providers/ad/ad_refresh.c | 7 +- src/providers/ad/ad_resolver.c | 6 +- src/providers/ad/ad_subdomains.c | 44 +-- src/providers/backend.h | 2 +- src/providers/data_provider.h | 6 - src/providers/data_provider/dp_custom_data.h | 14 +- src/providers/data_provider/dp_iface.h | 31 +- src/providers/data_provider/dp_reply_std.c | 108 ++---- .../data_provider/dp_target_hostid.c | 6 +- src/providers/data_provider/dp_target_id.c | 16 +- .../data_provider/dp_target_resolver.c | 7 +- .../data_provider/dp_target_subdomains.c | 7 +- src/providers/data_provider/dp_target_sudo.c | 7 +- src/providers/data_provider_be.c | 22 +- src/providers/idp/idp_id.c | 43 +-- src/providers/idp/idp_online_check.c | 2 +- src/providers/ipa/ipa_access.c | 17 +- src/providers/ipa/ipa_auth.c | 15 +- src/providers/ipa/ipa_dyndns.c | 11 +- src/providers/ipa/ipa_id.c | 132 ++----- src/providers/ipa/ipa_id.h | 15 +- src/providers/ipa/ipa_refresh.c | 7 +- src/providers/ipa/ipa_s2n_exop.c | 10 +- src/providers/ipa/ipa_selinux.c | 5 +- src/providers/ipa/ipa_session.c | 15 +- src/providers/ipa/ipa_subdomains.c | 19 +- src/providers/ipa/ipa_subdomains.h | 2 +- src/providers/ipa/ipa_subdomains_ext_groups.c | 52 +-- src/providers/ipa/ipa_subdomains_id.c | 114 ++---- src/providers/ipa/ipa_sudo.c | 12 +- src/providers/ipa/ipa_sudo.h | 5 +- src/providers/ipa/ipa_sudo_async.c | 17 +- src/providers/ipa/ipa_sudo_refresh.c | 45 +-- src/providers/ipa/ipa_views.c | 18 +- src/providers/krb5/krb5_auth.c | 42 +-- src/providers/krb5/krb5_auth.h | 5 +- .../krb5/krb5_delayed_online_authentication.c | 3 +- src/providers/krb5/krb5_renew_tgt.c | 3 +- src/providers/krb5/krb5_wait_queue.c | 21 +- src/providers/ldap/ldap_common.h | 12 +- src/providers/ldap/ldap_id.c | 122 ++----- src/providers/ldap/ldap_id_netgroup.c | 22 +- src/providers/ldap/ldap_id_services.c | 22 +- src/providers/ldap/ldap_id_subid.c | 32 +- src/providers/ldap/sdap_access.c | 63 +--- src/providers/ldap/sdap_async_autofs.c | 43 +-- src/providers/ldap/sdap_async_enum.c | 46 +-- src/providers/ldap/sdap_async_groups.c | 3 +- src/providers/ldap/sdap_async_initgroups.c | 5 +- src/providers/ldap/sdap_async_initgroups_ad.c | 25 +- src/providers/ldap/sdap_async_resolver_enum.c | 25 +- src/providers/ldap/sdap_async_sudo.c | 18 +- src/providers/ldap/sdap_autofs.c | 35 +- src/providers/ldap/sdap_autofs.h | 6 +- src/providers/ldap/sdap_dyndns.c | 15 +- src/providers/ldap/sdap_hostid.c | 31 +- src/providers/ldap/sdap_id_op.c | 61 ++-- src/providers/ldap/sdap_id_op.h | 18 +- src/providers/ldap/sdap_iphost.c | 31 +- src/providers/ldap/sdap_ipnetwork.c | 31 +- src/providers/ldap/sdap_online_check.c | 6 +- src/providers/ldap/sdap_refresh.c | 8 +- src/providers/ldap/sdap_sudo.c | 12 +- src/providers/ldap/sdap_sudo.h | 8 +- src/providers/ldap/sdap_sudo_refresh.c | 43 +-- src/providers/minimal/minimal_id.c | 14 +- src/providers/proxy/proxy_hosts.c | 6 +- src/providers/proxy/proxy_id.c | 34 +- src/providers/proxy/proxy_ipnetworks.c | 6 +- src/providers/simple/simple_access_check.c | 6 +- .../common/cache_req/cache_req_private.h | 4 +- .../cache_req/plugins/cache_req_common.c | 20 +- .../plugins/cache_req_enum_ip_hosts.c | 10 +- .../plugins/cache_req_enum_ip_networks.c | 10 +- .../plugins/cache_req_ip_host_by_addr.c | 10 +- .../plugins/cache_req_ip_host_by_name.c | 10 +- .../plugins/cache_req_ip_network_by_addr.c | 10 +- .../plugins/cache_req_ip_network_by_name.c | 10 +- .../plugins/cache_req_ssh_host_id_by_name.c | 11 +- src/responder/common/responder.h | 8 +- src/responder/common/responder_dp.c | 25 +- src/responder/common/responder_get_domains.c | 28 +- src/responder/sudo/sudosrv_dp.c | 12 +- src/responder/sudo/sudosrv_get_sudorules.c | 24 +- src/responder/sudo/sudosrv_private.h | 4 +- src/sss_iface/sbus_sss_arguments.c | 88 +++-- src/sss_iface/sbus_sss_arguments.h | 33 +- src/sss_iface/sbus_sss_client_async.c | 329 ++++++++---------- src/sss_iface/sbus_sss_client_async.h | 36 +- src/sss_iface/sbus_sss_interface.h | 48 +-- src/sss_iface/sbus_sss_invokers.c | 290 +++++++-------- src/sss_iface/sbus_sss_invokers.h | 12 +- src/sss_iface/sbus_sss_symbols.c | 11 - src/sss_iface/sss_iface.xml | 11 - src/tests/cmocka/common_mock_resp.h | 5 +- src/tests/cmocka/common_mock_resp_dp.c | 34 +- src/tests/cmocka/test_krb5_wait_queue.c | 26 +- src/tests/cmocka/test_nss_srv.c | 16 +- src/tests/cmocka/test_pam_srv.c | 4 +- 105 files changed, 971 insertions(+), 2002 deletions(-) diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c index c3686069e38..2c0653fd737 100644 --- a/src/providers/ad/ad_dyndns.c +++ b/src/providers/ad/ad_dyndns.c @@ -180,7 +180,6 @@ ad_dyndns_update_send(TALLOC_CTX *mem_ctx, static void ad_dyndns_update_connect_done(struct tevent_req *subreq) { - int dp_error; int ret; struct tevent_req *req; struct ad_dyndns_update_state *state; @@ -191,11 +190,14 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_dyndns_update_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); + ctx = state->ad_ctx; + sdap_ctx = ctx->id_ctx->sdap_id_ctx; + if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(sdap_ctx->be)) { DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " "dynamic DNS update is skipped in offline mode.\n"); tevent_req_error(req, ERR_DYNDNS_OFFLINE); @@ -208,9 +210,6 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq) return; } - ctx = state->ad_ctx; - sdap_ctx = ctx->id_ctx->sdap_id_ctx; - ret = ldap_url_parse(ctx->service->sdap->uri, &lud); if (ret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse ldap URI '%s': %d\n", diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index e2eeb2692be..1aa6568c4ac 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -2135,7 +2135,6 @@ ad_gpo_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct ad_gpo_access_state *state; - int dp_error; errno_t ret; char *server_uri; LDAPURLDesc *lud; @@ -2145,11 +2144,11 @@ ad_gpo_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error != DP_ERR_OFFLINE) { + if (!be_is_offline(state->conn->id_ctx->be)) { DEBUG(SSSDBG_OP_FAILURE, "Failed to connect to AD server: [%d](%s)\n", ret, sss_strerror(ret)); @@ -2282,7 +2281,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_gpo_access_state *state; int ret; - int dp_error; const char *target_dn = NULL; uint32_t uac; static const char *host_attrs[] = { SYSDB_ORIG_DN, SYSDB_AD_USER_ACCOUNT_CONTROL, SYSDB_SID_STR, NULL }; @@ -2292,10 +2290,10 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); - ret = groups_by_user_recv(subreq, &dp_error); + ret = groups_by_user_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (ret == EAGAIN && dp_error == DP_ERR_OFFLINE) { + if (ret == EAGAIN) { DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); ret = process_offline_gpos(state, state->user, @@ -2481,7 +2479,6 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_gpo_access_state *state; int ret; - int dp_error; struct gp_gpo **candidate_gpos = NULL; int num_candidate_gpos = 0; int i = 0; @@ -2493,7 +2490,7 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, @@ -3367,7 +3364,6 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_gpo_process_som_state *state; int ret; - int dp_error; int i = 0; size_t reply_count; struct sysdb_attrs **reply; @@ -3380,7 +3376,7 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq) &reply_count, &reply); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); DEBUG(SSSDBG_OP_FAILURE, "Unable to get configNC: [%d](%s)\n", ret, sss_strerror(ret)); @@ -3493,7 +3489,6 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_gpo_process_som_state *state; int ret; - int dp_error; size_t num_results; struct sysdb_attrs **results; struct ldb_message_element *el = NULL; @@ -3509,7 +3504,7 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); DEBUG(SSSDBG_OP_FAILURE, "Unable to get SOM attributes: [%d](%s)\n", @@ -4216,7 +4211,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_gpo_process_gpo_state *state; int ret; - int dp_error; size_t num_results, refcount; struct sysdb_attrs **results; char **refs; @@ -4230,7 +4224,7 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); DEBUG(SSSDBG_OP_FAILURE, "Unable to get GPO attributes: [%d](%s)\n", @@ -4290,7 +4284,6 @@ void ad_gpo_get_sd_referral_done(struct tevent_req *subreq) { errno_t ret; - int dp_error; struct sysdb_attrs *reply; char *smb_host; @@ -4303,7 +4296,7 @@ ad_gpo_get_sd_referral_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { /* Terminate the sdap_id_op */ - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); DEBUG(SSSDBG_OP_FAILURE, "Unable to get referred GPO attributes: [%d](%s)\n", @@ -5025,7 +5018,6 @@ static void ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq) { errno_t ret; - int dp_error; const char *attrs[] = AD_GPO_ATTRS; LDAPURLDesc *lud = NULL; @@ -5034,10 +5026,10 @@ ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq) struct ad_gpo_get_sd_referral_state *state = tevent_req_data(req, struct ad_gpo_get_sd_referral_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->conn->id_ctx->be)) { DEBUG(SSSDBG_TRACE_FUNC, "Backend is marked offline, retry later!\n"); tevent_req_done(req); @@ -5091,7 +5083,6 @@ static void ad_gpo_get_sd_referral_search_done(struct tevent_req *subreq) { errno_t ret; - int dp_error; size_t num_results, num_refs; struct sysdb_attrs **results = NULL; char **refs; @@ -5105,7 +5096,7 @@ ad_gpo_get_sd_referral_search_done(struct tevent_req *subreq) &num_refs, &refs); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->ref_op, ret, &dp_error); + ret = sdap_id_op_done(state->ref_op, ret); DEBUG(SSSDBG_OP_FAILURE, "Unable to get GPO attributes: [%d](%s)\n", diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 272aea0ad74..f20a8af9a62 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -111,7 +111,6 @@ struct ad_handle_acct_info_state { struct ad_options *ad_options; bool using_pac; - int dp_error; const char *err; }; @@ -240,7 +239,6 @@ static void ad_handle_acct_info_done(struct tevent_req *subreq) { errno_t ret; - int dp_error; const char *err; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); @@ -248,11 +246,11 @@ ad_handle_acct_info_done(struct tevent_req *subreq) struct ad_handle_acct_info_state); if (state->using_pac) { - ret = ad_handle_pac_initgr_recv(subreq, &dp_error, &err); + ret = ad_handle_pac_initgr_recv(subreq, &err); } else { - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err); + ret = sdap_handle_acct_req_recv(subreq, &err); } - if (dp_error == DP_ERR_OFFLINE + if (ret == ERR_OFFLINE && state->conn[state->cindex+1] != NULL && state->conn[state->cindex]->ignore_mark_offline) { /* This is a special case: GC does not work. @@ -262,8 +260,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq) } talloc_zfree(subreq); if (ret != EOK) { - /* if GC was not used dp error should be set */ - state->dp_error = dp_error; + /* if GC was not used error should be set */ state->err = err; goto fail; @@ -284,7 +281,6 @@ ad_handle_acct_info_done(struct tevent_req *subreq) /* No additional search in progress. Save the last * error status, we'll be returning it. */ - state->dp_error = dp_error; state->err = err; if (ret == EOK) { @@ -316,15 +312,11 @@ ad_handle_acct_info_done(struct tevent_req *subreq) errno_t ad_handle_acct_info_recv(struct tevent_req *req, - int *_dp_error, const char **_err) + const char **_err) { struct ad_handle_acct_info_state *state = tevent_req_data(req, struct ad_handle_acct_info_state); - if (_dp_error) { - *_dp_error = state->dp_error; - } - if (_err) { *_err = state->err; } @@ -360,7 +352,6 @@ get_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, struct ad_account_info_state { const char *err_msg; - int dp_error; }; static void ad_account_info_done(struct tevent_req *subreq); @@ -439,7 +430,7 @@ static void ad_account_info_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_account_info_state); - ret = ad_handle_acct_info_recv(subreq, &state->dp_error, &state->err_msg); + ret = ad_handle_acct_info_recv(subreq, &state->err_msg); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ad_handle_acct_info_recv failed [%d]: %s\n", @@ -451,7 +442,6 @@ static void ad_account_info_done(struct tevent_req *subreq) } errno_t ad_account_info_recv(struct tevent_req *req, - int *_dp_error, const char **_err_msg) { struct ad_account_info_state *state = NULL; @@ -462,11 +452,6 @@ errno_t ad_account_info_recv(struct tevent_req *req, *_err_msg = state->err_msg; } - if (_dp_error) { - *_dp_error = state->dp_error; - } - - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -515,7 +500,7 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -529,17 +514,16 @@ static void ad_account_info_handler_done(struct tevent_req *subreq) struct ad_account_info_handler_state *state; struct tevent_req *req; const char *err_msg; - int dp_error = DP_ERR_FATAL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_account_info_handler_state); - ret = ad_account_info_recv(subreq, &dp_error, &err_msg); + ret = ad_account_info_recv(subreq, &err_msg); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, err_msg); + dp_reply_std_set(&state->reply, ret, err_msg); tevent_req_done(req); } @@ -581,7 +565,6 @@ struct ad_get_account_domain_state { const char *base_filter; char *filter; const char **attrs; - int dp_error; struct dp_reply_std reply; struct sdap_id_op *op; struct sysdb_attrs **objects; @@ -635,11 +618,11 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx, if (domain == NULL) { DEBUG(SSSDBG_TRACE_INTERNAL, "SID %s does not fit into any domain\n", data->filter_value); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL); + dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL); } else { DEBUG(SSSDBG_TRACE_INTERNAL, "SID %s fits into domain %s\n", data->filter_value, domain->name); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, domain->name); + dp_reply_std_set(&state->reply, EOK, domain->name); } tevent_req_done(req); tevent_req_post(req, params->ev); @@ -711,7 +694,7 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -793,16 +776,12 @@ static void ad_get_account_domain_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct ad_get_account_domain_state *state = tevent_req_data(req, - struct ad_get_account_domain_state); - int dp_error = DP_ERR_FATAL; errno_t ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -929,7 +908,7 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req) } DEBUG(SSSDBG_TRACE_FUNC, "Not found\n"); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL); + dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL); tevent_req_done(req); return; } else if (state->count > 1) { @@ -939,7 +918,7 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req) * from the responder side */ DEBUG(SSSDBG_OP_FAILURE, "Multiple entries found, error!\n"); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERANGE, NULL); + dp_reply_std_set(&state->reply, ERANGE, NULL); tevent_req_done(req); return; } @@ -951,14 +930,14 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req) if (obj_dom == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Could not match entry with domain!\n"); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL); + dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL); tevent_req_done(req); return; } DEBUG(SSSDBG_TRACE_INTERNAL, "Found object in domain %s\n", obj_dom->name); - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, obj_dom->name); + dp_reply_std_set(&state->reply, EOK, obj_dom->name); tevent_req_done(req); } diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h index 664361e3f06..dede0eddfc2 100644 --- a/src/providers/ad/ad_id.h +++ b/src/providers/ad/ad_id.h @@ -40,7 +40,6 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, struct dp_id_data *data); errno_t ad_account_info_recv(struct tevent_req *req, - int *_dp_error, const char **_err_msg); struct tevent_req * @@ -52,7 +51,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, struct sdap_id_conn_ctx **conn); errno_t ad_handle_acct_info_recv(struct tevent_req *req, - int *_dp_error, const char **_err); + const char **_err); struct tevent_req * ad_get_account_domain_send(TALLOC_CTX *mem_ctx, diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c index e5642f5a1d1..41d5d0145b7 100644 --- a/src/providers/ad/ad_pac.c +++ b/src/providers/ad/ad_pac.c @@ -275,7 +275,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, * sdap_handle_acct_req_recv() from the alternative group-membership * lookup path. */ state->err = NULL; - state->dp_error = DP_ERR_OK; + state->dp_error = EOK; ret = ad_get_pac_data_from_user_entry(state, msg, id_ctx->opts->idmap_ctx->map, @@ -431,16 +431,12 @@ static void ad_handle_pac_initgr_lookup_sids_done(struct tevent_req *subreq) } errno_t ad_handle_pac_initgr_recv(struct tevent_req *req, - int *_dp_error, const char **_err) + const char **_err) { struct ad_handle_pac_initgr_state *state; state = tevent_req_data(req, struct ad_handle_pac_initgr_state); - if (_dp_error) { - *_dp_error = state->dp_error; - } - if (_err) { *_err = state->err; } diff --git a/src/providers/ad/ad_pac.h b/src/providers/ad/ad_pac.h index 93f31ceda5b..e7657b0219e 100644 --- a/src/providers/ad/ad_pac.h +++ b/src/providers/ad/ad_pac.h @@ -77,7 +77,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct ldb_message *msg); errno_t ad_handle_pac_initgr_recv(struct tevent_req *req, - int *_dp_error, const char **_err); + const char **_err); errno_t check_upn_and_sid_from_user_and_pac(struct ldb_message *msg, struct sss_idmap_ctx *ctx, diff --git a/src/providers/ad/ad_refresh.c b/src/providers/ad/ad_refresh.c index 7aa56f33edc..9b4d93dbce7 100644 --- a/src/providers/ad/ad_refresh.c +++ b/src/providers/ad/ad_refresh.c @@ -154,18 +154,17 @@ static void ad_refresh_done(struct tevent_req *subreq) struct ad_refresh_state *state = NULL; struct tevent_req *req = NULL; const char *err_msg = NULL; - errno_t dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_refresh_state); - ret = ad_account_info_recv(subreq, &dp_error, &err_msg); + ret = ad_account_info_recv(subreq, &err_msg); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, " + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s, " "errno: %d]: %s\n", be_req2str(state->account_req->entry_type), - dp_error, ret, err_msg); + ret, err_msg); goto done; } diff --git a/src/providers/ad/ad_resolver.c b/src/providers/ad/ad_resolver.c index 0ce4e2a6496..5b7a53e99be 100644 --- a/src/providers/ad/ad_resolver.c +++ b/src/providers/ad/ad_resolver.c @@ -303,12 +303,12 @@ ad_resolver_enumeration_conn_done(struct tevent_req *subreq) struct ad_resolver_enum_state *state = tevent_req_data(req, struct ad_resolver_enum_state); struct sdap_id_ctx *id_ctx = state->resolver_ctx->ad_id_ctx->sdap_id_ctx; - int ret, dp_error; + int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(id_ctx->be)) { DEBUG(SSSDBG_TRACE_FUNC, "Backend is marked offline, retry later!\n"); tevent_req_done(req); diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index 002346f55da..2c255bb6671 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -1191,7 +1191,6 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq) { struct ad_get_slave_domain_state *state; struct tevent_req *req = NULL; - int dp_error; errno_t ret; const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER, AD_AT_SID, AD_AT_DOMAIN_NAME, @@ -1200,17 +1199,12 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_get_slave_domain_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " "[%d]: %s\n", ret, sss_strerror(ret)); - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, " - "cannot get the subdomain list while offline\n"); - ret = ERR_OFFLINE; - } tevent_req_error(req, ret); return; } @@ -1238,7 +1232,6 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq) struct sysdb_attrs **subdoms; size_t nsubdoms; bool has_changes; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); @@ -1252,17 +1245,14 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq) /* We continue to finish sdap_id_op. */ } - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = ad_get_slave_domain_retry(req); if (ret != EOK) { goto done; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - ret = ERR_OFFLINE; - goto done; } else if (ret != EOK) { goto done; } @@ -2034,23 +2024,17 @@ static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq) { struct ad_subdomains_refresh_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_subdomains_refresh_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " "[%d]: %s\n", ret, sss_strerror(ret)); - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, " - "cannot get the subdomain list while offline\n"); - ret = ERR_OFFLINE; - } tevent_req_error(req, ret); return; } @@ -2262,7 +2246,6 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_id_ctx *root_id_ctx; struct sysdb_attrs *root_attrs; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); @@ -2283,17 +2266,14 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq) /* We finish sdap_id_op here since we connect * to forest root for slave domains. */ - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = ad_subdomains_refresh_retry(req); if (ret != EOK) { tevent_req_error(req, ret); } return; - } else if (dp_error == DP_ERR_OFFLINE) { - tevent_req_error(req, ERR_OFFLINE); - return; } else if (ret != EOK) { tevent_req_error(req, ret); return; @@ -2385,7 +2365,7 @@ ad_subdomains_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -2407,7 +2387,7 @@ static void ad_subdomains_handler_done(struct tevent_req *subreq) talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } @@ -2671,22 +2651,16 @@ static void ad_check_domain_connect_done(struct tevent_req *subreq) struct tevent_req *req; struct ad_check_domain_state *state; int ret; - int dp_error; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_check_domain_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " "[%d]: %s\n", ret, sss_strerror(ret)); - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, " - "cannot get the subdomain list while offline\n"); - ret = ERR_OFFLINE; - } tevent_req_error(req, ret); return; } diff --git a/src/providers/backend.h b/src/providers/backend.h index fc13942bcbc..618e865ab06 100644 --- a/src/providers/backend.h +++ b/src/providers/backend.h @@ -114,7 +114,7 @@ struct be_ctx { struct sbus_connection *conn; /* Indicates whether the last state of the DP that has been logged is - * DP_ERR_OK or DP_ERR_OFFLINE. The only usage of this var, so far, is + * EOK or ERR_OFFLINE. The only usage of this var, so far, is * to log the DP status without spamming the syslog/journal. */ int last_dp_state; diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index 7509fb9566a..89aad995207 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -110,12 +110,6 @@ * @} */ /* end of group pamHandler */ -#define DP_ERR_DECIDE -1 -#define DP_ERR_OK 0 -#define DP_ERR_OFFLINE 1 -#define DP_ERR_TIMEOUT 2 -#define DP_ERR_FATAL 3 - #define BE_FILTER_NAME 1 #define BE_FILTER_IDNUM 2 #define BE_FILTER_ENUM 3 diff --git a/src/providers/data_provider/dp_custom_data.h b/src/providers/data_provider/dp_custom_data.h index 1ca85f70632..407f3e85468 100644 --- a/src/providers/data_provider/dp_custom_data.h +++ b/src/providers/data_provider/dp_custom_data.h @@ -66,23 +66,21 @@ struct dp_resolver_data { /* Reply private data. */ struct dp_reply_std { - int dp_error; int error; const char *message; }; void dp_reply_std_set(struct dp_reply_std *reply, - int dp_error, int error, const char *msg); +void dp_req_reply_std_with_msg(const char *request_name, + struct dp_reply_std *reply, + uint32_t *_error, + const char **_message); + void dp_req_reply_std(const char *request_name, struct dp_reply_std *reply, - uint16_t *_dp_error, - uint32_t *_error, - const char **_message); - -/* Convert pair of ret and dp_error to single ret value. */ -errno_t dp_error_to_ret(errno_t ret, int dp_error); + uint32_t *_error); #endif /* _DP_CUSTOM_DATA_H_ */ diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h index 87e0687045f..c2fc2a0c8dd 100644 --- a/src/providers/data_provider/dp_iface.h +++ b/src/providers/data_provider/dp_iface.h @@ -40,9 +40,7 @@ dp_get_account_info_send(TALLOC_CTX *mem_ctx, errno_t dp_get_account_info_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); struct tevent_req * dp_pam_handler_send(TALLOC_CTX *mem_ctx, @@ -66,9 +64,7 @@ dp_sudo_handler_send(TALLOC_CTX *mem_ctx, errno_t dp_sudo_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); struct tevent_req * dp_host_handler_send(TALLOC_CTX *mem_ctx, @@ -83,9 +79,7 @@ dp_host_handler_send(TALLOC_CTX *mem_ctx, errno_t dp_host_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); struct tevent_req * dp_autofs_handler_send(TALLOC_CTX *mem_ctx, @@ -98,9 +92,7 @@ dp_autofs_handler_send(TALLOC_CTX *mem_ctx, errno_t dp_autofs_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); struct tevent_req * dp_autofs_get_map_send(TALLOC_CTX *mem_ctx, @@ -146,9 +138,7 @@ dp_subdomains_handler_send(TALLOC_CTX *mem_ctx, errno_t dp_subdomains_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); struct tevent_req * dp_resolver_handler_send(TALLOC_CTX *mem_ctx, @@ -164,20 +154,18 @@ dp_resolver_handler_send(TALLOC_CTX *mem_ctx, errno_t dp_resolver_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg); + uint32_t *_error); /* * Return a domain the account belongs to. * * The request uses the dp_reply_std structure for reply, with the following * semantics: - * - DP_ERR_OK - it is expected that the string message contains the domain name + * - ERR_OK - it is expected that the string message contains the domain name * the entry was found in. A 'negative' reply where the - * request returns DP_ERR_OK, but no domain should be treated + * request returns ERR_OK, but no domain should be treated * as authoritative, as if the entry does not exist. - * - DP_ERR_* - the string message contains error string that corresponds + * - ERR_* - the string message contains error string that corresponds * to the errno field in dp_reply_std(). */ struct tevent_req * @@ -193,7 +181,6 @@ dp_get_account_domain_send(TALLOC_CTX *mem_ctx, errno_t dp_get_account_domain_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, uint32_t *_error, const char **_err_msg); diff --git a/src/providers/data_provider/dp_reply_std.c b/src/providers/data_provider/dp_reply_std.c index 74e8e044e19..201f6547048 100644 --- a/src/providers/data_provider/dp_reply_std.c +++ b/src/providers/data_provider/dp_reply_std.c @@ -25,32 +25,17 @@ #include "util/sss_utf8.h" #include "util/util.h" -static const char *dp_err_to_string(int dp_err_type) -{ - switch (dp_err_type) { - case DP_ERR_OK: - return "Success"; - case DP_ERR_OFFLINE: - return "Provider is Offline"; - case DP_ERR_TIMEOUT: - return "Request timed out"; - case DP_ERR_FATAL: - return "Internal Error"; - default: - break; - } - - return "Unknown Error"; -} - static const char *safe_be_req_err_msg(const char *msg_in, - int dp_err_type) + int error) { bool ok; + const char *def_msg; + + def_msg = sss_strerror(error); if (msg_in == NULL) { /* No custom error, just use default */ - return dp_err_to_string(dp_err_type); + return def_msg; } ok = sss_utf8_check((const uint8_t *) msg_in, @@ -59,7 +44,7 @@ static const char *safe_be_req_err_msg(const char *msg_in, DEBUG(SSSDBG_MINOR_FAILURE, "Back end message [%s] contains invalid non-UTF8 character, " \ "using default\n", msg_in); - return dp_err_to_string(dp_err_type); + return def_msg; } return msg_in; @@ -67,84 +52,43 @@ static const char *safe_be_req_err_msg(const char *msg_in, void dp_req_reply_std(const char *request_name, struct dp_reply_std *reply, - uint16_t *_dp_error, - uint32_t *_error, - const char **_message) + uint32_t *_error) +{ + const char *msg; + + msg = sss_strerror(*_error); + + DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%d]: %s", + *_error, msg); + + *_error = reply->error; + msg = reply->message; +} + +void dp_req_reply_std_with_msg(const char *request_name, + struct dp_reply_std *reply, + uint32_t *_error, + const char **_message) { const char *safe_err_msg; - safe_err_msg = safe_be_req_err_msg(reply->message, reply->dp_error); + safe_err_msg = safe_be_req_err_msg(reply->message, reply->error); - DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%s]: %d,%d,%s", - dp_err_to_string(reply->dp_error), reply->dp_error, + DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%d]: %s", reply->error, reply->message); - *_dp_error = reply->dp_error; *_error = reply->error; *_message = safe_err_msg; } void dp_reply_std_set(struct dp_reply_std *reply, - int dp_error, int error, const char *msg) { const char *def_msg; - if (dp_error == DP_ERR_DECIDE) { - switch (error) { - case EOK: - dp_error = DP_ERR_OK; - break; - case ERR_OFFLINE: - dp_error = DP_ERR_OFFLINE; - break; - case ETIMEDOUT: - dp_error = DP_ERR_TIMEOUT; - break; - default: - dp_error = DP_ERR_FATAL; - break; - } - } - - switch (dp_error) { - case DP_ERR_OK: - def_msg = "Success"; - break; - case DP_ERR_OFFLINE: - def_msg = "Offline"; - break; - default: - def_msg = sss_strerror(error); - break; - } + def_msg = sss_strerror(error); - if (dp_error == DP_ERR_OK && error != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "DP Error is OK on failed request?\n"); - } - - reply->dp_error = dp_error; reply->error = error; reply->message = msg == NULL ? def_msg : msg; } - -errno_t dp_error_to_ret(errno_t ret, int dp_error) -{ - if (ret != EOK) { - return ret; - } - - switch (dp_error) { - case DP_ERR_OK: - return EOK; - case DP_ERR_OFFLINE: - return ERR_OFFLINE; - case DP_ERR_TIMEOUT: - return ETIMEDOUT; - case DP_ERR_FATAL: - return EFAULT; - } - - return ERR_INTERNAL; -} diff --git a/src/providers/data_provider/dp_target_hostid.c b/src/providers/data_provider/dp_target_hostid.c index ea8f29014bc..f7441e06c32 100644 --- a/src/providers/data_provider/dp_target_hostid.c +++ b/src/providers/data_provider/dp_target_hostid.c @@ -110,9 +110,7 @@ static void dp_host_handler_done(struct tevent_req *subreq) errno_t dp_host_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg) + uint32_t *_error) { struct dp_host_handler_state *state; state = tevent_req_data(req, struct dp_host_handler_state); @@ -120,7 +118,7 @@ dp_host_handler_recv(TALLOC_CTX *mem_ctx, TEVENT_REQ_RETURN_ON_ERROR(req); dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + _error); return EOK; } diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c index 1d305e7cda2..2db27c76191 100644 --- a/src/providers/data_provider/dp_target_id.c +++ b/src/providers/data_provider/dp_target_id.c @@ -434,7 +434,7 @@ static void dp_req_initgr_pp_set_initgr_timestamp(struct dp_initgr_ctx *ctx, { errno_t ret; - if (reply->dp_error != DP_ERR_OK || reply->error != EOK) { + if (reply->error != EOK) { /* Only bump the timestamp on successful lookups */ return; } @@ -887,17 +887,14 @@ static void dp_get_account_info_done(struct tevent_req *subreq) errno_t dp_get_account_info_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg) + uint32_t *_error) { struct dp_get_account_info_state *state; state = tevent_req_data(req, struct dp_get_account_info_state); TEVENT_REQ_RETURN_ON_ERROR(req); - dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + dp_req_reply_std(state->request_name, &state->reply, _error); return EOK; } @@ -1025,7 +1022,6 @@ static void dp_get_account_domain_done(struct tevent_req *subreq) errno_t dp_get_account_domain_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, uint32_t *_error, const char **_err_msg) { @@ -1034,8 +1030,8 @@ dp_get_account_domain_recv(TALLOC_CTX *mem_ctx, TEVENT_REQ_RETURN_ON_ERROR(req); - dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + dp_req_reply_std_with_msg(state->request_name, &state->reply, _error, + _err_msg); return EOK; } @@ -1061,7 +1057,7 @@ default_account_domain_send(TALLOC_CTX *mem_ctx, } dp_reply_std_set(&state->reply, - DP_ERR_DECIDE, ERR_GET_ACCT_DOM_NOT_SUPPORTED, + ERR_GET_ACCT_DOM_NOT_SUPPORTED, NULL); tevent_req_done(req); tevent_req_post(req, params->ev); diff --git a/src/providers/data_provider/dp_target_resolver.c b/src/providers/data_provider/dp_target_resolver.c index 7dd24d3119c..6f759efdc98 100644 --- a/src/providers/data_provider/dp_target_resolver.c +++ b/src/providers/data_provider/dp_target_resolver.c @@ -132,17 +132,14 @@ static void dp_resolver_handler_done(struct tevent_req *subreq) errno_t dp_resolver_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg) + uint32_t *_error) { struct dp_resolver_handler_state *state; state = tevent_req_data(req, struct dp_resolver_handler_state); TEVENT_REQ_RETURN_ON_ERROR(req); - dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + dp_req_reply_std(state->request_name, &state->reply, _error); return EOK; } diff --git a/src/providers/data_provider/dp_target_subdomains.c b/src/providers/data_provider/dp_target_subdomains.c index e405d8c9a05..6411311e2af 100644 --- a/src/providers/data_provider/dp_target_subdomains.c +++ b/src/providers/data_provider/dp_target_subdomains.c @@ -106,17 +106,14 @@ static void dp_subdomains_handler_done(struct tevent_req *subreq) errno_t dp_subdomains_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg) + uint32_t *_error) { struct dp_subdomains_handler_state *state; state = tevent_req_data(req, struct dp_subdomains_handler_state); TEVENT_REQ_RETURN_ON_ERROR(req); - dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + dp_req_reply_std(state->request_name, &state->reply, _error); return EOK; } diff --git a/src/providers/data_provider/dp_target_sudo.c b/src/providers/data_provider/dp_target_sudo.c index f90589f6677..dbf9a7f3301 100644 --- a/src/providers/data_provider/dp_target_sudo.c +++ b/src/providers/data_provider/dp_target_sudo.c @@ -189,17 +189,14 @@ static void dp_sudo_handler_done(struct tevent_req *subreq) errno_t dp_sudo_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_err_msg) + uint32_t *_error) { struct dp_sudo_handler_state *state; state = tevent_req_data(req, struct dp_sudo_handler_state); TEVENT_REQ_RETURN_ON_ERROR(req); - dp_req_reply_std(state->request_name, &state->reply, - _dp_error, _error, _err_msg); + dp_req_reply_std(state->request_name, &state->reply, _error); return EOK; } diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c index a01f83531c3..fc981b74044 100644 --- a/src/providers/data_provider_be.c +++ b/src/providers/data_provider_be.c @@ -343,30 +343,30 @@ static void be_check_online_done(struct tevent_req *req) goto done; } - switch (reply->dp_error) { - case DP_ERR_OK: - if (be_ctx->last_dp_state != DP_ERR_OK) { - be_ctx->last_dp_state = DP_ERR_OK; + switch (reply->error) { + case EOK: + if (be_ctx->last_dp_state != EOK) { + be_ctx->last_dp_state = EOK; sss_log(SSS_LOG_INFO, "Backend is online\n"); } DEBUG(SSSDBG_TRACE_FUNC, "Backend is online\n"); break; - case DP_ERR_OFFLINE: - if (be_ctx->last_dp_state != DP_ERR_OFFLINE) { - be_ctx->last_dp_state = DP_ERR_OFFLINE; + case ERR_OFFLINE: + if (be_ctx->last_dp_state != ERR_OFFLINE) { + be_ctx->last_dp_state = ERR_OFFLINE; sss_log(SSS_LOG_INFO, "Backend is offline\n"); } DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline\n"); break; default: DEBUG(SSSDBG_TRACE_FUNC, "Error during online check [%d]: %s\n", - ret, sss_strerror(ret)); + reply->error, sss_strerror(reply->error)); break; } be_ctx->check_online_ref_count--; - if (reply->dp_error != DP_ERR_OK && be_ctx->check_online_ref_count > 0) { + if (reply->error != EOK && be_ctx->check_online_ref_count > 0) { be_ctx->check_online_retry_delay *= 2; if (be_ctx->check_online_retry_delay > ONLINE_CB_RETRY_MAX_DELAY) { be_ctx->check_online_retry_delay = ONLINE_CB_RETRY_MAX_DELAY; @@ -390,8 +390,8 @@ static void be_check_online_done(struct tevent_req *req) done: be_ctx->check_online_ref_count = 0; - if (reply && reply->dp_error != DP_ERR_OFFLINE) { - if (reply->dp_error != DP_ERR_OK) { + if (reply && reply->error != ERR_OFFLINE) { + if (reply->error != EOK) { reset_fo(be_ctx); } be_reset_offline(be_ctx); diff --git a/src/providers/idp/idp_id.c b/src/providers/idp/idp_id.c index 8ad85fb9217..8de4d4f4b2f 100644 --- a/src/providers/idp/idp_id.c +++ b/src/providers/idp/idp_id.c @@ -162,7 +162,6 @@ struct idp_type_get_state { struct tevent_context *ev; struct idp_id_ctx *idp_id_ctx; struct idp_req *idp_req; - int dp_error; int idp_ret; enum idp_lookup_type lookup_type; const char *filter_value; @@ -202,7 +201,6 @@ static struct tevent_req *idp_type_get_send(TALLOC_CTX *memctx, state->ev = ev; state->idp_id_ctx = idp_id_ctx; - state->dp_error = DP_ERR_FATAL; state->idp_ret = ENODATA; state->lookup_type = lookup_type; state->filter_value = talloc_strdup(state, filter_value); @@ -295,7 +293,6 @@ static void idp_type_get_done(struct tevent_req *subreq) ret = handle_oidc_child_recv(subreq, state, &buf, &buflen); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -336,27 +333,21 @@ static void idp_type_get_done(struct tevent_req *subreq) if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to evaluate user data returned by oidc_child.\n"); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } -static int idp_type_get_recv(struct tevent_req *req, int *dp_error_out, +static int idp_type_get_recv(struct tevent_req *req, int *idp_ret) { struct idp_type_get_state *state; state = tevent_req_data(req, struct idp_type_get_state); - if (dp_error_out != NULL) { - *dp_error_out = state->dp_error; - } - if (idp_ret != NULL) { *idp_ret = state->idp_ret; } @@ -380,10 +371,10 @@ static struct tevent_req *idp_users_get_send(TALLOC_CTX *memctx, noexist_delete, false, set_non_posix); } -static int idp_users_get_recv(struct tevent_req *req, int *dp_error_out, +static int idp_users_get_recv(struct tevent_req *req, int *idp_ret) { - return idp_type_get_recv(req, dp_error_out, idp_ret); + return idp_type_get_recv(req, idp_ret); } static struct tevent_req *idp_groups_get_send(TALLOC_CTX *memctx, @@ -400,10 +391,10 @@ static struct tevent_req *idp_groups_get_send(TALLOC_CTX *memctx, no_members, set_non_posix); } -static int idp_groups_get_recv(struct tevent_req *req, int *dp_error_out, +static int idp_groups_get_recv(struct tevent_req *req, int *idp_ret) { - return idp_type_get_recv(req, dp_error_out, idp_ret); + return idp_type_get_recv(req, idp_ret); } static struct tevent_req *idp_groups_by_user_send(TALLOC_CTX *memctx, @@ -420,16 +411,15 @@ static struct tevent_req *idp_groups_by_user_send(TALLOC_CTX *memctx, false, set_non_posix); } -static int idp_groups_by_user_recv(struct tevent_req *req, int *dp_error_out, +static int idp_groups_by_user_recv(struct tevent_req *req, int *idp_ret) { - return idp_type_get_recv(req, dp_error_out, idp_ret); + return idp_type_get_recv(req, idp_ret); } struct idp_handle_acct_req_state { struct dp_id_data *ar; const char *err; - int dp_error; int idp_ret; }; @@ -536,15 +526,15 @@ static void idp_handle_acct_req_done(struct tevent_req *subreq) switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ err = "User lookup failed"; - ret = idp_users_get_recv(subreq, &state->dp_error, &state->idp_ret); + ret = idp_users_get_recv(subreq, &state->idp_ret); break; case BE_REQ_GROUP: /* group */ err = "Group lookup failed"; - ret = idp_groups_get_recv(subreq, &state->dp_error, &state->idp_ret); + ret = idp_groups_get_recv(subreq, &state->idp_ret); break; case BE_REQ_INITGROUPS: /* init groups for user */ err = "Init group lookup failed"; - ret = idp_groups_by_user_recv(subreq, &state->dp_error, &state->idp_ret); + ret = idp_groups_by_user_recv(subreq, &state->idp_ret); break; default: /* fail */ ret = EINVAL; @@ -564,17 +554,13 @@ static void idp_handle_acct_req_done(struct tevent_req *subreq) static errno_t idp_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err, + const char **_err, int *idp_ret) { struct idp_handle_acct_req_state *state; state = tevent_req_data(req, struct idp_handle_acct_req_state); - if (_dp_error) { - *_dp_error = state->dp_error; - } - if (_err) { *_err = state->err; } @@ -624,7 +610,7 @@ idp_account_info_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -638,17 +624,16 @@ static void idp_account_info_handler_done(struct tevent_req *subreq) struct idp_account_info_handler_state *state; struct tevent_req *req; const char *error_msg = NULL; - int dp_error = DP_ERR_FATAL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct idp_account_info_handler_state); - ret = idp_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL); + ret = idp_handle_acct_req_recv(subreq, &error_msg, NULL); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, error_msg); + dp_reply_std_set(&state->reply, ret, error_msg); tevent_req_done(req); } diff --git a/src/providers/idp/idp_online_check.c b/src/providers/idp/idp_online_check.c index 683ed949842..c9089335e32 100644 --- a/src/providers/idp/idp_online_check.c +++ b/src/providers/idp/idp_online_check.c @@ -49,7 +49,7 @@ idp_online_check_handler_send(TALLOC_CTX *mem_ctx, /* TODO: evaluate if proper online check is needed */ ret = ENOTSUP; - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index bfa82a8c9b1..a9855113af4 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -217,18 +217,19 @@ static errno_t ipa_fetch_hbac_retry(struct tevent_req *req) static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; - int dp_error; + struct ipa_fetch_hbac_state *state = NULL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_fetch_hbac_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { goto done; } - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->be_ctx)) { ret = EOK; goto done; } @@ -293,7 +294,6 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq) struct ipa_fetch_hbac_state *state = NULL; struct tevent_req *req = NULL; errno_t ret; - int dp_error; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_fetch_hbac_state); @@ -313,8 +313,8 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq) * so that all searches are in another sub-request so that we can * error out at any step and the parent request can call * sdap_id_op_done just once. */ - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = ipa_fetch_hbac_retry(req); if (ret != EAGAIN) { @@ -405,7 +405,6 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq) { struct ipa_fetch_hbac_state *state = NULL; struct tevent_req *req = NULL; - int dp_error; errno_t ret; bool found; @@ -427,8 +426,8 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq) goto done; } - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = ipa_fetch_hbac_retry(req); if (ret != EAGAIN) { diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 3bbee7d85a8..3399d82d448 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -101,12 +101,12 @@ static void get_password_migration_flag_auth_done(struct tevent_req *subreq) struct get_password_migration_flag_state *state = tevent_req_data(req, struct get_password_migration_flag_state); static const char *attrs[] = {IPA_CONFIG_MIGRATION_ENABLED, NULL}; - int ret, dp_error; + int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->sdap_id_ctx->be)) { DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, cannot get the " "migration flag while offline\n"); @@ -246,7 +246,6 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq) { struct ipa_pam_auth_handler_state *state; struct tevent_req *req; - int dp_err; char *realm; errno_t ret; @@ -254,7 +253,7 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq) state = tevent_req_data(req, struct ipa_pam_auth_handler_state); state->pd->pam_status = PAM_SYSTEM_ERR; - ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, &dp_err); + ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status); talloc_free(subreq); if (ret != EOK && state->pd->pam_status != PAM_CRED_ERR) { DEBUG(SSSDBG_OP_FAILURE, "KRB5 auth failed [%d]: %s\n", @@ -262,9 +261,6 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq) goto done; } - if (dp_err != DP_ERR_OK) { - goto done; - } if (state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM && state->pd->pam_status == PAM_TRY_AGAIN) { /* Reset this to fork a new krb5_child in handle_child_send() */ @@ -468,13 +464,12 @@ static void ipa_pam_auth_handler_retry_done(struct tevent_req *subreq) { struct ipa_pam_auth_handler_state *state; struct tevent_req *req; - int dp_err; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_pam_auth_handler_state); - ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, &dp_err); + ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status); talloc_free(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv request failed.\n"); diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index 371a64c2bd3..f3b34754a5c 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -155,7 +155,6 @@ ipa_dyndns_update_send(TALLOC_CTX *mem_ctx, static void ipa_dyndns_update_connect_done(struct tevent_req *subreq) { - int dp_error; int ret; struct ipa_options *ctx; struct tevent_req *req; @@ -165,11 +164,14 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_dyndns_update_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); + ctx = state->ipa_ctx; + sdap_ctx = ctx->id_ctx->sdap_id_ctx; + if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(sdap_ctx->be)) { DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " "dynamic DNS update is skipped in offline mode.\n"); tevent_req_error(req, ERR_DYNDNS_OFFLINE); @@ -182,9 +184,6 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) return; } - ctx = state->ipa_ctx; - sdap_ctx = ctx->id_ctx->sdap_id_ctx; - /* The following three checks are here to prevent SEGFAULT * from ticket #3076. */ if (ctx->service == NULL) { diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c index 4409fed72bf..e0eb236290b 100644 --- a/src/providers/ipa/ipa_id.c +++ b/src/providers/ipa/ipa_id.c @@ -59,8 +59,6 @@ struct ipa_resolve_user_list_state { struct sss_domain_info *domain; struct sss_domain_info *user_domain; size_t user_idx; - - int dp_error; }; static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req); @@ -90,13 +88,11 @@ ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev, state->domain_name, true); state->users = users; state->user_idx = 0; - state->dp_error = DP_ERR_FATAL; ret = ipa_resolve_user_list_get_user_step(req); if (ret == EAGAIN) { return req; } else if (ret == EOK) { - state->dp_error = DP_ERR_OK; tevent_req_done(req); } else { DEBUG(SSSDBG_OP_FAILURE, @@ -166,9 +162,9 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq) int ret; if (state->user_domain != state->ipa_ctx->sdap_id_ctx->be->domain) { - ret = ipa_subdomain_account_recv(subreq, &state->dp_error); + ret = ipa_subdomain_account_recv(subreq); } else { - ret = ipa_id_get_account_info_recv(subreq, &state->dp_error); + ret = ipa_id_get_account_info_recv(subreq); } talloc_zfree(subreq); if (ret != EOK) { @@ -189,26 +185,15 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq) done: if (ret == EOK) { - state->dp_error = DP_ERR_OK; tevent_req_done(req); } else { - if (state->dp_error == DP_ERR_OK) { - state->dp_error = DP_ERR_FATAL; - } tevent_req_error(req, ret); } return; } -int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error) +int ipa_resolve_user_list_recv(struct tevent_req *req) { - struct ipa_resolve_user_list_state *state = tevent_req_data(req, - struct ipa_resolve_user_list_state); - - if (dp_error) { - *dp_error = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -225,8 +210,6 @@ struct ipa_initgr_get_overrides_state { const char *groups_id_attr; size_t group_idx; struct dp_id_data *ar; - - int dp_error; }; static int ipa_initgr_get_overrides_step(struct tevent_req *req); @@ -361,7 +344,7 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq) int ret; struct sysdb_attrs *override_attrs = NULL; - ret = ipa_get_trusted_override_recv(subreq, &state->dp_error, state, + ret = ipa_get_trusted_override_recv(subreq, state, &override_attrs); talloc_zfree(subreq); if (ret != EOK) { @@ -421,15 +404,8 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq) tevent_req_done(req); } -int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error) +int ipa_initgr_get_overrides_recv(struct tevent_req *req) { - struct ipa_initgr_get_overrides_state *state = tevent_req_data(req, - struct ipa_initgr_get_overrides_state); - - if (dp_error) { - *dp_error = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -518,7 +494,6 @@ struct ipa_id_get_account_info_state { struct ldb_result *res; size_t res_index; - int dp_error; }; static void ipa_id_get_account_info_connected(struct tevent_req *subreq); @@ -549,7 +524,6 @@ ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; - state->dp_error = DP_ERR_FATAL; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); if (state->op == NULL) { @@ -616,10 +590,9 @@ static void ipa_id_get_account_info_connected(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n"); @@ -640,7 +613,6 @@ static void ipa_id_get_account_info_connected(struct tevent_req *subreq) return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -651,20 +623,19 @@ static void ipa_id_get_account_info_got_override(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; const char *anchor = NULL; char *anchor_domain; char *ipa_uuid; - ret = ipa_get_trusted_override_recv(subreq, &dp_error, state, + ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret == EAGAIN) { /* retry */ subreq = sdap_id_op_connect_send(state->op, state, &ret); if (subreq == NULL) { @@ -736,7 +707,6 @@ static void ipa_id_get_account_info_got_override(struct tevent_req *subreq) return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -770,7 +740,6 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, @@ -781,7 +750,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) SYSDB_HOMEDIR, NULL }; - ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL); + ret = sdap_handle_acct_req_recv(subreq, NULL); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret); @@ -790,8 +759,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) if (! is_object_overridable(state->ar)) { DEBUG(SSSDBG_FUNC_DATA, "Object not overridable, ending request\n"); - state->dp_error = DP_ERR_OK; - tevent_req_done(req); + tevent_req_done(req); return; } @@ -825,8 +793,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) &state->obj_msg); if (ret == ENOENT) { DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n"); - state->dp_error = DP_ERR_OK; - tevent_req_done(req); + tevent_req_done(req); return; } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n"); @@ -842,12 +809,10 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) goto fail; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -999,12 +964,11 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; const char *class; enum sysdb_member_type type; - ret = ipa_get_trusted_override_recv(subreq, &dp_error, state, + ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { @@ -1089,12 +1053,10 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1105,10 +1067,9 @@ static void ipa_id_get_user_list_done(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = ipa_resolve_user_list_recv(subreq, &dp_error); + ret = ipa_resolve_user_list_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user list %d\n", ret); @@ -1127,12 +1088,10 @@ static void ipa_id_get_user_list_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1143,10 +1102,9 @@ static void ipa_id_get_user_groups_done(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = ipa_initgr_get_overrides_recv(subreq, &dp_error); + ret = ipa_initgr_get_overrides_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user groups %d\n", ret); @@ -1165,25 +1123,16 @@ static void ipa_id_get_user_groups_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } -int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error) +int ipa_id_get_account_info_recv(struct tevent_req *req) { - struct ipa_id_get_account_info_state *state = tevent_req_data(req, - struct ipa_id_get_account_info_state); - - if (dp_error) { - *dp_error = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1207,8 +1156,6 @@ struct ipa_id_get_netgroup_state { size_t count; struct sysdb_attrs **netgroups; - - int dp_error; }; static void ipa_id_get_netgroup_connected(struct tevent_req *subreq); @@ -1233,7 +1180,6 @@ static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ipa_ctx; - state->dp_error = DP_ERR_FATAL; state->op = sdap_id_op_create(state, ctx->conn->conn_cache); if (!state->op) { @@ -1288,15 +1234,13 @@ static void ipa_id_get_netgroup_connected(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct ipa_id_get_netgroup_state *state = tevent_req_data(req, struct ipa_id_get_netgroup_state); - int dp_error = DP_ERR_FATAL; int ret; struct sdap_id_ctx *sdap_ctx = state->ctx->sdap_id_ctx; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1322,15 +1266,14 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct ipa_id_get_netgroup_state *state = tevent_req_data(req, struct ipa_id_get_netgroup_state); - int dp_error = DP_ERR_FATAL; int ret; ret = ipa_get_netgroups_recv(subreq, state, &state->count, &state->netgroups); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret == EAGAIN) { /* retry */ subreq = sdap_id_op_connect_send(state->op, state, &ret); if (!subreq) { @@ -1342,7 +1285,6 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1363,20 +1305,12 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } -static int ipa_id_get_netgroup_recv(struct tevent_req *req, int *dp_error) +static int ipa_id_get_netgroup_recv(struct tevent_req *req) { - struct ipa_id_get_netgroup_state *state = - tevent_req_data(req, struct ipa_id_get_netgroup_state); - - if (dp_error) { - *dp_error = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1404,7 +1338,6 @@ struct ipa_account_info_state { enum ipa_account_info_type type; const char *err_msg; - int dp_error; }; static void ipa_account_info_done(struct tevent_req *subreq); @@ -1472,13 +1405,13 @@ static void ipa_account_info_done(struct tevent_req *subreq) switch (state->type) { case IPA_ACCOUNT_INFO_SUBDOMAIN: - ret = ipa_subdomain_account_recv(subreq, &state->dp_error); + ret = ipa_subdomain_account_recv(subreq); break; case IPA_ACCOUNT_INFO_NETGROUP: - ret = ipa_id_get_netgroup_recv(subreq, &state->dp_error); + ret = ipa_id_get_netgroup_recv(subreq); break; case IPA_ACCOUNT_INFO_OTHER: - ret = ipa_id_get_account_info_recv(subreq, &state->dp_error); + ret = ipa_id_get_account_info_recv(subreq); break; default: ret = EINVAL; @@ -1494,18 +1427,8 @@ static void ipa_account_info_done(struct tevent_req *subreq) tevent_req_done(req); } -errno_t ipa_account_info_recv(struct tevent_req *req, - int *_dp_error) +errno_t ipa_account_info_recv(struct tevent_req *req) { - struct ipa_account_info_state *state = NULL; - - state = tevent_req_data(req, struct ipa_account_info_state); - - /* Fail the request after collecting the dp_error */ - if (_dp_error) { - *_dp_error = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -1550,7 +1473,7 @@ ipa_account_info_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -1563,17 +1486,16 @@ static void ipa_account_info_handler_done(struct tevent_req *subreq) { struct ipa_account_info_handler_state *state; struct tevent_req *req; - int dp_error; errno_t ret = ERR_INTERNAL; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_account_info_handler_state); - ret = ipa_account_info_recv(subreq, &dp_error); + ret = ipa_account_info_recv(subreq); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h index 2c641130293..9e22dae301c 100644 --- a/src/providers/ipa/ipa_id.h +++ b/src/providers/ipa/ipa_id.h @@ -38,8 +38,7 @@ ipa_account_info_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct dp_id_data *data); -errno_t ipa_account_info_recv(struct tevent_req *req, - int *_dp_error); +errno_t ipa_account_info_recv(struct tevent_req *req); struct tevent_req * ipa_account_info_handler_send(TALLOC_CTX *mem_ctx, @@ -83,7 +82,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, struct ipa_id_ctx *ipa_ctx, struct sysdb_attrs *override_attrs, struct dp_id_data *ar); -int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out); +int ipa_get_subdom_acct_recv(struct tevent_req *req); errno_t get_dp_id_data_for_sid(TALLOC_CTX *mem_ctx, const char *sid, const char *domain_name, @@ -106,7 +105,7 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, const char *view_name, struct dp_id_data *ar); -errno_t ipa_get_trusted_override_recv(struct tevent_req *req, int *dp_error_out, +errno_t ipa_get_trusted_override_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct sysdb_attrs **override_attrs); @@ -115,7 +114,7 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, struct ipa_id_ctx *ipa_ctx, struct dp_id_data *ar); -errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out); +errno_t ipa_subdomain_account_recv(struct tevent_req *req); errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor, char **_anchor_domain, char **_ipa_uuid); @@ -133,7 +132,7 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx, size_t groups_count, struct ldb_message **groups, const char *groups_id_attr); -int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error); +int ipa_initgr_get_overrides_recv(struct tevent_req *req); struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -149,11 +148,11 @@ ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_id_ctx *ipa_ctx, const char *domain_name, struct ldb_message_element *users); -int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error); +int ipa_resolve_user_list_recv(struct tevent_req *req); struct tevent_req * ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_id_ctx *ipa_ctx, struct dp_id_data *ar); -int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error); +int ipa_id_get_account_info_recv(struct tevent_req *req); #endif diff --git a/src/providers/ipa/ipa_refresh.c b/src/providers/ipa/ipa_refresh.c index 64f8db81225..8106d75c651 100644 --- a/src/providers/ipa/ipa_refresh.c +++ b/src/providers/ipa/ipa_refresh.c @@ -134,18 +134,17 @@ static void ipa_refresh_done(struct tevent_req *subreq) { struct ipa_refresh_state *state = NULL; struct tevent_req *req = NULL; - errno_t dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_refresh_state); - ret = ipa_account_info_recv(subreq, &dp_error); + ret = ipa_account_info_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, " + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s, " "errno: %d]\n", be_req2str(state->account_req->entry_type), - dp_error, ret); + ret); goto done; } diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c index 269a719b3ff..562ebf01090 100644 --- a/src/providers/ipa/ipa_s2n_exop.c +++ b/src/providers/ipa/ipa_s2n_exop.c @@ -1546,17 +1546,15 @@ static void ipa_s2n_get_list_next(struct tevent_req *subreq) static void ipa_s2n_get_list_ipa_next(struct tevent_req *subreq) { int ret; - int dp_error; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct ipa_s2n_get_list_state *state = tevent_req_data(req, struct ipa_s2n_get_list_state); - ret = ipa_id_get_account_info_recv(subreq, &dp_error); + ret = ipa_id_get_account_info_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d %d\n", ret, - dp_error); + DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d\n", ret); goto done; } @@ -1587,7 +1585,7 @@ static void ipa_s2n_get_list_get_override_done(struct tevent_req *subreq) struct ipa_s2n_get_list_state *state = tevent_req_data(req, struct ipa_s2n_get_list_state); - ret = ipa_get_trusted_override_recv(subreq, NULL, state, &state->override_attrs); + ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); @@ -3072,7 +3070,7 @@ static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq) struct ipa_s2n_get_user_state); struct sysdb_attrs *override_attrs = NULL; - ret = ipa_get_trusted_override_recv(subreq, NULL, state, &override_attrs); + ret = ipa_get_trusted_override_recv(subreq, state, &override_attrs); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c index f2db640f9e4..9d902c781c3 100644 --- a/src/providers/ipa/ipa_selinux.c +++ b/src/providers/ipa/ipa_selinux.c @@ -809,17 +809,16 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq) struct tevent_req); struct ipa_get_selinux_state *state = tevent_req_data(req, struct ipa_get_selinux_state); - int dp_error = DP_ERR_FATAL; int ret; struct ipa_id_ctx *id_ctx = state->selinux_ctx->id_ctx; struct dp_module *access_mod; struct dp_module *selinux_mod; const char *hostname; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->be_ctx)) { talloc_zfree(state->op); ret = ipa_get_selinux_maps_offline(req); if (ret == EOK) { diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c index 47c10b6d277..2fef7cb94f1 100644 --- a/src/providers/ipa/ipa_session.c +++ b/src/providers/ipa/ipa_session.c @@ -208,12 +208,11 @@ static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { goto done; @@ -355,7 +354,6 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq) { struct tevent_req *req; struct ipa_fetch_deskprofile_state *state; - int dp_error; errno_t ret; bool found; @@ -378,15 +376,8 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq) goto done; } - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ipa_fetch_deskprofile_retry(req); - if (ret != EAGAIN) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { tevent_req_error(req, ret); return; } diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 6c93c847689..0144b521e09 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -2957,19 +2957,18 @@ static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq) { struct ipa_subdomains_refresh_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_subdomains_refresh_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " "[%d]: %s\n", ret, sss_strerror(ret)); - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->sd_ctx->be_ctx)) { DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, " "cannot get the subdomain list while offline\n"); ret = ERR_OFFLINE; @@ -3201,7 +3200,6 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq) { struct ipa_subdomains_refresh_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); @@ -3216,14 +3214,7 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq) /* Not good, but let's try to continue with other server side options */ } - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ipa_subdomains_refresh_retry(req); - } else if (dp_error == DP_ERR_OFFLINE) { - ret = ERR_OFFLINE; - } - + ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n", ret, sss_strerror(ret)); @@ -3313,7 +3304,7 @@ ipa_subdomains_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -3339,7 +3330,7 @@ static void ipa_subdomains_handler_done(struct tevent_req *subreq) } /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h index 13e82464376..110dc6f4691 100644 --- a/src/providers/ipa/ipa_subdomains.h +++ b/src/providers/ipa/ipa_subdomains.h @@ -172,7 +172,7 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, struct sdap_id_ctx *sdap_id_ctx, const char *domain); -errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req, int *dp_error_out); +errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req); struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c index eb0691439cb..7eaa060d5dc 100644 --- a/src/providers/ipa/ipa_subdomains_ext_groups.c +++ b/src/providers/ipa/ipa_subdomains_ext_groups.c @@ -525,7 +525,6 @@ struct get_trusted_membership_state { char *user_name; struct sss_domain_info *user_dom; - int dp_error; const char *domain; size_t reply_count; struct sysdb_attrs **reply; @@ -534,8 +533,7 @@ struct get_trusted_membership_state { static void ipa_get_trusted_memberships_connect_done(struct tevent_req *subreq); static void ipa_get_ext_groups_done(struct tevent_req *subreq); static errno_t ipa_add_ext_groups_step(struct tevent_req *req); -static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req, - int *dp_error_out); +static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req); struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -561,7 +559,6 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, state->sdap_id_ctx = sdap_id_ctx; state->srv = NULL; state->domain = domain; - state->dp_error = -1; if (((ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS && (ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_USER) @@ -624,10 +621,8 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, done: if (ret != EOK) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); } else { - state->dp_error = DP_ERR_OK; tevent_req_done(req); } tevent_req_post(req, state->ev); @@ -643,10 +638,10 @@ static void ipa_get_trusted_memberships_connect_done(struct tevent_req *subreq) struct get_trusted_membership_state); int ret; - ret = sdap_id_op_connect_recv(subreq, &state->dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (state->dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->sdap_id_ctx->be)) { DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, going offline\n"); } else { @@ -755,7 +750,6 @@ static errno_t ipa_add_ext_groups_step(struct tevent_req *req) if (user_dn == NULL) { DEBUG(SSSDBG_TRACE_ALL, "User [%s] not found in cache.\n", state->user_name); - state->dp_error = DP_ERR_OK; return EOK; } @@ -780,11 +774,9 @@ static void ipa_add_trusted_memberships_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct get_trusted_membership_state *state = tevent_req_data(req, - struct get_trusted_membership_state); int ret; - ret = ipa_add_trusted_memberships_recv(subreq, &state->dp_error); + ret = ipa_add_trusted_memberships_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ipa_add_ad_memberships request failed.\n"); @@ -792,22 +784,14 @@ static void ipa_add_trusted_memberships_done(struct tevent_req *subreq) return; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } -errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req, int *dp_error_out) +errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req) { - struct get_trusted_membership_state *state = tevent_req_data(req, - struct get_trusted_membership_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - return EOK; } @@ -873,7 +857,6 @@ struct add_trusted_membership_state { char **orig_groups; /* a superset of `groups`, memory is shared */ char **groups; char **missing_groups; - int dp_error; size_t iter; struct sdap_domain *group_sdom; }; @@ -929,7 +912,6 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx, goto done; } - state->dp_error = -1; state->iter = 0; state->group_sdom = sdap_domain_get(sdap_id_ctx->opts, group_dom); if (state->group_sdom == NULL) { @@ -971,10 +953,8 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx, done: if (ret != EOK) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); } else { - state->dp_error = DP_ERR_OK; tevent_req_done(req); } tevent_req_post(req, state->ev); @@ -990,10 +970,10 @@ static void ipa_add_trusted_memberships_connect_done(struct tevent_req *subreq) struct add_trusted_membership_state); int ret; - ret = sdap_id_op_connect_recv(subreq, &state->dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (state->dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->sdap_id_ctx->be)) { DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, going offline\n"); } else { @@ -1098,7 +1078,7 @@ static void ipa_add_trusted_memberships_get_group_done(struct tevent_req *subreq struct add_trusted_membership_state); int ret; - ret = groups_get_recv(subreq, &state->dp_error); + ret = groups_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to read group [%s] from LDAP [%d](%s)\n", @@ -1112,18 +1092,10 @@ static void ipa_add_trusted_memberships_get_group_done(struct tevent_req *subreq ipa_add_trusted_memberships_get_next(req); } -static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req, - int *dp_error_out) +static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req) { - struct add_trusted_membership_state *state = tevent_req_data(req, - struct add_trusted_membership_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - return EOK; } @@ -1346,10 +1318,10 @@ static void ipa_ext_group_member_done(struct tevent_req *subreq) DEBUG(SSSDBG_OP_FAILURE, "dp_req_recv failed\n"); tevent_req_error(req, ret); return; - } else if (reply->dp_error != DP_ERR_OK) { + } else if (reply->error != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, - "Cannot refresh data from DP: %u,%u: %s\n", - reply->dp_error, reply->error, reply->message); + "Cannot refresh data from DP: %u: %s\n", + reply->error, reply->message); tevent_req_error(req, EIO); return; } diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index 5d440d3f3f4..8f373f19cef 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -45,7 +45,7 @@ ipa_srv_acct_send(TALLOC_CTX *mem_ctx, struct sysdb_attrs *override_attrs, struct dp_id_data *ar); static errno_t -ipa_srv_acct_recv(struct tevent_req *req, int *dp_error_out); +ipa_srv_acct_recv(struct tevent_req *req); struct ipa_subdomain_account_state { struct tevent_context *ev; @@ -64,8 +64,6 @@ struct ipa_subdomain_account_state { struct sysdb_attrs *override_attrs; struct sysdb_attrs *mapped_attrs; char *object_sid; - - int dp_error; }; static void ipa_subdomain_account_connected(struct tevent_req *subreq); @@ -93,7 +91,6 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; - state->dp_error = DP_ERR_FATAL; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); if (!state->op) { @@ -161,10 +158,9 @@ static void ipa_subdomain_account_connected(struct tevent_req *subreq) struct tevent_req); struct ipa_subdomain_account_state *state = tevent_req_data(req, struct ipa_subdomain_account_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n"); @@ -187,7 +183,6 @@ static void ipa_subdomain_account_connected(struct tevent_req *subreq) return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -201,18 +196,17 @@ static void ipa_subdomain_account_got_override(struct tevent_req *subreq) struct tevent_req); struct ipa_subdomain_account_state *state = tevent_req_data(req, struct ipa_subdomain_account_state); - int dp_error = DP_ERR_FATAL; int ret; const char *anchor = NULL; struct dp_id_data *ar; - ret = ipa_get_trusted_override_recv(subreq, &dp_error, state, + ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret == EAGAIN) { /* retry */ subreq = sdap_id_op_connect_send(state->op, state, &ret); if (subreq == NULL) { @@ -326,7 +320,6 @@ static void ipa_subdomain_account_got_override(struct tevent_req *subreq) return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -363,21 +356,19 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq) struct tevent_req); struct ipa_subdomain_account_state *state = tevent_req_data(req, struct ipa_subdomain_account_state); - int dp_error = DP_ERR_FATAL; int ret; struct ldb_result *res; struct sss_domain_info *object_dom; if (state->ipa_server_mode) { - ret = ipa_srv_acct_recv(subreq, &dp_error); + ret = ipa_srv_acct_recv(subreq); } else { - ret = ipa_get_subdom_acct_recv(subreq, &dp_error); + ret = ipa_get_subdom_acct_recv(subreq); } talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n", ret, sss_strerror(ret)); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -406,20 +397,12 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } -errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out) +errno_t ipa_subdomain_account_recv(struct tevent_req *req) { - struct ipa_subdomain_account_state *state = tevent_req_data(req, - struct ipa_subdomain_account_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -440,8 +423,6 @@ struct ipa_get_subdom_acct { const char *extra_value; bool use_pac; struct ldb_message *user_msg; - - int dp_error; }; static void ipa_get_subdom_acct_connected(struct tevent_req *subreq); @@ -464,7 +445,6 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; - state->dp_error = DP_ERR_FATAL; state->override_attrs = override_attrs; state->use_pac = false; @@ -538,16 +518,14 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) struct tevent_req); struct ipa_get_subdom_acct *state = tevent_req_data(req, struct ipa_get_subdom_acct); - int dp_error = DP_ERR_FATAL; int ret; char *endptr; struct req_input *req_input; char *shortname; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -659,14 +637,12 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) } else { DEBUG(SSSDBG_OP_FAILURE, "Lookup by certificate not supported by the server.\n"); - state->dp_error = DP_ERR_OK; tevent_req_error(req, EINVAL); return; } break; default: DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n"); - state->dp_error = dp_error; tevent_req_error(req, EINVAL); return; } @@ -695,14 +671,13 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq) struct tevent_req); struct ipa_get_subdom_acct *state = tevent_req_data(req, struct ipa_get_subdom_acct); - int dp_error = DP_ERR_FATAL; int ret; ret = ipa_s2n_get_acct_info_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ subreq = sdap_id_op_connect_send(state->op, state, &ret); if (!subreq) { @@ -714,26 +689,17 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } /* FIXME: do we need some special handling of ENOENT */ - state->dp_error = DP_ERR_OK; tevent_req_done(req); } -int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out) +int ipa_get_subdom_acct_recv(struct tevent_req *req) { - struct ipa_get_subdom_acct *state = tevent_req_data(req, - struct ipa_get_subdom_acct); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -787,7 +753,6 @@ ipa_ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *ipa_ctx, /* IPA lookup for server mode. AD or IPA subdomain */ struct ipa_get_acct_state { - int dp_error; struct tevent_context *ev; struct ipa_id_ctx *ipa_ctx; struct dp_id_data *ar; @@ -828,7 +793,6 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, req = tevent_req_create(mem_ctx, &state, struct ipa_get_acct_state); if (req == NULL) return NULL; - state->dp_error = -1; state->ev = ev; state->ipa_ctx = ipa_ctx; state->ar = ar; @@ -891,7 +855,6 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, return req; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); tevent_req_post(req, ev); return req; @@ -958,7 +921,6 @@ ipa_get_ipa_acct_send(TALLOC_CTX *mem_ctx, req = tevent_req_create(mem_ctx, &state, struct ipa_get_acct_state); if (req == NULL) return NULL; - state->dp_error = -1; state->ev = ev; state->ipa_ctx = ipa_ctx; state->ar = ar; @@ -999,7 +961,6 @@ ipa_get_ipa_acct_send(TALLOC_CTX *mem_ctx, return req; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); tevent_req_post(req, ev); return req; @@ -1365,7 +1326,6 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, static void ipa_get_sid_ipa_next(struct tevent_req *subreq) { int ret; - int dp_error = DP_ERR_FATAL; const char *sid; const char *user; struct ldb_message *user_msg; @@ -1376,11 +1336,10 @@ static void ipa_get_sid_ipa_next(struct tevent_req *subreq) struct ipa_get_acct_state *state = tevent_req_data(req, struct ipa_get_acct_state); - ret = ipa_subdomain_account_recv(subreq, &state->dp_error); + ret = ipa_subdomain_account_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d %d\n", ret, - dp_error); + DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d \n", ret); goto done; } @@ -1472,9 +1431,9 @@ ipa_get_trusted_acct_part_done(struct tevent_req *subreq) struct dp_id_data *user_ar; if (state->type == IPA_TRUST_AD) { - ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL); + ret = ad_handle_acct_info_recv(subreq, NULL); } else if (state->type == IPA_TRUST_IPA) { - ret = ipa_id_get_account_info_recv(subreq, &state->dp_error); + ret = ipa_id_get_account_info_recv(subreq); } else { ret = EINVAL; } @@ -1591,7 +1550,6 @@ ipa_get_trusted_acct_part_done(struct tevent_req *subreq) return; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -1606,7 +1564,7 @@ ipa_get_trusted_override_done(struct tevent_req *subreq) struct ipa_get_acct_state); errno_t ret; - ret = ipa_get_trusted_override_recv(subreq, &state->dp_error, state, + ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { @@ -1625,7 +1583,6 @@ ipa_get_trusted_override_done(struct tevent_req *subreq) return; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -1678,7 +1635,7 @@ static void ipa_check_ghost_members_done(struct tevent_req *subreq) struct tevent_req); int ret; - ret = ipa_resolve_user_list_recv(subreq, NULL); + ret = ipa_resolve_user_list_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list request failed [%d]\n", @@ -1825,7 +1782,7 @@ static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq) struct tevent_req); errno_t ret; - ret = ipa_initgr_get_overrides_recv(subreq, NULL); + ret = ipa_initgr_get_overrides_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, @@ -1872,11 +1829,9 @@ ipa_get_trusted_acct_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct ipa_get_acct_state *state = tevent_req_data(req, - struct ipa_get_acct_state); errno_t ret; - ret = ipa_get_trusted_memberships_recv(subreq, &state->dp_error); + ret = ipa_get_trusted_memberships_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA external groups lookup failed: %d\n", @@ -1890,15 +1845,8 @@ ipa_get_trusted_acct_done(struct tevent_req *subreq) } static errno_t -ipa_get_acct_recv(struct tevent_req *req, int *dp_error_out) +ipa_get_acct_recv(struct tevent_req *req) { - struct ipa_get_acct_state *state = tevent_req_data(req, - struct ipa_get_acct_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1914,8 +1862,6 @@ struct ipa_srv_acct_state { struct be_ctx *be_ctx; enum ipa_trust_type type; bool retry; - - int dp_error; }; static int ipa_srv_acct_lookup_step(struct tevent_req *req); @@ -1943,7 +1889,6 @@ ipa_srv_acct_send(TALLOC_CTX *mem_ctx, state->override_attrs = override_attrs; state->ar = ar; state->retry = true; - state->dp_error = DP_ERR_FATAL; state->be_ctx = ipa_ctx->sdap_id_ctx->be; state->obj_dom = find_domain_by_name( @@ -2002,13 +1947,12 @@ static int ipa_srv_acct_lookup_step(struct tevent_req *req) static void ipa_srv_acct_lookup_done(struct tevent_req *subreq) { errno_t ret; - int dp_error = DP_ERR_FATAL; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct ipa_srv_acct_state *state = tevent_req_data(req, struct ipa_srv_acct_state); - ret = ipa_get_acct_recv(subreq, &dp_error); + ret = ipa_get_acct_recv(subreq); talloc_free(subreq); if (ret == ERR_SUBDOM_INACTIVE && state->retry == true) { @@ -2033,12 +1977,10 @@ static void ipa_srv_acct_lookup_done(struct tevent_req *subreq) goto fail; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = dp_error; tevent_req_error(req, ret); } @@ -2056,7 +1998,6 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq) if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to re-set subdomain [%d]: %s\n", ret, sss_strerror(ret)); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -2065,7 +2006,6 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq) ad_id_ctx = ipa_get_ad_id_ctx(state->ipa_ctx, state->obj_dom); if (ad_id_ctx == NULL || ad_id_ctx->ad_options == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "No AD ID ctx or no ID CTX options?\n"); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, EINVAL); return; } @@ -2076,22 +2016,14 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq) if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to look up AD acct [%d]: %s\n", ret, sss_strerror(ret)); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } } static errno_t -ipa_srv_acct_recv(struct tevent_req *req, int *dp_error_out) +ipa_srv_acct_recv(struct tevent_req *req) { - struct ipa_srv_acct_state *state = tevent_req_data(req, - struct ipa_srv_acct_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } diff --git a/src/providers/ipa/ipa_sudo.c b/src/providers/ipa/ipa_sudo.c index 32ff1ceced1..2d3a7f5e61f 100644 --- a/src/providers/ipa/ipa_sudo.c +++ b/src/providers/ipa/ipa_sudo.c @@ -80,7 +80,7 @@ ipa_sudo_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -93,7 +93,6 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq) { struct ipa_sudo_handler_state *state; struct tevent_req *req; - int dp_error; bool deleted; errno_t ret; @@ -102,17 +101,17 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq) switch (state->type) { case BE_REQ_SUDO_FULL: - ret = ipa_sudo_full_refresh_recv(subreq, &dp_error); + ret = ipa_sudo_full_refresh_recv(subreq); talloc_zfree(subreq); /* Postpone the periodic task since the refresh was just finished * per user request. */ - if (ret == EOK && dp_error == DP_ERR_OK) { + if (ret == EOK) { be_ptask_postpone(state->sudo_ctx->full_refresh); } break; case BE_REQ_SUDO_RULES: - ret = ipa_sudo_rules_refresh_recv(subreq, &dp_error, &deleted); + ret = ipa_sudo_rules_refresh_recv(subreq, &deleted); talloc_zfree(subreq); if (ret == EOK && deleted == true) { ret = ENOENT; @@ -120,13 +119,12 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq) break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type); - dp_error = DP_ERR_FATAL; ret = ERR_INTERNAL; break; } /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ipa/ipa_sudo.h b/src/providers/ipa/ipa_sudo.h index 026fc290d9f..7c86814b695 100644 --- a/src/providers/ipa/ipa_sudo.h +++ b/src/providers/ipa/ipa_sudo.h @@ -47,12 +47,10 @@ ipa_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, struct ipa_sudo_ctx *sudo_ctx); int -ipa_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error); +ipa_sudo_full_refresh_recv(struct tevent_req *req); int ipa_sudo_rules_refresh_recv(struct tevent_req *req, - int *dp_error, bool *deleted); struct tevent_req * @@ -72,7 +70,6 @@ ipa_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, errno_t ipa_sudo_refresh_recv(struct tevent_req *req, - int *dp_error, size_t *_num_rules); struct ipa_sudo_conv; diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c index c531ecbf9e8..a903422351f 100644 --- a/src/providers/ipa/ipa_sudo_async.c +++ b/src/providers/ipa/ipa_sudo_async.c @@ -851,7 +851,6 @@ struct ipa_sudo_refresh_state { struct sdap_id_op *sdap_op; struct sdap_handle *sh; - int dp_error; struct sysdb_attrs **rules; size_t num_rules; @@ -887,7 +886,6 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx, state->sudo_ctx = sudo_ctx; state->ipa_opts = sudo_ctx->ipa_opts; state->sdap_opts = sudo_ctx->sdap_opts; - state->dp_error = DP_ERR_FATAL; state->update_usn = update_usn; state->sdap_op = sdap_id_op_create(state, @@ -960,19 +958,17 @@ ipa_sudo_refresh_connect_done(struct tevent_req *subreq) struct ipa_sudo_refresh_state *state; const char *hostname; struct tevent_req *req; - int dp_error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_sudo_refresh_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed " "[%d]: %s\n", ret, strerror(ret)); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -991,7 +987,6 @@ ipa_sudo_refresh_connect_done(struct tevent_req *subreq) state->ipa_opts->hostgroup_map, state->ipa_opts->id->sdom->host_search_bases); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1012,7 +1007,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq) host = talloc_zero(state, struct ipa_hostinfo); if (host == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1023,7 +1017,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq) if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve host information " "[%d]: %s\n", ret, sss_strerror(ret)); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -1036,7 +1029,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq) state->ipa_opts->hostgroup_map, state->sh, state->cmdgroups_filter, state->search_filter); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1061,8 +1053,8 @@ ipa_sudo_refresh_done(struct tevent_req *subreq) &state->num_rules, &usn); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error); - if (state->dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret == EAGAIN) { /* retry */ ret = ipa_sudo_refresh_retry(req); if (ret != EOK) { @@ -1123,7 +1115,6 @@ ipa_sudo_refresh_done(struct tevent_req *subreq) errno_t ipa_sudo_refresh_recv(struct tevent_req *req, - int *dp_error, size_t *_num_rules) { struct ipa_sudo_refresh_state *state = NULL; @@ -1131,8 +1122,6 @@ ipa_sudo_refresh_recv(struct tevent_req *req, TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - if (_num_rules != NULL) { *_num_rules = state->num_rules; } diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c index 7386a01f2c4..e7e7ae5b028 100644 --- a/src/providers/ipa/ipa_sudo_refresh.c +++ b/src/providers/ipa/ipa_sudo_refresh.c @@ -31,7 +31,6 @@ struct ipa_sudo_full_refresh_state { struct ipa_sudo_ctx *sudo_ctx; struct sss_domain_info *domain; - int dp_error; }; static void ipa_sudo_full_refresh_done(struct tevent_req *subreq); @@ -95,9 +94,9 @@ ipa_sudo_full_refresh_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_sudo_full_refresh_state); - ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, NULL); + ret = ipa_sudo_refresh_recv(subreq, NULL); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -122,21 +121,14 @@ ipa_sudo_full_refresh_done(struct tevent_req *subreq) } int -ipa_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error) +ipa_sudo_full_refresh_recv(struct tevent_req *req) { - struct ipa_sudo_full_refresh_state *state; - state = tevent_req_data(req, struct ipa_sudo_full_refresh_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } struct ipa_sudo_smart_refresh_state { - int dp_error; }; static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq); @@ -165,7 +157,6 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, if (be_ptask_running(sudo_ctx->full_refresh)) { DEBUG(SSSDBG_TRACE_FUNC, "Skipping smart refresh because " "there is ongoing full refresh.\n"); - state->dp_error = DP_ERR_OK; ret = EOK; goto immediately; } @@ -223,15 +214,13 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; - struct ipa_sudo_smart_refresh_state *state = NULL; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state); - ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, NULL); + ret = ipa_sudo_refresh_recv(subreq, NULL); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -246,22 +235,15 @@ static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq) tevent_req_done(req); } -int ipa_sudo_smart_refresh_recv(struct tevent_req *req, - int *dp_error) +int ipa_sudo_smart_refresh_recv(struct tevent_req *req) { - struct ipa_sudo_smart_refresh_state *state = NULL; - state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } struct ipa_sudo_rules_refresh_state { size_t num_rules; - int dp_error; bool deleted; }; @@ -297,7 +279,6 @@ ipa_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, } if (rules == NULL || rules[0] == NULL) { - state->dp_error = DP_ERR_OK; state->num_rules = 0; state->deleted = false; ret = EOK; @@ -381,9 +362,9 @@ ipa_sudo_rules_refresh_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_sudo_rules_refresh_state); - ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, &downloaded_rules_num); + ret = ipa_sudo_refresh_recv(subreq, &downloaded_rules_num); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -400,7 +381,6 @@ ipa_sudo_rules_refresh_done(struct tevent_req *subreq) int ipa_sudo_rules_refresh_recv(struct tevent_req *req, - int *dp_error, bool *deleted) { struct ipa_sudo_rules_refresh_state *state; @@ -408,7 +388,6 @@ ipa_sudo_rules_refresh_recv(struct tevent_req *req, TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; *deleted = state->deleted; return EOK; @@ -430,9 +409,7 @@ ipa_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx, static errno_t ipa_sudo_ptask_full_refresh_recv(struct tevent_req *req) { - int dp_error; - - return ipa_sudo_full_refresh_recv(req, &dp_error); + return ipa_sudo_full_refresh_recv(req); } static struct tevent_req * @@ -451,9 +428,7 @@ ipa_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx, static errno_t ipa_sudo_ptask_smart_refresh_recv(struct tevent_req *req) { - int dp_error; - - return ipa_sudo_smart_refresh_recv(req, &dp_error); + return ipa_sudo_smart_refresh_recv(req); } errno_t diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c index c22cb10a562..e2fff877d9b 100644 --- a/src/providers/ipa/ipa_views.c +++ b/src/providers/ipa/ipa_views.c @@ -389,7 +389,6 @@ struct ipa_get_trusted_override_state { struct sss_domain_info *dom; struct sdap_id_op *sdap_op; - int dp_error; struct sysdb_attrs *override_attrs; char *filter; bool login_override_checked; @@ -424,7 +423,6 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, state->ipa_options = ipa_options; state->ipa_realm = ipa_realm; state->ar = ar; - state->dp_error = -1; state->override_attrs = NULL; state->filter = NULL; @@ -469,10 +467,8 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, done: if (ret != EOK) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); } else { - state->dp_error = DP_ERR_OK; tevent_req_done(req); } tevent_req_post(req, state->ev); @@ -491,10 +487,10 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq) char *search_base; struct ipa_options *ipa_opts = state->ipa_options; - ret = sdap_id_op_connect_recv(subreq, &state->dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (state->dp_error == DP_ERR_OFFLINE) { + if (ret == ERR_OFFLINE) { DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, going offline\n"); } else { @@ -550,7 +546,6 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq) return; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -603,7 +598,6 @@ static void ipa_get_trusted_override_done(struct tevent_req *subreq) state->ar->entry_type = BE_REQ_GROUP; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } else if (reply_count == MAX_USER_AND_GROUP_REPLIES && @@ -634,12 +628,10 @@ static void ipa_get_trusted_override_done(struct tevent_req *subreq) goto fail; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; fail: - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); return; } @@ -671,17 +663,13 @@ static errno_t ipa_get_trusted_override_qualify_name( return EOK; } -errno_t ipa_get_trusted_override_recv(struct tevent_req *req, int *dp_error_out, +errno_t ipa_get_trusted_override_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct sysdb_attrs **override_attrs) { struct ipa_get_trusted_override_state *state = tevent_req_data(req, struct ipa_get_trusted_override_state); - if (dp_error_out != NULL) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); if (override_attrs != NULL) { diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index ac02dfbd78b..585f5b4429c 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -250,7 +250,7 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, struct sss_domain_info *domain, struct confdb_ctx *cdb, struct pam_data *pd, uid_t uid, - int *pam_status, int *dp_err) + int *pam_status) { const char *password = NULL; errno_t ret; @@ -262,7 +262,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, "available for password authentication (single factor).\n", ret, strerror(ret)); *pam_status = PAM_SYSTEM_ERR; - *dp_err = DP_ERR_OK; return; } @@ -271,7 +270,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Offline authentication failed\n"); *pam_status = cached_login_pam_status(ret); - *dp_err = DP_ERR_OK; return; } @@ -285,7 +283,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, "add_user_to_delayed_online_authentication failed.\n"); } *pam_status = PAM_AUTHINFO_UNAVAIL; - *dp_err = DP_ERR_OFFLINE; } static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr, @@ -499,7 +496,6 @@ struct krb5_auth_state { bool search_kpasswd; int pam_status; - int dp_err; }; static void krb5_auth_resolve_done(struct tevent_req *subreq); @@ -534,7 +530,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, state->krb5_ctx = krb5_ctx; state->kr = NULL; state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_FATAL; ret = get_domain_or_subdomain(be_ctx, pd->domain, &state->domain); if (ret != EOK) { @@ -565,7 +560,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, "Illegal empty authtok for user [%s]\n", pd->user); state->pam_status = PAM_AUTH_ERR; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -576,7 +570,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, SSS_AUTHTOK_TYPE_PASSWORD, authtok_type); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_FATAL; ret = EINVAL; goto done; } @@ -587,7 +580,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_MINOR_FAILURE, "Password reset by root is not supported.\n"); state->pam_status = PAM_PERM_DENIED; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -598,7 +590,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, 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; } @@ -612,7 +603,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, SSS_AUTHTOK_TYPE_CCFILE, authtok_type); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_FATAL; ret = EINVAL; goto done; } @@ -622,7 +612,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, default: DEBUG(SSSDBG_CONF_SETTINGS, "Unexpected pam task %d.\n", pd->cmd); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_FATAL; ret = EINVAL; goto done; } @@ -634,7 +623,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, "Password changes and ticket renewal are not possible " "while offline.\n"); state->pam_status = PAM_AUTHINFO_UNAVAIL; - state->dp_err = DP_ERR_OFFLINE; ret = EOK; goto done; } @@ -668,7 +656,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_FUNC_DATA, "sysdb search for upn of user [%s] failed.\n", pd->user); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_OK; goto done; } @@ -752,7 +739,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Skipping password checks for OTP-enabled user\n"); state->pam_status = PAM_SUCCESS; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -806,7 +792,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) * authentication is. We return an PAM error here, but do not * mark the backend offline. */ state->pam_status = PAM_AUTHTOK_LOCK_BUSY; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -824,7 +809,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "No KDC suitable for password change is available\n"); state->pam_status = PAM_AUTHTOK_LOCK_BUSY; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -933,7 +917,6 @@ static void krb5_auth_done(struct tevent_req *subreq) } case SSS_PAM_PREAUTH: state->pam_status = PAM_CRED_UNAVAIL; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; default: @@ -1029,7 +1012,6 @@ static void krb5_auth_done(struct tevent_req *subreq) * change password request just return success. */ if (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) { state->pam_status = PAM_SUCCESS; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -1101,49 +1083,41 @@ static void krb5_auth_done(struct tevent_req *subreq) } state->pam_status = PAM_NEW_AUTHTOK_REQD; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_CREDS_INVALID: state->pam_status = PAM_CRED_ERR; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_ACCOUNT_EXPIRED: state->pam_status = PAM_ACCT_EXPIRED; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_ACCOUNT_LOCKED: state->pam_status = PAM_PERM_DENIED; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_NO_CREDS: state->pam_status = PAM_CRED_UNAVAIL; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_AUTH_FAILED: state->pam_status = PAM_AUTH_ERR; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_CHPASS_FAILED: state->pam_status = PAM_AUTHTOK_ERR; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; case ERR_NO_AUTH_METHOD_AVAILABLE: state->pam_status = PAM_NO_MODULE_DATA; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; @@ -1152,7 +1126,6 @@ static void krb5_auth_done(struct tevent_req *subreq) "The krb5_child process returned an error. Please inspect the " "krb5_child.log file or the journal for more information\n"); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -1172,7 +1145,6 @@ static void krb5_auth_done(struct tevent_req *subreq) if (pd->cmd == SSS_PAM_PREAUTH) { state->pam_status = PAM_SUCCESS; - state->dp_err = DP_ERR_OK; ret = EOK; goto done; } @@ -1228,12 +1200,11 @@ static void krb5_auth_done(struct tevent_req *subreq) state->domain, state->be_ctx->cdb, state->pd, state->kr->uid, - &state->pam_status, &state->dp_err); + &state->pam_status); } else { DEBUG(SSSDBG_CONF_SETTINGS, "Backend is marked offline, retry later!\n"); state->pam_status = PAM_AUTHINFO_UNAVAIL; - state->dp_err = DP_ERR_OFFLINE; } ret = EOK; goto done; @@ -1260,13 +1231,11 @@ static void krb5_auth_done(struct tevent_req *subreq) "pam_add_response failed: %d (%s).\n", ret, sss_strerror(ret)); state->pam_status = PAM_SYSTEM_ERR; - state->dp_err = DP_ERR_OK; goto done; } } state->pam_status = PAM_SUCCESS; - state->dp_err = DP_ERR_OK; ret = EOK; done: @@ -1278,11 +1247,10 @@ static void krb5_auth_done(struct tevent_req *subreq) } -int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err) +int krb5_auth_recv(struct tevent_req *req, int *pam_status) { struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state); *pam_status = state->pam_status; - *dp_err = state->dp_err; TEVENT_REQ_RETURN_ON_ERROR(req); @@ -1381,7 +1349,7 @@ static void krb5_pam_handler_auth_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct krb5_pam_handler_state); - ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, NULL); + ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status); talloc_zfree(subreq); if (ret != EOK) { state->pd->pam_status = PAM_SYSTEM_ERR; @@ -1423,7 +1391,7 @@ static void krb5_pam_handler_auth_retry_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct krb5_pam_handler_state); - ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, NULL); + ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status); talloc_free(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv request failed.\n"); diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index c2d802d87a0..4f908443c2d 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -97,7 +97,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct pam_data *pd, struct krb5_ctx *krb5_ctx); -int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err); +int krb5_auth_recv(struct tevent_req *req, int *pam_status); struct tevent_req *handle_child_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -148,7 +148,6 @@ struct tevent_req *krb5_auth_queue_send(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx); int krb5_auth_queue_recv(struct tevent_req *req, - int *_pam_status, - int *_dp_err); + int *_pam_status); #endif /* __KRB5_AUTH_H__ */ diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c index 7f49e2e5975..5152862e1a1 100644 --- a/src/providers/krb5/krb5_delayed_online_authentication.c +++ b/src/providers/krb5/krb5_delayed_online_authentication.c @@ -118,9 +118,8 @@ static void authenticate_user_done(struct tevent_req *req) struct auth_data); int ret; int pam_status = PAM_SYSTEM_ERR; - int dp_err = DP_ERR_OK; - ret = krb5_auth_queue_recv(req, &pam_status, &dp_err); + ret = krb5_auth_queue_recv(req, &pam_status); talloc_free(req); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth request failed.\n"); diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c index 7d8f0e4347a..90ac52c00e0 100644 --- a/src/providers/krb5/krb5_renew_tgt.c +++ b/src/providers/krb5/krb5_renew_tgt.c @@ -85,10 +85,9 @@ static void renew_tgt_done(struct tevent_req *req) struct auth_data); int ret; int pam_status = PAM_SYSTEM_ERR; - int dp_err; hash_value_t value; - ret = krb5_auth_queue_recv(req, &pam_status, &dp_err); + ret = krb5_auth_queue_recv(req, &pam_status); talloc_free(req); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth request failed.\n"); diff --git a/src/providers/krb5/krb5_wait_queue.c b/src/providers/krb5/krb5_wait_queue.c index 06d7a981cd9..b8929109501 100644 --- a/src/providers/krb5/krb5_wait_queue.c +++ b/src/providers/krb5/krb5_wait_queue.c @@ -43,7 +43,7 @@ struct queue_entry { static void wait_queue_auth_done(struct tevent_req *req); static void krb5_auth_queue_finish(struct tevent_req *req, errno_t ret, - int pam_status, int dp_err); + int pam_status); static void wait_queue_auth(struct tevent_context *ev, struct tevent_timer *te, struct timeval current_time, void *private_data) @@ -68,16 +68,15 @@ static void wait_queue_auth_done(struct tevent_req *req) struct tevent_req *parent_req = \ tevent_req_callback_data(req, struct tevent_req); int pam_status; - int dp_err; errno_t ret; - ret = krb5_auth_recv(req, &pam_status, &dp_err); + ret = krb5_auth_recv(req, &pam_status); talloc_zfree(req); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed: %d\n", ret); } - krb5_auth_queue_finish(parent_req, ret, pam_status, dp_err); + krb5_auth_queue_finish(parent_req, ret, pam_status); } static void wait_queue_del_cb(hash_entry_t *entry, hash_destroy_enum type, @@ -242,7 +241,6 @@ struct krb5_auth_queue_state { struct pam_data *pd; int pam_status; - int dp_err; }; static void krb5_auth_queue_done(struct tevent_req *subreq); @@ -309,7 +307,7 @@ static void krb5_auth_queue_done(struct tevent_req *subreq) tevent_req_data(req, struct krb5_auth_queue_state); errno_t ret; - ret = krb5_auth_recv(subreq, &state->pam_status, &state->dp_err); + ret = krb5_auth_recv(subreq, &state->pam_status); talloc_zfree(subreq); check_wait_queue(state->krb5_ctx, state->pd->user); @@ -331,8 +329,7 @@ static void krb5_auth_queue_done(struct tevent_req *subreq) */ static void krb5_auth_queue_finish(struct tevent_req *req, errno_t ret, - int pam_status, - int dp_err) + int pam_status) { struct krb5_auth_queue_state *state = \ tevent_req_data(req, struct krb5_auth_queue_state); @@ -340,7 +337,6 @@ static void krb5_auth_queue_finish(struct tevent_req *req, check_wait_queue(state->krb5_ctx, state->pd->user); state->pam_status = pam_status; - state->dp_err = dp_err; if (ret != EOK) { tevent_req_error(req, ret); } else { @@ -350,8 +346,7 @@ static void krb5_auth_queue_finish(struct tevent_req *req, } int krb5_auth_queue_recv(struct tevent_req *req, - int *_pam_status, - int *_dp_err) + int *_pam_status) { struct krb5_auth_queue_state *state = \ tevent_req_data(req, struct krb5_auth_queue_state); @@ -363,10 +358,6 @@ int krb5_auth_queue_recv(struct tevent_req *req, *_pam_status = state->pam_status; } - if (_dp_err) { - *_dp_err = state->dp_err; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 24fcec78913..bc44ceb0e81 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -157,7 +157,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, bool noexist_delete); errno_t sdap_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err); + const char **_err); struct tevent_req * sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, @@ -301,7 +301,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, bool noexist_delete, bool no_members, bool set_non_posix); -int groups_get_recv(struct tevent_req *req, int *dp_error_out); +int groups_get_recv(struct tevent_req *req); struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -317,7 +317,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, bool noexist_delete, bool set_non_posix); -int groups_by_user_recv(struct tevent_req *req, int *dp_error_out); +int groups_by_user_recv(struct tevent_req *req); struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -326,7 +326,7 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct sdap_id_conn_ctx *conn, const char *name, bool noexist_delete); -int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out); +int ldap_netgroup_get_recv(struct tevent_req *req); struct tevent_req * services_get_send(TALLOC_CTX *mem_ctx, @@ -340,7 +340,7 @@ services_get_send(TALLOC_CTX *mem_ctx, bool noexist_delete); errno_t -services_get_recv(struct tevent_req *req, int *dp_error_out); +services_get_recv(struct tevent_req *req); struct tevent_req * sdap_iphost_handler_send(TALLOC_CTX *mem_ctx, @@ -490,7 +490,7 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, struct sdap_id_conn_ctx *conn, const char* filter_value); -int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out); +int subid_ranges_get_recv(struct tevent_req *req); #endif #endif /* _LDAP_COMMON_H_ */ diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index e842fd9eeb0..faa02af742f 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -146,7 +146,6 @@ struct users_get_state { bool use_id_mapping; bool non_posix; - int dp_error; bool noexist_delete; struct sysdb_attrs *extra_attrs; }; @@ -187,7 +186,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, state->ctx = ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->noexist_delete = noexist_delete; state->extra_attrs = NULL; @@ -376,7 +374,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, } ret = EOK; - state->dp_error = DP_ERR_OK; goto done; } @@ -493,16 +490,12 @@ static void users_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -547,14 +540,13 @@ static void users_get_done(struct tevent_req *subreq) struct users_get_state); char *endptr; uid_t uid = 0; - int dp_error = DP_ERR_FATAL; int ret; ret = sdap_get_users_recv(subreq, NULL, NULL); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = users_get_retry(req); if (ret != EOK) { @@ -601,7 +593,6 @@ static void users_get_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -615,20 +606,12 @@ static void users_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; /* FIXME - return sdap error so that we know the user was not found */ tevent_req_done(req); } -int users_get_recv(struct tevent_req *req, int *dp_error_out) +int users_get_recv(struct tevent_req *req) { - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -653,7 +636,6 @@ struct groups_get_state { bool use_id_mapping; bool non_posix; - int dp_error; bool noexist_delete; bool no_members; }; @@ -695,7 +677,6 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, state->ctx = ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->noexist_delete = noexist_delete; state->no_members = no_members; @@ -907,16 +888,12 @@ static void groups_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -959,14 +936,13 @@ static void groups_get_done(struct tevent_req *subreq) struct tevent_req); struct groups_get_state *state = tevent_req_data(req, struct groups_get_state); - int dp_error = DP_ERR_FATAL; int ret; ret = sdap_get_groups_recv(subreq, NULL, NULL); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret != EOK) { /* retry */ ret = groups_get_retry(req); if (ret != EOK) { @@ -978,7 +954,6 @@ static void groups_get_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1018,7 +993,6 @@ static void groups_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } @@ -1030,7 +1004,7 @@ static void groups_get_mpg_done(struct tevent_req *subreq) struct groups_get_state *state = tevent_req_data(req, struct groups_get_state); - ret = users_get_recv(subreq, &state->dp_error); + ret = users_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { @@ -1114,15 +1088,8 @@ errno_t groups_get_handle_no_group(TALLOC_CTX *mem_ctx, return ret; } -int groups_get_recv(struct tevent_req *req, int *dp_error_out) +int groups_get_recv(struct tevent_req *req) { - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1149,7 +1116,6 @@ struct groups_by_user_state { const char **attrs; bool non_posix; - int dp_error; bool noexist_delete; }; @@ -1180,7 +1146,6 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; - state->dp_error = DP_ERR_FATAL; state->conn = conn; state->sdom = sdom; state->noexist_delete = noexist_delete; @@ -1244,14 +1209,12 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) struct tevent_req); struct groups_by_user_state *state = tevent_req_data(req, struct groups_by_user_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1283,14 +1246,13 @@ static void groups_by_user_done(struct tevent_req *subreq) struct tevent_req); struct groups_by_user_state *state = tevent_req_data(req, struct groups_by_user_state); - int dp_error = DP_ERR_FATAL; int ret; ret = sdap_get_initgr_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret != EOK) { /* retry */ ret = groups_by_user_retry(req); if (ret != EOK) { @@ -1330,24 +1292,15 @@ static void groups_by_user_done(struct tevent_req *subreq) case EOK: break; default: - state->dp_error = dp_error; tevent_req_error(req, ret); return; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } -int groups_by_user_recv(struct tevent_req *req, int *dp_error_out) +int groups_by_user_recv(struct tevent_req *req) { - struct groups_by_user_state *state = tevent_req_data(req, - struct groups_by_user_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1367,8 +1320,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, int filter_type, bool noexist_delete); -errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out); +errno_t sdap_get_user_and_group_recv(struct tevent_req *req); bool sdap_is_enum_request(struct dp_id_data *ar) { @@ -1388,7 +1340,6 @@ bool sdap_is_enum_request(struct dp_id_data *ar) struct sdap_handle_acct_req_state { struct dp_id_data *ar; const char *err; - int dp_error; }; static void sdap_handle_acct_req_done(struct tevent_req *subreq); @@ -1607,31 +1558,31 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ err = "User lookup failed"; - ret = users_get_recv(subreq, &state->dp_error); + ret = users_get_recv(subreq); break; case BE_REQ_GROUP: /* group */ err = "Group lookup failed"; - ret = groups_get_recv(subreq, &state->dp_error); + ret = groups_get_recv(subreq); break; case BE_REQ_INITGROUPS: /* init groups for user */ err = "Init group lookup failed"; - ret = groups_by_user_recv(subreq, &state->dp_error); + ret = groups_by_user_recv(subreq); break; case BE_REQ_SUBID_RANGES: err = "Subid ranges lookup failed"; #ifdef BUILD_SUBID - ret = subid_ranges_get_recv(subreq, &state->dp_error); + ret = subid_ranges_get_recv(subreq); #else ret = EINVAL; #endif break; case BE_REQ_NETGROUP: err = "Netgroup lookup failed"; - ret = ldap_netgroup_get_recv(subreq, &state->dp_error); + ret = ldap_netgroup_get_recv(subreq); break; case BE_REQ_SERVICES: err = "Service lookup failed"; - ret = services_get_recv(subreq, &state->dp_error); + ret = services_get_recv(subreq); break; case BE_REQ_BY_SECID: /* Fall through */ @@ -1639,11 +1590,11 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) /* Fall through */ case BE_REQ_USER_AND_GROUP: err = "Lookup by SID failed"; - ret = sdap_get_user_and_group_recv(subreq, &state->dp_error); + ret = sdap_get_user_and_group_recv(subreq); break; case BE_REQ_BY_CERT: err = "User lookup by certificate failed"; - ret = users_get_recv(subreq, &state->dp_error); + ret = users_get_recv(subreq); break; default: /* fail */ ret = EINVAL; @@ -1663,7 +1614,7 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) errno_t sdap_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err) + const char **_err) { struct sdap_handle_acct_req_state *state; @@ -1674,10 +1625,6 @@ sdap_handle_acct_req_recv(struct tevent_req *req, state->ar->filter_type, state->ar->filter_value, PROBE_SAFE_STR(state->ar->extra_value)); - if (_dp_error) { - *_dp_error = state->dp_error; - } - if (_err) { *_err = state->err; } @@ -1701,7 +1648,6 @@ struct get_user_and_group_state { char *filter; const char **attrs; - int dp_error; bool noexist_delete; }; @@ -1732,7 +1678,6 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, state->id_ctx = id_ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->noexist_delete = noexist_delete; state->op = sdap_id_op_create(state, state->conn->conn_cache); @@ -1776,7 +1721,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) int ret; struct sdap_id_conn_ctx *user_conn; - ret = groups_get_recv(subreq, &state->dp_error); + ret = groups_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { /* Fatal error while looking up group */ @@ -1822,7 +1767,7 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) struct get_user_and_group_state); int ret; - ret = users_get_recv(subreq, &state->dp_error); + ret = users_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { @@ -1851,16 +1796,8 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) return; } -errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out) +errno_t sdap_get_user_and_group_recv(struct tevent_req *req) { - struct get_user_and_group_state *state = tevent_req_data(req, - struct get_user_and_group_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1908,7 +1845,7 @@ sdap_account_info_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -1922,17 +1859,16 @@ static void sdap_account_info_handler_done(struct tevent_req *subreq) struct sdap_account_info_handler_state *state; struct tevent_req *req; const char *error_msg; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_account_info_handler_state); - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg); + ret = sdap_handle_acct_req_recv(subreq, &error_msg); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, error_msg); + dp_reply_std_set(&state->reply, ret, error_msg); tevent_req_done(req); } diff --git a/src/providers/ldap/ldap_id_netgroup.c b/src/providers/ldap/ldap_id_netgroup.c index d17396ed9b7..9240441b264 100644 --- a/src/providers/ldap/ldap_id_netgroup.c +++ b/src/providers/ldap/ldap_id_netgroup.c @@ -48,7 +48,6 @@ struct ldap_netgroup_get_state { size_t count; struct sysdb_attrs **netgroups; - int dp_error; bool noexist_delete; }; @@ -76,7 +75,6 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, state->ctx = ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->noexist_delete = noexist_delete; state->op = sdap_id_op_create(state, state->conn->conn_cache); @@ -146,14 +144,12 @@ static void ldap_netgroup_get_connect_done(struct tevent_req *subreq) struct tevent_req); struct ldap_netgroup_get_state *state = tevent_req_data(req, struct ldap_netgroup_get_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -180,15 +176,14 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) struct tevent_req); struct ldap_netgroup_get_state *state = tevent_req_data(req, struct ldap_netgroup_get_state); - int dp_error = DP_ERR_FATAL; int ret; ret = sdap_get_netgroups_recv(subreq, state, NULL, &state->count, &state->netgroups); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); + ret = sdap_id_op_done(state->op, ret); - if (dp_error == DP_ERR_OK && ret != EOK) { + if (ret != EOK) { /* retry */ ret = ldap_netgroup_get_retry(req); if (ret != EOK) { @@ -200,7 +195,6 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -221,20 +215,12 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } -int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out) +int ldap_netgroup_get_recv(struct tevent_req *req) { - struct ldap_netgroup_get_state *state = tevent_req_data(req, - struct ldap_netgroup_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c index 2c75ba8bebc..019710b918b 100644 --- a/src/providers/ldap/ldap_id_services.c +++ b/src/providers/ldap/ldap_id_services.c @@ -47,7 +47,6 @@ struct sdap_services_get_state { int filter_type; - int dp_error; bool noexist_delete; }; @@ -83,7 +82,6 @@ services_get_send(TALLOC_CTX *mem_ctx, state->id_ctx = id_ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->name = name; @@ -184,13 +182,11 @@ services_get_connect_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct sdap_services_get_state *state = tevent_req_data(req, struct sdap_services_get_state); - int dp_error = DP_ERR_FATAL; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -221,7 +217,6 @@ services_get_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct sdap_services_get_state *state = tevent_req_data(req, struct sdap_services_get_state); - int dp_error = DP_ERR_FATAL; ret = sdap_get_services_recv(NULL, subreq, NULL); talloc_zfree(subreq); @@ -229,8 +224,8 @@ services_get_done(struct tevent_req *subreq) /* Check whether we need to try again with another * failover server. */ - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = services_get_retry(req); if (ret != EOK) { @@ -244,7 +239,6 @@ services_get_done(struct tevent_req *subreq) /* An error occurred. */ if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -282,20 +276,12 @@ services_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } errno_t -services_get_recv(struct tevent_req *req, int *dp_error_out) +services_get_recv(struct tevent_req *req) { - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c index 4084d20684d..1095a97ee6a 100644 --- a/src/providers/ldap/ldap_id_subid.c +++ b/src/providers/ldap/ldap_id_subid.c @@ -36,7 +36,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, const char *extra_value, bool noexist_delete, bool set_non_posix); -int users_get_recv(struct tevent_req *req, int *dp_error_out); +int users_get_recv(struct tevent_req *req); static int subid_ranges_get_retry(struct tevent_req *req); static void subid_ranges_get_connect_done(struct tevent_req *subreq); @@ -58,8 +58,6 @@ struct subid_ranges_get_state { char *owner_name; char *owner_dn; const char **attrs; - - int dp_error; }; struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, @@ -82,7 +80,6 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, state->ctx = ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->owner_name = talloc_strdup(state, filter_value); if (!state->owner_name) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed\n"); @@ -135,16 +132,12 @@ static void subid_ranges_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct subid_ranges_get_state *state = tevent_req_data(req, - struct subid_ranges_get_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -217,14 +210,12 @@ static void subid_ranges_resolve_owner_done(struct tevent_req *subreq) struct tevent_req); struct subid_ranges_get_state *state = tevent_req_data(req, struct subid_ranges_get_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = users_get_recv(subreq, &dp_error); + ret = users_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -233,7 +224,6 @@ static void subid_ranges_resolve_owner_done(struct tevent_req *subreq) if (state->owner_dn == NULL) { DEBUG(SSSDBG_TRACE_FUNC, "Online lookup didn't find range owner '%s'\n", state->owner_name); - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } @@ -291,7 +281,6 @@ static void subid_ranges_get_done(struct tevent_req *subreq) struct tevent_req); struct subid_ranges_get_state *state = tevent_req_data(req, struct subid_ranges_get_state); - int dp_error = DP_ERR_FATAL; int ret; struct sysdb_attrs **results; size_t num_results; @@ -303,8 +292,8 @@ static void subid_ranges_get_done(struct tevent_req *subreq) return; } - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = subid_ranges_get_retry(req); if (ret != EOK) { @@ -316,7 +305,6 @@ static void subid_ranges_get_done(struct tevent_req *subreq) if (ret && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve subid ranges.\n"); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -337,19 +325,11 @@ static void subid_ranges_get_done(struct tevent_req *subreq) results[0]); } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } -int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out) +int subid_ranges_get_recv(struct tevent_req *req) { - struct subid_ranges_get_state *state = tevent_req_data(req, - struct subid_ranges_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index bbfa2620d04..593f3d8f91f 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -989,20 +989,12 @@ static void sdap_access_filter_connect_done(struct tevent_req *subreq) struct tevent_req); struct sdap_access_filter_req_ctx *state = tevent_req_data(req, struct sdap_access_filter_req_ctx); - int ret, dp_error; + int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - ret = sdap_access_decide_offline(state->cached_access); - if (ret == EOK) { - tevent_req_done(req); - return; - } - } - tevent_req_error(req, ret); return; } @@ -1032,7 +1024,7 @@ static void sdap_access_filter_connect_done(struct tevent_req *subreq) static void sdap_access_filter_done(struct tevent_req *subreq) { - int ret, tret, dp_error; + int ret, tret; size_t num_results; bool found = false; struct sysdb_attrs **results; @@ -1045,17 +1037,9 @@ static void sdap_access_filter_done(struct tevent_req *subreq) &num_results, &results); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - if (dp_error == DP_ERR_OK) { - /* retry */ - tret = sdap_access_filter_retry(req); - if (tret == EOK) { - return; - } - } else if (dp_error == DP_ERR_OFFLINE) { - ret = sdap_access_decide_offline(state->cached_access); - } else if (ret == ERR_INVALID_FILTER) { + if (ret == ERR_INVALID_FILTER) { sss_log(SSS_LOG_ERR, MALFORMED_FILTER, state->filter); DEBUG(SSSDBG_CRIT_FAILURE, MALFORMED_FILTER, state->filter); ret = ERR_ACCESS_DENIED; @@ -1558,24 +1542,16 @@ static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_access_ppolicy_req_ctx *state; - int ret, dp_error; + int ret; const char *ppolicy_dn; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - ret = sdap_access_decide_offline(state->cached_access); - if (ret == EOK) { - tevent_req_done(req); - return; - } - } - tevent_req_error(req, ret); return; } @@ -1674,7 +1650,7 @@ sdap_access_ppolicy_get_lockout_step(struct tevent_req *req) static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq) { - int ret, tret, dp_error; + int ret, tret; size_t num_results; bool pwdLockout = false; struct sysdb_attrs **results; @@ -1773,7 +1749,7 @@ static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq) done: if (ret != EAGAIN) { /* release connection */ - tret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + tret = sdap_id_op_done(state->sdap_op, ret); if (tret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_send() returned error [%d][%s]\n", @@ -1911,7 +1887,7 @@ is_account_locked(const char *pwdAccountLockedTime, static void sdap_access_ppolicy_step_done(struct tevent_req *subreq) { - int ret, tret, dp_error; + int ret, tret; size_t num_results; bool locked = false; const char *pwdAccountLockedTime; @@ -1926,22 +1902,11 @@ static void sdap_access_ppolicy_step_done(struct tevent_req *subreq) ret = sdap_get_generic_recv(subreq, state, &num_results, &results); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - if (dp_error == DP_ERR_OK) { - /* retry */ - tret = sdap_access_ppolicy_retry(req); - if (tret == EOK) { - return; - } - } else if (dp_error == DP_ERR_OFFLINE) { - ret = sdap_access_decide_offline(state->cached_access); - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_id_op_done() returned error [%d][%s]\n", - ret, sss_strerror(ret)); - } - + DEBUG(SSSDBG_CRIT_FAILURE, + "sdap_id_op_done() returned error [%d][%s]\n", + ret, sss_strerror(ret)); goto done; } diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c index 8a542f971c9..0ea1ce3de8d 100644 --- a/src/providers/ldap/sdap_async_autofs.c +++ b/src/providers/ldap/sdap_async_autofs.c @@ -647,8 +647,6 @@ struct sdap_autofs_setautomntent_state { struct sysdb_attrs *map; struct sysdb_attrs **entries; size_t entries_count; - - int dp_error; }; static void @@ -767,7 +765,6 @@ sdap_autofs_setautomntent_done(struct tevent_req *subreq) return; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } @@ -971,7 +968,6 @@ struct sdap_autofs_get_map_state { struct sdap_options *opts; struct sdap_id_op *sdap_op; const char *mapname; - int dp_error; }; static errno_t sdap_autofs_get_map_retry(struct tevent_req *req); @@ -994,7 +990,6 @@ struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, state->id_ctx = id_ctx; state->opts = id_ctx->opts; state->mapname = mapname; - state->dp_error = DP_ERR_FATAL; state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); if (!state->sdap_op) { @@ -1047,19 +1042,17 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) char *filter; char *safe_mapname; const char **attrs; - int dp_error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_autofs_get_map_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed " "[%d]: %s\n", ret, strerror(ret)); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1097,7 +1090,6 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), filter, attrs, NULL); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1120,8 +1112,8 @@ static void sdap_autofs_get_map_done(struct tevent_req *subreq) &reply); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error); - if (state->dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_autofs_get_map_retry(req); if (ret != EOK) { @@ -1159,17 +1151,10 @@ static void sdap_autofs_get_map_done(struct tevent_req *subreq) tevent_req_done(req); } -errno_t sdap_autofs_get_map_recv(struct tevent_req *req, - int *dp_error) +errno_t sdap_autofs_get_map_recv(struct tevent_req *req) { - struct sdap_autofs_get_map_state *state; - - state = tevent_req_data(req, struct sdap_autofs_get_map_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } @@ -1179,7 +1164,6 @@ struct sdap_autofs_get_entry_state { struct sdap_id_op *sdap_op; const char *mapname; const char *entryname; - int dp_error; }; static errno_t sdap_autofs_get_entry_retry(struct tevent_req *req); @@ -1204,7 +1188,6 @@ struct tevent_req *sdap_autofs_get_entry_send(TALLOC_CTX *mem_ctx, state->opts = id_ctx->opts; state->mapname = mapname; state->entryname = entryname; - state->dp_error = DP_ERR_FATAL; state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); if (!state->sdap_op) { @@ -1259,19 +1242,17 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq) char *safe_entryname; const char **attrs; const char *base_dn; - int dp_error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_autofs_get_entry_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed " "[%d]: %s\n", ret, strerror(ret)); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1329,7 +1310,6 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq) dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), filter, attrs, base_dn); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1359,8 +1339,8 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq) &reply); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error); - if (state->dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_autofs_get_entry_retry(req); if (ret != EOK) { @@ -1402,17 +1382,10 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq) return; } -errno_t sdap_autofs_get_entry_recv(struct tevent_req *req, - int *dp_error) +errno_t sdap_autofs_get_entry_recv(struct tevent_req *req) { - struct sdap_autofs_get_entry_state *state; - - state = tevent_req_data(req, struct sdap_autofs_get_entry_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c index 44cec84adb7..c48838028d6 100644 --- a/src/providers/ldap/sdap_async_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -150,23 +150,16 @@ static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq) { errno_t ret; - int dp_error; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, - "Backend is marked offline, retry later!\n"); - tevent_req_done(req); - } else { - DEBUG(SSSDBG_MINOR_FAILURE, - "Domain enumeration failed to connect to " \ - "LDAP server: (%d)[%s]\n", ret, strerror(ret)); - tevent_req_error(req, ret); - } + DEBUG(SSSDBG_MINOR_FAILURE, + "Domain enumeration failed to connect to " \ + "LDAP server: (%d)[%s]\n", ret, strerror(ret)); + tevent_req_error(req, ret); return false; } @@ -201,12 +194,11 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); errno_t ret; - int dp_error; ret = enum_users_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->user_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->user_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_dom_enum_ex_retry(req, state->user_op, sdap_dom_enum_ex_get_users); @@ -215,10 +207,6 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) return; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); - tevent_req_done(req); - return; } else if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, @@ -272,12 +260,11 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); int ret; - int dp_error; ret = enum_groups_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->group_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->group_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_dom_enum_ex_retry(req, state->group_op, sdap_dom_enum_ex_get_groups); @@ -286,10 +273,6 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) return; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); - tevent_req_done(req); - return; } else if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, @@ -341,12 +324,11 @@ static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); int ret; - int dp_error; ret = enum_services_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->svc_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->svc_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_dom_enum_ex_retry(req, state->user_op, sdap_dom_enum_ex_get_svcs); @@ -355,11 +337,7 @@ static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq) return; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); - tevent_req_done(req); - return; - } else if (ret != EOK && ret != ENOENT) { + } else if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "Service enumeration failed: %d: %s\n", ret, sss_strerror(ret)); diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index b0df2080b11..5ece72f9988 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -1815,12 +1815,11 @@ static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq) struct tevent_req *req; struct sdap_get_groups_state *state; int ret; - int dp_error; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_get_groups_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index d9348aba453..c5ce04dc079 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2907,10 +2907,9 @@ static void sdap_get_initgr_user_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { @@ -3442,7 +3441,7 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); errno_t ret; - ret = groups_get_recv(subreq, NULL); + ret = groups_get_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index a82b5b80a2e..0eed0ca0f2b 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -360,26 +360,25 @@ static void sdap_ad_resolve_sids_done(struct tevent_req *subreq) { struct sdap_ad_resolve_sids_state *state = NULL; struct tevent_req *req = NULL; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_resolve_sids_state); - ret = groups_get_recv(subreq, &dp_error); + ret = groups_get_recv(subreq); talloc_zfree(subreq); - if (ret == ENOENT && dp_error == DP_ERR_OK) { + if (ret == ENOENT) { /* Group was not found, we will ignore the error and continue with * next group. This may happen for example if the group is built-in, * but a custom search base is provided. */ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to resolve SID %s - will try next sid.\n", state->current_sid); - } else if (ret != EOK || dp_error != DP_ERR_OK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s [dp_error: %d, " - "ret: %d]: %s\n", state->current_sid, dp_error, - ret, strerror(ret)); + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s, " + "ret: %d]: %s\n", state->current_sid, ret, + strerror(ret)); goto done; } @@ -523,14 +522,13 @@ sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq) struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; struct tevent_req *req = NULL; int ret; - int dp_error = DP_ERR_FATAL; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { @@ -870,14 +868,13 @@ sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq) struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; struct tevent_req *req = NULL; int ret; - int dp_error = DP_ERR_FATAL; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { @@ -1160,7 +1157,6 @@ struct sdap_ad_get_domain_local_groups_state { struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *dom; - int dp_error; struct sdap_search_base **search_bases; struct sysdb_attrs **groups; @@ -1243,14 +1239,12 @@ sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq) struct tevent_req); struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, struct sdap_ad_get_domain_local_groups_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -1262,7 +1256,6 @@ sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq) state->group_hash, 0); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "rfc2307bis_nested_groups_send failed.\n"); - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } diff --git a/src/providers/ldap/sdap_async_resolver_enum.c b/src/providers/ldap/sdap_async_resolver_enum.c index 8c92260b7d1..bb4693b09c8 100644 --- a/src/providers/ldap/sdap_async_resolver_enum.c +++ b/src/providers/ldap/sdap_async_resolver_enum.c @@ -121,15 +121,16 @@ sdap_dom_resolver_enum_retry(struct tevent_req *req, static bool sdap_dom_resolver_enum_connected(struct tevent_req *subreq) { errno_t ret; - int dp_error; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_dom_resolver_enum_state *state = tevent_req_data(req, + struct sdap_dom_resolver_enum_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { + if (be_is_offline(state->id_ctx->be)) { DEBUG(SSSDBG_TRACE_FUNC, "Backend is marked offline, retry later!\n"); tevent_req_done(req); @@ -175,15 +176,14 @@ static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq) struct tevent_req); struct sdap_dom_resolver_enum_state *state; errno_t ret; - int dp_error; state = tevent_req_data(req, struct sdap_dom_resolver_enum_state); ret = enum_iphosts_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->iphost_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->iphost_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_dom_resolver_enum_retry(req, state->iphost_op, sdap_dom_resolver_enum_get_iphost); @@ -192,10 +192,6 @@ static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq) return; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); - tevent_req_done(req); - return; } else if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, @@ -252,15 +248,14 @@ static void sdap_dom_resolver_enum_ipnetwork_done(struct tevent_req *subreq) struct tevent_req); struct sdap_dom_resolver_enum_state *state; errno_t ret; - int dp_error; state = tevent_req_data(req, struct sdap_dom_resolver_enum_state); ret = enum_ipnetworks_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->ipnetwork_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->ipnetwork_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_dom_resolver_enum_retry(req, state->ipnetwork_op, sdap_dom_resolver_enum_get_ipnetwork); @@ -269,10 +264,6 @@ static void sdap_dom_resolver_enum_ipnetwork_done(struct tevent_req *subreq) return; } return; - } else if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); - tevent_req_done(req); - return; } else if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c index 28b65b639fe..0a9be2f9ce2 100644 --- a/src/providers/ldap/sdap_async_sudo.c +++ b/src/providers/ldap/sdap_async_sudo.c @@ -289,7 +289,6 @@ struct sdap_sudo_refresh_state { const char *delete_filter; bool update_usn; - int dp_error; size_t num_rules; }; @@ -326,7 +325,6 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, state->opts = id_ctx->opts; state->domain = id_ctx->be->domain; state->sysdb = id_ctx->be->domain->sysdb; - state->dp_error = DP_ERR_FATAL; state->update_usn = update_usn; state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); @@ -389,19 +387,17 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_sudo_refresh_state *state; - int dp_error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed " "[%d]: %s\n", ret, strerror(ret)); - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -413,7 +409,6 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) subreq = sdap_sudo_get_hostinfo_send(state, state->opts, state->sudo_ctx->id_ctx->be); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -425,7 +420,6 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) ret = sdap_sudo_refresh_sudoers(req); if (ret != EAGAIN) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); } } @@ -456,7 +450,6 @@ static void sdap_sudo_refresh_hostinfo_done(struct tevent_req *subreq) ret = sdap_sudo_refresh_sudoers(req); if (ret != EAGAIN) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ret); } } @@ -584,7 +577,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) struct sysdb_attrs **rules = NULL; size_t rules_count = 0; char *usn = NULL; - int dp_error; int ret; errno_t sret; bool in_transaction = false; @@ -595,8 +587,8 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->sdap_op, ret); + if (ret != EOK) { /* retry */ ret = sdap_sudo_refresh_retry(req); if (ret != EOK) { @@ -669,7 +661,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) } } - state->dp_error = dp_error; if (ret == EOK) { tevent_req_done(req); } else { @@ -679,7 +670,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - int *dp_error, size_t *num_rules) { struct sdap_sudo_refresh_state *state; @@ -688,8 +678,6 @@ int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx, TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - if (num_rules != NULL) { *num_rules = state->num_rules; } diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c index b9517905dff..463309d9ac2 100644 --- a/src/providers/ldap/sdap_autofs.c +++ b/src/providers/ldap/sdap_autofs.c @@ -60,8 +60,6 @@ struct sdap_autofs_enumerate_state { struct sdap_id_ctx *ctx; struct sdap_id_op *op; const char *map_name; - - int dp_error; }; static errno_t @@ -86,7 +84,6 @@ sdap_autofs_enumerate_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->ctx = ctx; - state->dp_error = DP_ERR_FATAL; state->map_name = map_name; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); @@ -133,14 +130,12 @@ sdap_autofs_enumerate_connect_done(struct tevent_req *subreq) struct tevent_req); struct sdap_autofs_enumerate_state *state = tevent_req_data(req, struct sdap_autofs_enumerate_state); - int dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -169,14 +164,13 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq) struct tevent_req); struct sdap_autofs_enumerate_state *state = tevent_req_data(req, struct sdap_autofs_enumerate_state); - int dp_error = DP_ERR_FATAL; int ret; ret = sdap_autofs_setautomntent_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = sdap_autofs_enumerate_retry(req); if (ret != EOK) { @@ -187,7 +181,6 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq) } if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -203,20 +196,12 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } static errno_t -sdap_autofs_enumerate_recv(struct tevent_req *req, int *dp_error_out) +sdap_autofs_enumerate_recv(struct tevent_req *req) { - struct sdap_autofs_enumerate_state *state = - tevent_req_data(req, struct sdap_autofs_enumerate_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -275,14 +260,12 @@ sdap_autofs_enumerate_handler_send(TALLOC_CTX *mem_ctx, static void sdap_autofs_enumerate_handler_done(struct tevent_req *subreq) { struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_autofs_enumerate_recv(subreq, &dp_error); + ret = sdap_autofs_enumerate_recv(subreq); talloc_zfree(subreq); - ret = dp_error_to_ret(ret, dp_error); if (ret != EOK) { tevent_req_error(req, ret); @@ -354,14 +337,12 @@ sdap_autofs_get_map_handler_send(TALLOC_CTX *mem_ctx, static void sdap_autofs_get_map_handler_done(struct tevent_req *subreq) { struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_autofs_get_map_recv(subreq, &dp_error); + ret = sdap_autofs_get_map_recv(subreq); talloc_zfree(subreq); - ret = dp_error_to_ret(ret, dp_error); if (ret != EOK) { tevent_req_error(req, ret); @@ -433,14 +414,12 @@ sdap_autofs_get_entry_handler_send(TALLOC_CTX *mem_ctx, static void sdap_autofs_get_entry_handler_done(struct tevent_req *subreq) { struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_autofs_get_entry_recv(subreq, &dp_error); + ret = sdap_autofs_get_entry_recv(subreq); talloc_zfree(subreq); - ret = dp_error_to_ret(ret, dp_error); if (ret != EOK) { tevent_req_error(req, ret); diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h index 4f30fbf1743..f89890caea4 100644 --- a/src/providers/ldap/sdap_autofs.h +++ b/src/providers/ldap/sdap_autofs.h @@ -47,15 +47,13 @@ struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, struct sdap_id_ctx *id_ctx, const char *mapname); -errno_t sdap_autofs_get_map_recv(struct tevent_req *req, - int *dp_error); +errno_t sdap_autofs_get_map_recv(struct tevent_req *req); struct tevent_req *sdap_autofs_get_entry_send(TALLOC_CTX *mem_ctx, struct sdap_id_ctx *id_ctx, const char *mapname, const char *entryname); -errno_t sdap_autofs_get_entry_recv(struct tevent_req *req, - int *dp_error); +errno_t sdap_autofs_get_entry_recv(struct tevent_req *req); #endif /* _SDAP_AUTOFS_H_ */ diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 9a0172bc6df..2491552a0ca 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -635,25 +635,18 @@ static void sdap_dyndns_get_addrs_done(struct tevent_req *subreq) { errno_t ret; - int dp_error; struct tevent_req *req; struct sdap_dyndns_get_addrs_state *state; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_dyndns_get_addrs_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, "No LDAP server is available, " - "dynamic DNS update is skipped in offline mode.\n"); - ret = ERR_DYNDNS_OFFLINE; - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to LDAP server: [%d](%s)\n", - ret, sss_strerror(ret)); - } + DEBUG(SSSDBG_OP_FAILURE, + "Failed to connect to LDAP server: [%d](%s)\n", + ret, sss_strerror(ret)); tevent_req_error(req, ret); return; } diff --git a/src/providers/ldap/sdap_hostid.c b/src/providers/ldap/sdap_hostid.c index ae8caaddb89..8b9b3a9ed7a 100644 --- a/src/providers/ldap/sdap_hostid.c +++ b/src/providers/ldap/sdap_hostid.c @@ -35,7 +35,6 @@ struct hosts_get_state { size_t count; struct sysdb_attrs **hosts; - int dp_error; }; static errno_t @@ -61,7 +60,6 @@ hosts_get_send(TALLOC_CTX *memctx, state->ev = ev; state->id_ctx = id_ctx; - state->dp_error = DP_ERR_FATAL; state->op = sdap_id_op_create(state, id_ctx->conn->conn_cache); if (!state->op) { @@ -111,14 +109,12 @@ hosts_get_connect_done(struct tevent_req *subreq) struct tevent_req); struct hosts_get_state *state = tevent_req_data(req, struct hosts_get_state); - int dp_error = DP_ERR_FATAL; errno_t ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -142,7 +138,6 @@ hosts_get_done(struct tevent_req *subreq) struct tevent_req); struct hosts_get_state *state = tevent_req_data(req, struct hosts_get_state); - int dp_error = DP_ERR_FATAL; errno_t ret; struct sysdb_attrs *attrs; time_t now = time(NULL); @@ -151,8 +146,8 @@ hosts_get_done(struct tevent_req *subreq) &state->count, &state->hosts); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = hosts_get_retry(req); if (ret != EOK) { @@ -203,10 +198,7 @@ hosts_get_done(struct tevent_req *subreq) goto done; } - dp_error = DP_ERR_OK; - done: - state->dp_error = dp_error; if (ret == EOK) { tevent_req_done(req); } else { @@ -215,16 +207,8 @@ hosts_get_done(struct tevent_req *subreq) } static errno_t -hosts_get_recv(struct tevent_req *req, - int *dp_error_out) +hosts_get_recv(struct tevent_req *req) { - struct hosts_get_state *state = tevent_req_data(req, - struct hosts_get_state); - - if (dp_error_out) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -266,7 +250,7 @@ sdap_hostid_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -279,17 +263,16 @@ static void sdap_hostid_handler_done(struct tevent_req *subreq) { struct sdap_hostid_handler_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_hostid_handler_state); - ret = hosts_get_recv(subreq, &dp_error); + ret = hosts_get_recv(subreq); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c index f9fe516708c..ea2b548d053 100644 --- a/src/providers/ldap/sdap_id_op.c +++ b/src/providers/ldap/sdap_id_op.c @@ -108,7 +108,7 @@ static void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn static int sdap_id_op_destroy(void *pvt); static bool sdap_id_op_can_reconnect(struct sdap_id_op *op); -static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret); +static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret); static int sdap_id_op_connect_state_destroy(void *pvt); static int sdap_id_op_connect_step(struct tevent_req *req); static void sdap_id_op_connect_done(struct tevent_req *subreq); @@ -518,7 +518,6 @@ struct sdap_id_op_connect_state { struct sdap_id_conn_ctx *id_conn; struct tevent_context *ev; struct sdap_id_op *op; - int dp_error; int result; }; @@ -848,7 +847,7 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq) int retry_ret = sdap_id_op_connect_step(op->connect_req); if (retry_ret != EOK) { can_retry = false; - sdap_id_op_connect_req_complete(op, DP_ERR_FATAL, retry_ret); + sdap_id_op_connect_req_complete(op, retry_ret); } continue; @@ -858,14 +857,14 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq) if (ret == EOK) { DEBUG(SSSDBG_TRACE_ALL, "notify connected to op #%d\n", notify_count); - sdap_id_op_connect_req_complete(op, DP_ERR_OK, ret); + sdap_id_op_connect_req_complete(op, ret); } else if (is_offline) { DEBUG(SSSDBG_TRACE_ALL, "notify offline to op #%d\n", notify_count); - sdap_id_op_connect_req_complete(op, DP_ERR_OFFLINE, EAGAIN); + sdap_id_op_connect_req_complete(op, EAGAIN); } else { DEBUG(SSSDBG_TRACE_ALL, "notify error to op #%d: %d [%s]\n", notify_count, ret, strerror(ret)); - sdap_id_op_connect_req_complete(op, DP_ERR_FATAL, ret); + sdap_id_op_connect_req_complete(op, ret); } } @@ -927,7 +926,7 @@ static void sdap_id_op_connect_reinit_done(struct tevent_req *req) } /* Mark operation connection request as complete */ -static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret) +static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret) { struct tevent_req *req = op->connect_req; struct sdap_id_op_connect_state *state; @@ -940,7 +939,6 @@ static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, op->connect_req = NULL; state = tevent_req_data(req, struct sdap_id_op_connect_state); - state->dp_error = dp_error; state->result = ret; /* Set the chain id to the one associated with this request. */ @@ -956,29 +954,28 @@ static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, /* Get the result of an asynchronous connect operation on sdap_id_op * - * In dp_error data provider error code is returned: - * DP_ERR_OK - connection established - * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * DP_ERR_FATAL - operation failed + * In data provider error code is returned: + * ERR_OK - connection established + * ERR_OFFLINE - backend is offline, operation result is set EAGAIN + * ERR_FATAL - operation failed */ -int sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error) +int sdap_id_op_connect_recv(struct tevent_req *req) { struct sdap_id_op_connect_state *state = tevent_req_data(req, struct sdap_id_op_connect_state); - *dp_error = state->dp_error; return state->result; } /* Report completion of LDAP operation and release associated connection. * Returns operation result (possible updated) passed in ret parameter. * - * In dp_error data provider error code is returned: - * DP_ERR_OK (operation result = EOK) - operation completed - * DP_ERR_OK (operation result != EOK) - operation can be retried - * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * DP_ERR_FATAL - operation failed */ -int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out) + * In data provider error code is returned: + * ERR_OK (operation result = EOK) - operation completed + * ERR_OK (operation result != EOK) - operation can be retried + * ERR_OFFLINE - backend is offline, operation result is set EAGAIN + * ERR_FATAL - operation failed */ +int sdap_id_op_done(struct sdap_id_op *op, int retval) { bool communication_error; struct sdap_id_conn_data *current_conn = op->conn_data; @@ -1005,36 +1002,29 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out) op->conn_cache->id_conn->service->name); } - int dp_err; if (retval == EOK) { - dp_err = DP_ERR_OK; + /* operation completed successfully */ + op->reconnect_retry_count = 0; } else if (be_is_offline(op->conn_cache->id_conn->id_ctx->be)) { /* if backend is already offline, just report offline, do not duplicate errors */ - dp_err = DP_ERR_OFFLINE; retval = EAGAIN; + op->reconnect_retry_count = 0; DEBUG(SSSDBG_TRACE_ALL, "falling back to offline data...\n"); } else if (communication_error) { /* communication error, can try to reconnect */ if (!sdap_id_op_can_reconnect(op)) { - dp_err = DP_ERR_FATAL; DEBUG(SSSDBG_TRACE_ALL, "too many communication failures, giving up...\n"); + op->reconnect_retry_count = 0; } else { - dp_err = DP_ERR_OK; retval = EAGAIN; + op->reconnect_retry_count++; + DEBUG(SSSDBG_TRACE_ALL, + "advising for connection retry #%i\n", op->reconnect_retry_count); } } else { - dp_err = DP_ERR_FATAL; - } - - if (dp_err == DP_ERR_OK && retval != EOK) { - /* reconnect retry */ - op->reconnect_retry_count++; - DEBUG(SSSDBG_TRACE_ALL, - "advising for connection retry #%i\n", op->reconnect_retry_count); - } else { - /* end of request */ + /* fatal error, cannot retry */ op->reconnect_retry_count = 0; } @@ -1043,7 +1033,6 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out) sdap_id_op_hook_conn_data(op, NULL); } - *dp_err_out = dp_err; return retval; } diff --git a/src/providers/ldap/sdap_id_op.h b/src/providers/ldap/sdap_id_op.h index f7f230a734a..1e0f9d8ce97 100644 --- a/src/providers/ldap/sdap_id_op.h +++ b/src/providers/ldap/sdap_id_op.h @@ -52,21 +52,21 @@ struct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op, /* Get the result of an asynchronous connect operation on sdap_id_op * * In dp_error data provider error code is returned: - * DP_ERR_OK - connection established - * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * DP_ERR_FATAL - operation failed + * ERR_OK - connection established + * ERR_OFFLINE - backend is offline, operation result is set EAGAIN + * ERR_FATAL - operation failed */ -int sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error); +int sdap_id_op_connect_recv(struct tevent_req *req); /* Report completion of LDAP operation and release associated connection. * Returns operation result (possible updated) passed in ret parameter. * * In dp_error data provider error code is returned: - * DP_ERR_OK (operation result = EOK) - operation completed - * DP_ERR_OK (operation result != EOK) - operation can be retried - * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * DP_ERR_FATAL - operation failed */ -int sdap_id_op_done(struct sdap_id_op*, int ret, int *dp_error); + * ERR_OK (operation result = EOK) - operation completed + * ERR_OK (operation result != EOK) - operation can be retried + * ERR_OFFLINE - backend is offline, operation result is set EAGAIN + * ERR_FATAL - operation failed */ +int sdap_id_op_done(struct sdap_id_op*, int ret); /* Get SDAP handle associated with operation by sdap_id_op_connect */ struct sdap_handle *sdap_id_op_handle(struct sdap_id_op *op); diff --git a/src/providers/ldap/sdap_iphost.c b/src/providers/ldap/sdap_iphost.c index ccf94a068f9..348709ebc0f 100644 --- a/src/providers/ldap/sdap_iphost.c +++ b/src/providers/ldap/sdap_iphost.c @@ -39,7 +39,6 @@ struct sdap_ip_host_get_state { char *filter; const char **attrs; - int dp_error; bool noexist_delete; }; @@ -71,7 +70,6 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx, state->id_ctx = id_ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; @@ -161,17 +159,15 @@ sdap_ip_host_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_ip_host_get_state *state; - int dp_error = DP_ERR_FATAL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ip_host_get_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -199,7 +195,6 @@ sdap_ip_host_get_done(struct tevent_req *subreq) errno_t ret; struct tevent_req *req; struct sdap_ip_host_get_state *state; - int dp_error = DP_ERR_FATAL; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ip_host_get_state); @@ -209,8 +204,8 @@ sdap_ip_host_get_done(struct tevent_req *subreq) /* Check whether we need to try again with another * failover server. */ - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = sdap_ip_host_get_retry(req); if (ret != EOK) { @@ -224,7 +219,6 @@ sdap_ip_host_get_done(struct tevent_req *subreq) /* An error occurred. */ if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -256,22 +250,12 @@ sdap_ip_host_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } static errno_t -sdap_ip_host_get_recv(struct tevent_req *req, - int *dp_error_out) +sdap_ip_host_get_recv(struct tevent_req *req) { - struct sdap_ip_host_get_state *state; - - state = tevent_req_data(req, struct sdap_ip_host_get_state); - - if (dp_error_out != NULL) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -324,7 +308,7 @@ sdap_iphost_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -337,17 +321,16 @@ static void sdap_ip_host_handler_done(struct tevent_req *subreq) { struct sdap_ip_host_handler_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ip_host_handler_state); - ret = sdap_ip_host_get_recv(subreq, &dp_error); + ret = sdap_ip_host_get_recv(subreq); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_ipnetwork.c b/src/providers/ldap/sdap_ipnetwork.c index eb7bbc4e66d..43fae2dba23 100644 --- a/src/providers/ldap/sdap_ipnetwork.c +++ b/src/providers/ldap/sdap_ipnetwork.c @@ -39,7 +39,6 @@ struct sdap_ipnetwork_get_state { char *filter; const char **attrs; - int dp_error; bool noexist_delete; }; @@ -71,7 +70,6 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx, state->id_ctx = id_ctx; state->sdom = sdom; state->conn = conn; - state->dp_error = DP_ERR_FATAL; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; @@ -161,17 +159,15 @@ sdap_ipnetwork_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_ipnetwork_get_state *state; - int dp_error = DP_ERR_FATAL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ipnetwork_get_state); - ret = sdap_id_op_connect_recv(subreq, &dp_error); + ret = sdap_id_op_connect_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -199,7 +195,6 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) errno_t ret; struct tevent_req *req; struct sdap_ipnetwork_get_state *state; - int dp_error = DP_ERR_FATAL; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ipnetwork_get_state); @@ -209,8 +204,8 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) /* Check whether we need to try again with another * failover server. */ - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { + ret = sdap_id_op_done(state->op, ret); + if (ret != EOK) { /* retry */ ret = sdap_ipnetwork_get_retry(req); if (ret != EOK) { @@ -224,7 +219,6 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) /* An error occurred. */ if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -257,22 +251,12 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } static errno_t -sdap_ipnetwork_get_recv(struct tevent_req *req, - int *dp_error_out) +sdap_ipnetwork_get_recv(struct tevent_req *req) { - struct sdap_ipnetwork_get_state *state; - - state = tevent_req_data(req, struct sdap_ipnetwork_get_state); - - if (dp_error_out != NULL) { - *dp_error_out = state->dp_error; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -326,7 +310,7 @@ sdap_ipnetwork_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -340,17 +324,16 @@ sdap_ipnetwork_handler_done(struct tevent_req *subreq) { struct sdap_ipnetwork_handler_state *state; struct tevent_req *req; - int dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ipnetwork_handler_state); - ret = sdap_ipnetwork_get_recv(subreq, &dp_error); + ret = sdap_ipnetwork_get_recv(subreq); talloc_zfree(subreq); /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c index cd26841c2f3..f70e6a2423f 100644 --- a/src/providers/ldap/sdap_online_check.c +++ b/src/providers/ldap/sdap_online_check.c @@ -207,7 +207,7 @@ sdap_online_check_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -242,7 +242,7 @@ static void sdap_online_check_handler_done(struct tevent_req *subreq) } /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } @@ -271,7 +271,7 @@ static void sdap_online_check_subdomains_done(struct tevent_req *subreq) /* We return the EOK of the initial online check here, the result of the * subdomains request is not important for the online-check request. */ - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, NULL); + dp_reply_std_set(&state->reply, EOK, NULL); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c index da7359d5135..562c8352459 100644 --- a/src/providers/ldap/sdap_refresh.c +++ b/src/providers/ldap/sdap_refresh.c @@ -150,19 +150,17 @@ static void sdap_refresh_done(struct tevent_req *subreq) struct sdap_refresh_state *state = NULL; struct tevent_req *req = NULL; const char *err_msg = NULL; - errno_t dp_error; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_refresh_state); - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err_msg); + ret = sdap_handle_acct_req_recv(subreq, &err_msg); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, " - "errno: %d]: %s\n", + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [errno: %d]: %s\n", be_req2str(state->account_req->entry_type), - dp_error, ret, err_msg); + ret, err_msg); goto done; } diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index 8cea919b940..a80347ce9bd 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -83,7 +83,7 @@ sdap_sudo_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); /* TODO For backward compatibility we always return EOK to DP now. */ tevent_req_done(req); @@ -96,7 +96,6 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq) { struct sdap_sudo_handler_state *state; struct tevent_req *req; - int dp_error; bool deleted; errno_t ret; @@ -105,17 +104,17 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq) switch (state->type) { case BE_REQ_SUDO_FULL: - ret = sdap_sudo_full_refresh_recv(subreq, &dp_error); + ret = sdap_sudo_full_refresh_recv(subreq); talloc_zfree(subreq); /* Reschedule the periodic task since the refresh was just finished * per user request. */ - if (ret == EOK && dp_error == DP_ERR_OK) { + if (ret == EOK) { be_ptask_postpone(state->sudo_ctx->full_refresh); } break; case BE_REQ_SUDO_RULES: - ret = sdap_sudo_rules_refresh_recv(subreq, &dp_error, &deleted); + ret = sdap_sudo_rules_refresh_recv(subreq, &deleted); talloc_zfree(subreq); if (ret == EOK && deleted == true) { ret = ENOENT; @@ -123,13 +122,12 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq) break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type); - dp_error = DP_ERR_FATAL; ret = ERR_INTERNAL; break; } /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, dp_error, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h index 85eeccf268a..df3f175cc78 100644 --- a/src/providers/ldap/sdap_sudo.h +++ b/src/providers/ldap/sdap_sudo.h @@ -57,27 +57,23 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - int *dp_error, size_t *num_rules); struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx); -int sdap_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error); +int sdap_sudo_full_refresh_recv(struct tevent_req *req); struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx); -int sdap_sudo_smart_refresh_recv(struct tevent_req *req, - int *dp_error); +int sdap_sudo_smart_refresh_recv(struct tevent_req *req); struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx, const char **rules); int sdap_sudo_rules_refresh_recv(struct tevent_req *req, - int *dp_error, bool *deleted); errno_t diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c index a484c6ae2c2..03b4f2b4242 100644 --- a/src/providers/ldap/sdap_sudo_refresh.c +++ b/src/providers/ldap/sdap_sudo_refresh.c @@ -33,7 +33,6 @@ struct sdap_sudo_full_refresh_state { struct sdap_id_ctx *id_ctx; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; - int dp_error; }; static void sdap_sudo_full_refresh_done(struct tevent_req *subreq); @@ -106,9 +105,9 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_full_refresh_state); - ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL); + ret = sdap_sudo_refresh_recv(state, subreq, NULL); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -136,23 +135,16 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq) tevent_req_done(req); } -int sdap_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error) +int sdap_sudo_full_refresh_recv(struct tevent_req *req) { - struct sdap_sudo_full_refresh_state *state = NULL; - state = tevent_req_data(req, struct sdap_sudo_full_refresh_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } struct sdap_sudo_smart_refresh_state { struct sdap_id_ctx *id_ctx; struct sysdb_ctx *sysdb; - int dp_error; }; static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq); @@ -179,7 +171,6 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, if (be_ptask_running(sudo_ctx->full_refresh)) { DEBUG(SSSDBG_TRACE_FUNC, "Skipping smart refresh because " "there is ongoing full refresh.\n"); - state->dp_error = DP_ERR_OK; ret = EOK; goto immediately; } @@ -245,9 +236,9 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state); - ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL); + ret = sdap_sudo_refresh_recv(state, subreq, NULL); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -262,23 +253,16 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq) tevent_req_done(req); } -int sdap_sudo_smart_refresh_recv(struct tevent_req *req, - int *dp_error) +int sdap_sudo_smart_refresh_recv(struct tevent_req *req) { - struct sdap_sudo_smart_refresh_state *state = NULL; - state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; - return EOK; } struct sdap_sudo_rules_refresh_state { struct sdap_id_ctx *id_ctx; size_t num_rules; - int dp_error; bool deleted; }; @@ -396,10 +380,9 @@ static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state); - ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, - &downloaded_rules_num); + ret = sdap_sudo_refresh_recv(state, subreq, &downloaded_rules_num); talloc_zfree(subreq); - if (ret != EOK || state->dp_error != DP_ERR_OK) { + if (ret != EOK) { goto done; } @@ -415,7 +398,6 @@ static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq) } int sdap_sudo_rules_refresh_recv(struct tevent_req *req, - int *dp_error, bool *deleted) { struct sdap_sudo_rules_refresh_state *state = NULL; @@ -423,7 +405,6 @@ int sdap_sudo_rules_refresh_recv(struct tevent_req *req, TEVENT_REQ_RETURN_ON_ERROR(req); - *dp_error = state->dp_error; *deleted = state->deleted; return EOK; @@ -445,9 +426,7 @@ sdap_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx, static errno_t sdap_sudo_ptask_full_refresh_recv(struct tevent_req *req) { - int dp_error; - - return sdap_sudo_full_refresh_recv(req, &dp_error); + return sdap_sudo_full_refresh_recv(req); } static struct tevent_req * @@ -466,9 +445,7 @@ sdap_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx, static errno_t sdap_sudo_ptask_smart_refresh_recv(struct tevent_req *req) { - int dp_error; - - return sdap_sudo_smart_refresh_recv(req, &dp_error); + return sdap_sudo_smart_refresh_recv(req); } errno_t diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c index 6e080965f97..6c471932650 100644 --- a/src/providers/minimal/minimal_id.c +++ b/src/providers/minimal/minimal_id.c @@ -33,7 +33,6 @@ struct minimal_handle_acct_req_state { struct dp_id_data *ar; const char *err; - int dp_error; int minimal_ret; int sdap_ret; }; @@ -141,17 +140,13 @@ static void minimal_handle_acct_req_done(struct tevent_req *subreq) static errno_t minimal_handle_acct_req_recv(struct tevent_req *req, - int *_dp_error, const char **_err, + const char **_err, int *minimal_ret) { struct minimal_handle_acct_req_state *state; state = tevent_req_data(req, struct minimal_handle_acct_req_state); - if (_dp_error) { - *_dp_error = DP_ERR_OK; - } - if (_err) { *_err = state->err; } @@ -204,7 +199,7 @@ minimal_account_info_handler_send(TALLOC_CTX *mem_ctx, return req; immediately: - dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + dp_reply_std_set(&state->reply, ret, NULL); tevent_req_done(req); tevent_req_post(req, params->ev); @@ -217,16 +212,15 @@ static void minimal_account_info_handler_done(struct tevent_req *subreq) struct minimal_account_info_handler_state *state; struct tevent_req *req; const char *error_msg = NULL; - int dp_error = DP_ERR_FATAL; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct minimal_account_info_handler_state); - ret = minimal_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL); + ret = minimal_handle_acct_req_recv(subreq, &error_msg, NULL); talloc_zfree(subreq); - dp_reply_std_set(&state->reply, dp_error, ret, error_msg); + dp_reply_std_set(&state->reply, ret, error_msg); tevent_req_done(req); } diff --git a/src/providers/proxy/proxy_hosts.c b/src/providers/proxy/proxy_hosts.c index d2248293039..2249bf12cd6 100644 --- a/src/providers/proxy/proxy_hosts.c +++ b/src/providers/proxy/proxy_hosts.c @@ -704,7 +704,7 @@ proxy_hosts_info(TALLOC_CTX *mem_ctx, break; default: - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, EINVAL, "Invalid filter type"); return reply; } @@ -716,11 +716,11 @@ proxy_hosts_info(TALLOC_CTX *mem_ctx, be_mark_offline(be_ctx); } - dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL); + dp_reply_std_set(&reply, ret, NULL); return reply; } - dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL); + dp_reply_std_set(&reply, EOK, NULL); return reply; } diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c index b1d0c22ad13..4b4147e0416 100644 --- a/src/providers/proxy/proxy_id.c +++ b/src/providers/proxy/proxy_id.c @@ -1748,7 +1748,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx, /* Proxy provider does not support security ID lookups. */ if (data->filter_type == BE_FILTER_SECID) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENOSYS, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Security lookups are not supported"); return reply; } @@ -1767,14 +1767,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx, case BE_FILTER_IDNUM: uid = (uid_t) strtouint32(data->filter_value, &endptr, 10); if (errno || *endptr || (data->filter_value == endptr)) { - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid attr type"); return reply; } ret = get_pw_uid(ctx, domain, uid); break; default: - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } @@ -1791,14 +1791,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx, case BE_FILTER_IDNUM: gid = (gid_t) strtouint32(data->filter_value, &endptr, 10); if (errno || *endptr || (data->filter_value == endptr)) { - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid attr type"); return reply; } ret = get_gr_gid(mem_ctx, ctx, sysdb, domain, gid, 0); break; default: - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } @@ -1806,12 +1806,12 @@ proxy_account_info(TALLOC_CTX *mem_ctx, case BE_REQ_INITGROUPS: /* init groups for user */ if (data->filter_type != BE_FILTER_NAME) { - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } if (ctx->ops.initgroups_dyn == NULL) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, + dp_reply_std_set(&reply, ERR_INTERNAL, "Initgroups call not supported"); return reply; } @@ -1820,13 +1820,13 @@ proxy_account_info(TALLOC_CTX *mem_ctx, case BE_REQ_NETGROUP: if (data->filter_type != BE_FILTER_NAME) { - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL || ctx->ops.endnetgrent == NULL) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, + dp_reply_std_set(&reply, ERR_INTERNAL, "Netgroups are not supported"); return reply; } @@ -1838,7 +1838,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx, switch (data->filter_type) { case BE_FILTER_NAME: if (ctx->ops.getservbyname_r == NULL) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, + dp_reply_std_set(&reply, ERR_INTERNAL, "Services are not supported"); return reply; } @@ -1848,7 +1848,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx, break; case BE_FILTER_IDNUM: if (ctx->ops.getservbyport_r == NULL) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, + dp_reply_std_set(&reply, ERR_INTERNAL, "Services are not supported"); return reply; } @@ -1860,14 +1860,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx, if (!ctx->ops.setservent || !ctx->ops.getservent_r || !ctx->ops.endservent) { - dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV, + dp_reply_std_set(&reply, ERR_INTERNAL, "Services are not supported"); return reply; } ret = enum_services(ctx, sysdb, domain); break; default: - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } @@ -1878,7 +1878,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected filter type for lookup by cert: %d\n", data->filter_type); - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Unexpected filter type for lookup by cert"); return reply; } @@ -1896,7 +1896,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx, break; default: /*fail*/ - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, ERR_INVALID_FILTER, "Invalid filter type"); return reply; } @@ -1908,11 +1908,11 @@ proxy_account_info(TALLOC_CTX *mem_ctx, be_mark_offline(be_ctx); } - dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL); + dp_reply_std_set(&reply, ret, NULL); return reply; } - dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL); + dp_reply_std_set(&reply, EOK, NULL); return reply; } diff --git a/src/providers/proxy/proxy_ipnetworks.c b/src/providers/proxy/proxy_ipnetworks.c index 73919b8352d..8c07754cde8 100644 --- a/src/providers/proxy/proxy_ipnetworks.c +++ b/src/providers/proxy/proxy_ipnetworks.c @@ -565,7 +565,7 @@ proxy_nets_info(TALLOC_CTX *mem_ctx, break; default: - dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL, + dp_reply_std_set(&reply, EINVAL, "Invalid filter type"); return reply; } @@ -577,11 +577,11 @@ proxy_nets_info(TALLOC_CTX *mem_ctx, be_mark_offline(be_ctx); } - dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL); + dp_reply_std_set(&reply, ret, NULL); return reply; } - dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL); + dp_reply_std_set(&reply, EOK, NULL); return reply; } diff --git a/src/providers/simple/simple_access_check.c b/src/providers/simple/simple_access_check.c index 8adfb1e263d..b2ddda88e4d 100644 --- a/src/providers/simple/simple_access_check.c +++ b/src/providers/simple/simple_access_check.c @@ -369,10 +369,10 @@ static void simple_resolve_group_done(struct tevent_req *subreq) return; } - if (reply->dp_error != DP_ERR_OK) { + if (reply->error != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, - "Cannot refresh data from DP: %u,%u: %s\n", - reply->dp_error, reply->error, reply->message); + "Cannot refresh data from DP: %u: %s\n", + reply->error, reply->message); tevent_req_error(req, EIO); return; } diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h index 437e1be7710..6764d09f5ef 100644 --- a/src/responder/common/cache_req/cache_req_private.h +++ b/src/responder/common/cache_req/cache_req_private.h @@ -208,9 +208,7 @@ cache_req_well_known_sid_result(TALLOC_CTX *mem_ctx, bool cache_req_common_process_dp_reply(struct cache_req *cr, errno_t ret, - uint16_t err_maj, - uint32_t err_min, - const char *err_msg); + uint32_t err); bool cache_req_common_dp_recv(struct tevent_req *subreq, 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 00b9383ee4c..e4fbb091c0b 100644 --- a/src/responder/common/cache_req/plugins/cache_req_common.c +++ b/src/responder/common/cache_req/plugins/cache_req_common.c @@ -122,9 +122,7 @@ cache_req_well_known_sid_result(TALLOC_CTX *mem_ctx, bool cache_req_common_process_dp_reply(struct cache_req *cr, errno_t ret, - uint16_t err_maj, - uint32_t err_min, - const char *err_msg) + uint32_t err) { bool bret; @@ -142,10 +140,10 @@ cache_req_common_process_dp_reply(struct cache_req *cr, goto done; } - if (err_maj) { + if (err) { CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr, - "Data Provider Error: %u, %u, %s\n", - (unsigned int)err_maj, (unsigned int)err_min, err_msg); + "Data Provider Error: %u, %s\n", + (unsigned int)err, sss_strerror(err)); CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Due to an error we will return cached data\n"); @@ -163,16 +161,12 @@ bool cache_req_common_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { - const char *err_msg; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; bool bret; - /* Use subreq as memory context so err_msg is freed with it. */ - ret = sss_dp_get_account_recv(subreq, subreq, &err_maj, &err_min, &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_get_account_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c index ae468b3d24e..3f704d19fdc 100644 --- a/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c +++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c @@ -63,15 +63,11 @@ cache_req_enum_host_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c index e03bf6ad52b..8a6601312ba 100644 --- a/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c +++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c @@ -63,15 +63,11 @@ cache_req_enum_ip_networks_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c index 1ecfc979868..1e00cb65395 100644 --- a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c +++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c @@ -108,15 +108,11 @@ cache_req_ip_host_by_addr_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c index b5f33ee5f78..df5fa91098a 100644 --- a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c @@ -103,15 +103,11 @@ cache_req_ip_host_by_name_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c index 238d104ea38..9f2e37f71ac 100644 --- a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c +++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c @@ -108,15 +108,11 @@ cache_req_ip_network_by_addr_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c index c02bc065a1d..0d3ba853ba6 100644 --- a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c @@ -103,15 +103,11 @@ cache_req_ip_network_by_name_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { bool bret; - uint16_t err_maj; - uint32_t err_min; + uint32_t err; errno_t ret; - const char *err_msg; - ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min, - &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sss_dp_resolver_get_recv(subreq, subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c index d5d39de98d1..889d60ca4c3 100644 --- a/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c @@ -89,17 +89,12 @@ static bool cache_req_host_by_name_dp_recv(struct tevent_req *subreq, struct cache_req *cr) { - const char *err_msg; - dbus_uint16_t err_maj; - dbus_uint32_t err_min; + dbus_uint32_t err; errno_t ret; bool bret; - /* Use subreq as memory context so err_msg is freed with it. */ - ret = sbus_call_dp_dp_hostHandler_recv(subreq, subreq, &err_maj, - &err_min, &err_msg); - bret = cache_req_common_process_dp_reply(cr, ret, err_maj, - err_min, err_msg); + ret = sbus_call_dp_dp_hostHandler_recv(subreq, &err); + bret = cache_req_common_process_dp_reply(cr, ret, err); return bret; } diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index e2dacc289fa..b17bd6def4b 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -259,9 +259,7 @@ sss_dp_get_account_send(TALLOC_CTX *mem_ctx, errno_t sss_dp_get_account_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_error_message); + uint32_t *_error); struct tevent_req * sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx, @@ -275,9 +273,7 @@ sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx, errno_t sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_error_message); + uint32_t *_error); bool sss_utf8_check(const uint8_t *s, size_t n); diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c index 5db22ec9a68..03db215e0ff 100644 --- a/src/responder/common/responder_dp.c +++ b/src/responder/common/responder_dp.c @@ -114,9 +114,7 @@ sss_dp_get_account_filter(TALLOC_CTX *mem_ctx, } struct sss_dp_get_account_state { - uint16_t dp_error; uint32_t error; - const char *error_message; }; static void sss_dp_get_account_done(struct tevent_req *subreq); @@ -210,9 +208,7 @@ static void sss_dp_get_account_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sss_dp_get_account_state); - ret = sbus_call_dp_dp_getAccountInfo_recv(state, subreq, &state->dp_error, - &state->error, - &state->error_message); + ret = sbus_call_dp_dp_getAccountInfo_recv(subreq, &state->error); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); @@ -226,26 +222,20 @@ static void sss_dp_get_account_done(struct tevent_req *subreq) errno_t sss_dp_get_account_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_error_message) + uint32_t *_error) { struct sss_dp_get_account_state *state; state = tevent_req_data(req, struct sss_dp_get_account_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_dp_error = state->dp_error; *_error = state->error; - *_error_message = talloc_steal(mem_ctx, state->error_message); return EOK; } struct sss_dp_resolver_get_state { - uint16_t dp_error; uint32_t error; - const char *error_message; }; static void sss_dp_resolver_get_done(struct tevent_req *subreq); @@ -334,10 +324,7 @@ static void sss_dp_resolver_get_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sss_dp_resolver_get_state); - ret = sbus_call_dp_dp_resolverHandler_recv(state, subreq, - &state->dp_error, - &state->error, - &state->error_message); + ret = sbus_call_dp_dp_resolverHandler_recv(subreq, &state->error); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); @@ -351,18 +338,14 @@ static void sss_dp_resolver_get_done(struct tevent_req *subreq) errno_t sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_error_message) + uint32_t *_error) { struct sss_dp_resolver_get_state *state; state = tevent_req_data(req, struct sss_dp_resolver_get_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_dp_error = state->dp_error; *_error = state->error; - *_error_message = talloc_steal(mem_ctx, state->error_message); return EOK; } diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c index f179eb14635..4f9ce00b36f 100644 --- a/src/responder/common/responder_get_domains.c +++ b/src/responder/common/responder_get_domains.c @@ -27,9 +27,7 @@ /* ========== Get subdomains for a domain ================= */ struct get_subdomains_state { - uint16_t dp_error; uint32_t error; - const char *error_message; }; static void get_subdomains_done(struct tevent_req *subreq); @@ -89,11 +87,9 @@ static void get_subdomains_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct get_subdomains_state); - ret = sbus_call_dp_dp_getDomains_recv(state, subreq, &state->dp_error, - &state->error, &state->error_message); + ret = sbus_call_dp_dp_getDomains_recv(subreq, &state->error); talloc_zfree(subreq); if (ret != EOK) { - state->dp_error = DP_ERR_FATAL; state->error = ret; } @@ -104,18 +100,14 @@ static void get_subdomains_done(struct tevent_req *subreq) static errno_t get_subdomains_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char **_error_message) + uint32_t *_error) { struct get_subdomains_state *state; state = tevent_req_data(req, struct get_subdomains_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_dp_error = state->dp_error; *_error = state->error; - *_error_message = talloc_steal(mem_ctx, state->error_message); return EOK; } @@ -230,11 +222,9 @@ sss_dp_get_domains_process(struct tevent_req *subreq) struct tevent_req); struct sss_dp_get_domains_state *state = tevent_req_data(req, struct sss_dp_get_domains_state); - uint16_t dp_err; - uint32_t dp_ret; - const char *err_msg; + uint32_t err; - ret = get_subdomains_recv(subreq, subreq, &dp_err, &dp_ret, &err_msg); + ret = get_subdomains_recv(subreq, subreq, &err); talloc_zfree(subreq); if (ret != EOK) { goto fail; @@ -630,7 +620,6 @@ errno_t sss_parse_inp_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct sss_dp_get_account_domain_state { - uint16_t dp_error; uint32_t error; const char *domain_name; }; @@ -738,7 +727,7 @@ static void sss_dp_get_account_domain_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sss_dp_get_account_domain_state); - ret = sbus_call_dp_dp_getAccountDomain_recv(state, subreq, &state->dp_error, + ret = sbus_call_dp_dp_getAccountDomain_recv(state, subreq, &state->error, &state->domain_name); talloc_zfree(subreq); @@ -749,12 +738,11 @@ static void sss_dp_get_account_domain_done(struct tevent_req *subreq) return; } - if (state->dp_error != DP_ERR_OK) { + if (state->error != ERR_OK) { DEBUG(state->error == ERR_GET_ACCT_DOM_NOT_SUPPORTED ? SSSDBG_TRACE_INTERNAL : SSSDBG_IMPORTANT_INFO, - "Data Provider Error: %u, %u [%s]\n", - (unsigned int)state->dp_error, (unsigned int)state->error, - sss_strerror(state->error)); + "Data Provider Error: %u [%s]\n", + (unsigned int)state->error, sss_strerror(state->error)); tevent_req_error(req, state->error ? state->error : EIO); return; } diff --git a/src/responder/sudo/sudosrv_dp.c b/src/responder/sudo/sudosrv_dp.c index 20832b1ea3f..7c8fbd349ea 100644 --- a/src/responder/sudo/sudosrv_dp.c +++ b/src/responder/sudo/sudosrv_dp.c @@ -137,9 +137,7 @@ sss_dp_get_sudoers_msg(TALLOC_CTX *mem_ctx, } struct sss_dp_get_sudoers_state { - uint16_t dp_error; uint32_t error; - const char *error_message; }; static void sss_dp_get_sudoers_done(struct tevent_req *subreq); @@ -209,9 +207,7 @@ static void sss_dp_get_sudoers_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sss_dp_get_sudoers_state); - ret = sbus_call_dp_dp_sudoHandler_recv(state, subreq, &state->dp_error, - &state->error, - &state->error_message); + ret = sbus_call_dp_dp_sudoHandler_recv(subreq, &state->error); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); @@ -225,18 +221,14 @@ static void sss_dp_get_sudoers_done(struct tevent_req *subreq) errno_t sss_dp_get_sudoers_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char ** _error_message) + uint32_t *_error) { struct sss_dp_get_sudoers_state *state; state = tevent_req_data(req, struct sss_dp_get_sudoers_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_dp_error = state->dp_error; *_error = state->error; - *_error_message = talloc_steal(mem_ctx, state->error_message); return EOK; } diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c index 1bcfc377ace..f364fe63379 100644 --- a/src/responder/sudo/sudosrv_get_sudorules.c +++ b/src/responder/sudo/sudosrv_get_sudorules.c @@ -663,30 +663,19 @@ static void sudosrv_refresh_rules_done(struct tevent_req *subreq) { struct sudosrv_refresh_rules_state *state; struct tevent_req *req; - dbus_uint16_t err_maj; - dbus_uint32_t err_min; - const char *err_msg; + uint32_t err; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sudosrv_refresh_rules_state); - ret = sss_dp_get_sudoers_recv(state, subreq, &err_maj, &err_min, &err_msg); + ret = sss_dp_get_sudoers_recv(state, subreq, &err); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh rules [%d]: %s\n", ret, sss_strerror(ret)); goto done; - } else if (err_maj != 0 || err_min != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Unable to get information from Data Provider, " - "Error: %u, %u, %s\n", - (unsigned int)err_maj, (unsigned int)err_min, - (err_msg == NULL ? "(null)" : err_msg)); - goto done; - } - - if (err_min == ENOENT) { + } else if (err == ENOENT) { DEBUG(SSSDBG_TRACE_INTERNAL, "Some expired rules were removed from the server, scheduling " "full refresh out of band\n"); @@ -701,6 +690,13 @@ static void sudosrv_refresh_rules_done(struct tevent_req *subreq) } tevent_req_set_callback(subreq, sudosrv_dp_oob_req_done, NULL); + } else if (err != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unable to get information from Data Provider, " + "Error: %u, %s\n", + (unsigned int)err, + sss_strerror(err)); + goto done; } ret = EOK; diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h index 157afaa4492..0537a4a8eae 100644 --- a/src/responder/sudo/sudosrv_private.h +++ b/src/responder/sudo/sudosrv_private.h @@ -105,8 +105,6 @@ sss_dp_get_sudoers_send(TALLOC_CTX *mem_ctx, errno_t sss_dp_get_sudoers_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t *_dp_error, - uint32_t *_error, - const char ** _error_message); + uint32_t *_error); #endif /* _SUDOSRV_PRIVATE_H_ */ diff --git a/src/sss_iface/sbus_sss_arguments.c b/src/sss_iface/sbus_sss_arguments.c index 14d705ba89e..6af387db7ee 100644 --- a/src/sss_iface/sbus_sss_arguments.c +++ b/src/sss_iface/sbus_sss_arguments.c @@ -201,55 +201,6 @@ errno_t _sbus_sss_invoker_write_q return EOK; } -errno_t _sbus_sss_invoker_read_qus - (TALLOC_CTX *mem_ctx, - DBusMessageIter *iter, - struct _sbus_sss_invoker_args_qus *args) -{ - errno_t ret; - - ret = sbus_iterator_read_q(iter, &args->arg0); - if (ret != EOK) { - return ret; - } - - ret = sbus_iterator_read_u(iter, &args->arg1); - if (ret != EOK) { - return ret; - } - - ret = sbus_iterator_read_s(mem_ctx, iter, &args->arg2); - if (ret != EOK) { - return ret; - } - - return EOK; -} - -errno_t _sbus_sss_invoker_write_qus - (DBusMessageIter *iter, - struct _sbus_sss_invoker_args_qus *args) -{ - errno_t ret; - - ret = sbus_iterator_write_q(iter, args->arg0); - if (ret != EOK) { - return ret; - } - - ret = sbus_iterator_write_u(iter, args->arg1); - if (ret != EOK) { - return ret; - } - - ret = sbus_iterator_write_s(iter, args->arg2); - if (ret != EOK) { - return ret; - } - - return EOK; -} - errno_t _sbus_sss_invoker_read_s (TALLOC_CTX *mem_ctx, DBusMessageIter *iter, @@ -445,6 +396,45 @@ errno_t _sbus_sss_invoker_write_u return EOK; } +errno_t _sbus_sss_invoker_read_us + (TALLOC_CTX *mem_ctx, + DBusMessageIter *iter, + struct _sbus_sss_invoker_args_us *args) +{ + errno_t ret; + + ret = sbus_iterator_read_u(iter, &args->arg0); + if (ret != EOK) { + return ret; + } + + ret = sbus_iterator_read_s(mem_ctx, iter, &args->arg1); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +errno_t _sbus_sss_invoker_write_us + (DBusMessageIter *iter, + struct _sbus_sss_invoker_args_us *args) +{ + errno_t ret; + + ret = sbus_iterator_write_u(iter, args->arg0); + if (ret != EOK) { + return ret; + } + + ret = sbus_iterator_write_s(iter, args->arg1); + if (ret != EOK) { + return ret; + } + + return EOK; +} + errno_t _sbus_sss_invoker_read_usq (TALLOC_CTX *mem_ctx, DBusMessageIter *iter, diff --git a/src/sss_iface/sbus_sss_arguments.h b/src/sss_iface/sbus_sss_arguments.h index 41067aae6c9..1e561b10ee4 100644 --- a/src/sss_iface/sbus_sss_arguments.h +++ b/src/sss_iface/sbus_sss_arguments.h @@ -118,23 +118,6 @@ _sbus_sss_invoker_write_q (DBusMessageIter *iter, struct _sbus_sss_invoker_args_q *args); -struct _sbus_sss_invoker_args_qus { - uint16_t arg0; - uint32_t arg1; - const char * arg2; -}; - -errno_t -_sbus_sss_invoker_read_qus - (TALLOC_CTX *mem_ctx, - DBusMessageIter *iter, - struct _sbus_sss_invoker_args_qus *args); - -errno_t -_sbus_sss_invoker_write_qus - (DBusMessageIter *iter, - struct _sbus_sss_invoker_args_qus *args); - struct _sbus_sss_invoker_args_s { const char * arg0; }; @@ -215,6 +198,22 @@ _sbus_sss_invoker_write_u (DBusMessageIter *iter, struct _sbus_sss_invoker_args_u *args); +struct _sbus_sss_invoker_args_us { + uint32_t arg0; + const char * arg1; +}; + +errno_t +_sbus_sss_invoker_read_us + (TALLOC_CTX *mem_ctx, + DBusMessageIter *iter, + struct _sbus_sss_invoker_args_us *args); + +errno_t +_sbus_sss_invoker_write_us + (DBusMessageIter *iter, + struct _sbus_sss_invoker_args_us *args); + struct _sbus_sss_invoker_args_usq { uint32_t arg0; const char * arg1; diff --git a/src/sss_iface/sbus_sss_client_async.c b/src/sss_iface/sbus_sss_client_async.c index 1391d8de0ea..45f8c1d7bbb 100644 --- a/src/sss_iface/sbus_sss_client_async.c +++ b/src/sss_iface/sbus_sss_client_async.c @@ -212,30 +212,30 @@ sbus_method_in_pam_data_out_pam_response_recv return EOK; } -struct sbus_method_in_raw_out_qus_state { - struct _sbus_sss_invoker_args_qus *out; +struct sbus_method_in_raw_out_u_state { + struct _sbus_sss_invoker_args_u *out; }; -static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_raw_out_u_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_raw_out_qus_send +sbus_method_in_raw_out_u_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, DBusMessage *raw_message) { - struct sbus_method_in_raw_out_qus_state *state; + struct sbus_method_in_raw_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_raw_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_raw_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -254,7 +254,7 @@ sbus_method_in_raw_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_raw_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_raw_out_u_done, req); ret = EAGAIN; @@ -267,15 +267,15 @@ sbus_method_in_raw_out_qus_send return req; } -static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_raw_out_u_done(struct tevent_req *subreq) { - struct sbus_method_in_raw_out_qus_state *state; + struct sbus_method_in_raw_out_u_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_raw_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_raw_out_u_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -284,7 +284,7 @@ static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -295,21 +295,16 @@ static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_raw_out_qus_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) +sbus_method_in_raw_out_u_recv + (struct tevent_req *req, + uint32_t* _arg0) { - struct sbus_method_in_raw_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_raw_out_qus_state); + struct sbus_method_in_raw_out_u_state *state; + state = tevent_req_data(req, struct sbus_method_in_raw_out_u_state); TEVENT_REQ_RETURN_ON_ERROR(req); *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); return EOK; } @@ -521,15 +516,15 @@ sbus_method_in_s_out_b_recv return EOK; } -struct sbus_method_in_s_out_qus_state { +struct sbus_method_in_s_out_s_state { struct _sbus_sss_invoker_args_s in; - struct _sbus_sss_invoker_args_qus *out; + struct _sbus_sss_invoker_args_s *out; }; -static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_s_out_s_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_s_out_qus_send +sbus_method_in_s_out_s_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -539,18 +534,18 @@ sbus_method_in_s_out_qus_send const char *method, const char * arg0) { - struct sbus_method_in_s_out_qus_state *state; + struct sbus_method_in_s_out_s_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_s_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_s); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -569,7 +564,7 @@ sbus_method_in_s_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_s_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_s_out_s_done, req); ret = EAGAIN; @@ -582,15 +577,15 @@ sbus_method_in_s_out_qus_send return req; } -static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_s_out_s_done(struct tevent_req *subreq) { - struct sbus_method_in_s_out_qus_state *state; + struct sbus_method_in_s_out_s_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_s_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_s_out_s_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -599,7 +594,7 @@ static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_s, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -610,34 +605,30 @@ static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_s_out_qus_recv +sbus_method_in_s_out_s_recv (TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) + const char ** _arg0) { - struct sbus_method_in_s_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_s_out_qus_state); + struct sbus_method_in_s_out_s_state *state; + state = tevent_req_data(req, struct sbus_method_in_s_out_s_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); + *_arg0 = talloc_steal(mem_ctx, state->out->arg0); return EOK; } -struct sbus_method_in_s_out_s_state { +struct sbus_method_in_s_out_u_state { struct _sbus_sss_invoker_args_s in; - struct _sbus_sss_invoker_args_s *out; + struct _sbus_sss_invoker_args_u *out; }; -static void sbus_method_in_s_out_s_done(struct tevent_req *subreq); +static void sbus_method_in_s_out_u_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_s_out_s_send +sbus_method_in_s_out_u_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -647,18 +638,18 @@ sbus_method_in_s_out_s_send const char *method, const char * arg0) { - struct sbus_method_in_s_out_s_state *state; + struct sbus_method_in_s_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_s_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_s); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -677,7 +668,7 @@ sbus_method_in_s_out_s_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_s_out_s_done, req); + tevent_req_set_callback(subreq, sbus_method_in_s_out_u_done, req); ret = EAGAIN; @@ -690,15 +681,15 @@ sbus_method_in_s_out_s_send return req; } -static void sbus_method_in_s_out_s_done(struct tevent_req *subreq) +static void sbus_method_in_s_out_u_done(struct tevent_req *subreq) { - struct sbus_method_in_s_out_s_state *state; + struct sbus_method_in_s_out_u_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_s_out_s_state); + state = tevent_req_data(req, struct sbus_method_in_s_out_u_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -707,7 +698,7 @@ static void sbus_method_in_s_out_s_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_s, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -718,17 +709,16 @@ static void sbus_method_in_s_out_s_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_s_out_s_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - const char ** _arg0) +sbus_method_in_s_out_u_recv + (struct tevent_req *req, + uint32_t* _arg0) { - struct sbus_method_in_s_out_s_state *state; - state = tevent_req_data(req, struct sbus_method_in_s_out_s_state); + struct sbus_method_in_s_out_u_state *state; + state = tevent_req_data(req, struct sbus_method_in_s_out_u_state); TEVENT_REQ_RETURN_ON_ERROR(req); - *_arg0 = talloc_steal(mem_ctx, state->out->arg0); + *_arg0 = state->out->arg0; return EOK; } @@ -1182,15 +1172,15 @@ sbus_method_in_ussu_out__recv return EOK; } -struct sbus_method_in_ussu_out_qus_state { +struct sbus_method_in_ussu_out_u_state { struct _sbus_sss_invoker_args_ussu in; - struct _sbus_sss_invoker_args_qus *out; + struct _sbus_sss_invoker_args_u *out; }; -static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_ussu_out_u_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_ussu_out_qus_send +sbus_method_in_ussu_out_u_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -1203,18 +1193,18 @@ sbus_method_in_ussu_out_qus_send const char * arg2, uint32_t arg3) { - struct sbus_method_in_ussu_out_qus_state *state; + struct sbus_method_in_ussu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_ussu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_ussu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -1236,7 +1226,7 @@ sbus_method_in_ussu_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_ussu_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_ussu_out_u_done, req); ret = EAGAIN; @@ -1249,15 +1239,15 @@ sbus_method_in_ussu_out_qus_send return req; } -static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_ussu_out_u_done(struct tevent_req *subreq) { - struct sbus_method_in_ussu_out_qus_state *state; + struct sbus_method_in_ussu_out_u_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_ussu_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_ussu_out_u_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -1266,7 +1256,7 @@ static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1277,21 +1267,16 @@ static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_ussu_out_qus_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) +sbus_method_in_ussu_out_u_recv + (struct tevent_req *req, + uint32_t* _arg0) { - struct sbus_method_in_ussu_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_ussu_out_qus_state); + struct sbus_method_in_ussu_out_u_state *state; + state = tevent_req_data(req, struct sbus_method_in_ussu_out_u_state); TEVENT_REQ_RETURN_ON_ERROR(req); *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); return EOK; } @@ -1382,15 +1367,15 @@ sbus_method_in_usu_out__recv return EOK; } -struct sbus_method_in_uusssu_out_qus_state { +struct sbus_method_in_uusssu_out_u_state { struct _sbus_sss_invoker_args_uusssu in; - struct _sbus_sss_invoker_args_qus *out; + struct _sbus_sss_invoker_args_u *out; }; -static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_uusssu_out_u_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_uusssu_out_qus_send +sbus_method_in_uusssu_out_u_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -1405,18 +1390,18 @@ sbus_method_in_uusssu_out_qus_send const char * arg4, uint32_t arg5) { - struct sbus_method_in_uusssu_out_qus_state *state; + struct sbus_method_in_uusssu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusssu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusssu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -1440,7 +1425,7 @@ sbus_method_in_uusssu_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_uusssu_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_uusssu_out_u_done, req); ret = EAGAIN; @@ -1453,15 +1438,15 @@ sbus_method_in_uusssu_out_qus_send return req; } -static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_uusssu_out_u_done(struct tevent_req *subreq) { - struct sbus_method_in_uusssu_out_qus_state *state; + struct sbus_method_in_uusssu_out_u_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_uusssu_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_uusssu_out_u_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -1470,7 +1455,7 @@ static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1481,34 +1466,29 @@ static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_uusssu_out_qus_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) +sbus_method_in_uusssu_out_u_recv + (struct tevent_req *req, + uint32_t* _arg0) { - struct sbus_method_in_uusssu_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_uusssu_out_qus_state); + struct sbus_method_in_uusssu_out_u_state *state; + state = tevent_req_data(req, struct sbus_method_in_uusssu_out_u_state); TEVENT_REQ_RETURN_ON_ERROR(req); *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); return EOK; } -struct sbus_method_in_uusu_out_qus_state { +struct sbus_method_in_uusu_out_us_state { struct _sbus_sss_invoker_args_uusu in; - struct _sbus_sss_invoker_args_qus *out; + struct _sbus_sss_invoker_args_us *out; }; -static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_uusu_out_us_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_uusu_out_qus_send +sbus_method_in_uusu_out_us_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -1521,18 +1501,18 @@ sbus_method_in_uusu_out_qus_send const char * arg2, uint32_t arg3) { - struct sbus_method_in_uusu_out_qus_state *state; + struct sbus_method_in_uusu_out_us_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusu_out_us_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_us); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -1554,7 +1534,7 @@ sbus_method_in_uusu_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_uusu_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_uusu_out_us_done, req); ret = EAGAIN; @@ -1567,15 +1547,15 @@ sbus_method_in_uusu_out_qus_send return req; } -static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_uusu_out_us_done(struct tevent_req *subreq) { - struct sbus_method_in_uusu_out_qus_state *state; + struct sbus_method_in_uusu_out_us_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_uusu_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_uusu_out_us_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -1584,7 +1564,7 @@ static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_us, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1595,34 +1575,32 @@ static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_uusu_out_qus_recv +sbus_method_in_uusu_out_us_recv (TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) + uint32_t* _arg0, + const char ** _arg1) { - struct sbus_method_in_uusu_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_uusu_out_qus_state); + struct sbus_method_in_uusu_out_us_state *state; + state = tevent_req_data(req, struct sbus_method_in_uusu_out_us_state); TEVENT_REQ_RETURN_ON_ERROR(req); *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); + *_arg1 = talloc_steal(mem_ctx, state->out->arg1); return EOK; } -struct sbus_method_in_uuusu_out_qus_state { +struct sbus_method_in_uuusu_out_u_state { struct _sbus_sss_invoker_args_uuusu in; - struct _sbus_sss_invoker_args_qus *out; + struct _sbus_sss_invoker_args_u *out; }; -static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq); +static void sbus_method_in_uuusu_out_u_done(struct tevent_req *subreq); static struct tevent_req * -sbus_method_in_uuusu_out_qus_send +sbus_method_in_uuusu_out_u_send (TALLOC_CTX *mem_ctx, struct sbus_connection *conn, sbus_invoker_keygen keygen, @@ -1636,18 +1614,18 @@ sbus_method_in_uuusu_out_qus_send const char * arg3, uint32_t arg4) { - struct sbus_method_in_uuusu_out_qus_state *state; + struct sbus_method_in_uuusu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uuusu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uuusu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; } - state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus); + state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u); if (state->out == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate space for output parameters!\n"); @@ -1670,7 +1648,7 @@ sbus_method_in_uuusu_out_qus_send goto done; } - tevent_req_set_callback(subreq, sbus_method_in_uuusu_out_qus_done, req); + tevent_req_set_callback(subreq, sbus_method_in_uuusu_out_u_done, req); ret = EAGAIN; @@ -1683,15 +1661,15 @@ sbus_method_in_uuusu_out_qus_send return req; } -static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq) +static void sbus_method_in_uuusu_out_u_done(struct tevent_req *subreq) { - struct sbus_method_in_uuusu_out_qus_state *state; + struct sbus_method_in_uuusu_out_u_state *state; struct tevent_req *req; DBusMessage *reply; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sbus_method_in_uuusu_out_qus_state); + state = tevent_req_data(req, struct sbus_method_in_uuusu_out_u_state); ret = sbus_call_method_recv(state, subreq, &reply); talloc_zfree(subreq); @@ -1700,7 +1678,7 @@ static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq) return; } - ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out); + ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1711,21 +1689,16 @@ static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq) } static errno_t -sbus_method_in_uuusu_out_qus_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _arg0, - uint32_t* _arg1, - const char ** _arg2) +sbus_method_in_uuusu_out_u_recv + (struct tevent_req *req, + uint32_t* _arg0) { - struct sbus_method_in_uuusu_out_qus_state *state; - state = tevent_req_data(req, struct sbus_method_in_uuusu_out_qus_state); + struct sbus_method_in_uuusu_out_u_state *state; + state = tevent_req_data(req, struct sbus_method_in_uuusu_out_u_state); TEVENT_REQ_RETURN_ON_ERROR(req); *_arg0 = state->out->arg0; - *_arg1 = state->out->arg1; - *_arg2 = talloc_steal(mem_ctx, state->out->arg2); return EOK; } @@ -1967,7 +1940,7 @@ sbus_call_dp_dp_getAccountDomain_send const char * arg_filter, uint32_t arg_cli_id) { - return sbus_method_in_uusu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uusu_0_1_2, + return sbus_method_in_uusu_out_us_send(mem_ctx, conn, _sbus_sss_key_uusu_0_1_2, busname, object_path, "sssd.dataprovider", "getAccountDomain", arg_dp_flags, arg_entry_type, arg_filter, arg_cli_id); } @@ -1975,11 +1948,10 @@ errno_t sbus_call_dp_dp_getAccountDomain_recv (TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t* _dp_error, uint32_t* _error, const char ** _domain_name) { - return sbus_method_in_uusu_out_qus_recv(mem_ctx, req, _dp_error, _error, _domain_name); + return sbus_method_in_uusu_out_us_recv(mem_ctx, req, _error, _domain_name); } struct tevent_req * @@ -1995,19 +1967,16 @@ sbus_call_dp_dp_getAccountInfo_send const char * arg_extra, uint32_t arg_cli_id) { - return sbus_method_in_uusssu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uusssu_0_1_2_3_4, + return sbus_method_in_uusssu_out_u_send(mem_ctx, conn, _sbus_sss_key_uusssu_0_1_2_3_4, busname, object_path, "sssd.dataprovider", "getAccountInfo", arg_dp_flags, arg_entry_type, arg_filter, arg_domain, arg_extra, arg_cli_id); } errno_t sbus_call_dp_dp_getAccountInfo_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message) + (struct tevent_req *req, + uint32_t* _error) { - return sbus_method_in_uusssu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message); + return sbus_method_in_uusssu_out_u_recv(req, _error); } struct tevent_req * @@ -2018,19 +1987,16 @@ sbus_call_dp_dp_getDomains_send const char *object_path, const char * arg_domain_hint) { - return sbus_method_in_s_out_qus_send(mem_ctx, conn, _sbus_sss_key_s_0, + return sbus_method_in_s_out_u_send(mem_ctx, conn, _sbus_sss_key_s_0, busname, object_path, "sssd.dataprovider", "getDomains", arg_domain_hint); } errno_t sbus_call_dp_dp_getDomains_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message) + (struct tevent_req *req, + uint32_t* _error) { - return sbus_method_in_s_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message); + return sbus_method_in_s_out_u_recv(req, _error); } struct tevent_req * @@ -2044,19 +2010,16 @@ sbus_call_dp_dp_hostHandler_send const char * arg_alias, uint32_t arg_cli_id) { - return sbus_method_in_ussu_out_qus_send(mem_ctx, conn, _sbus_sss_key_ussu_0_1, + return sbus_method_in_ussu_out_u_send(mem_ctx, conn, _sbus_sss_key_ussu_0_1, busname, object_path, "sssd.dataprovider", "hostHandler", arg_dp_flags, arg_name, arg_alias, arg_cli_id); } errno_t sbus_call_dp_dp_hostHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message) + (struct tevent_req *req, + uint32_t* _error) { - return sbus_method_in_ussu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message); + return sbus_method_in_ussu_out_u_recv(req, _error); } struct tevent_req * @@ -2092,19 +2055,16 @@ sbus_call_dp_dp_resolverHandler_send const char * arg_filter_value, uint32_t arg_cli_id) { - return sbus_method_in_uuusu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uuusu_0_1_2_3, + return sbus_method_in_uuusu_out_u_send(mem_ctx, conn, _sbus_sss_key_uuusu_0_1_2_3, busname, object_path, "sssd.dataprovider", "resolverHandler", arg_dp_flags, arg_entry_type, arg_filter_type, arg_filter_value, arg_cli_id); } errno_t sbus_call_dp_dp_resolverHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message) + (struct tevent_req *req, + uint32_t* _error) { - return sbus_method_in_uuusu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message); + return sbus_method_in_uuusu_out_u_recv(req, _error); } struct tevent_req * @@ -2113,18 +2073,15 @@ sbus_call_dp_dp_sudoHandler_send struct sbus_connection *conn, DBusMessage *raw_message) { - return sbus_method_in_raw_out_qus_send(mem_ctx, conn, raw_message); + return sbus_method_in_raw_out_u_send(mem_ctx, conn, raw_message); } errno_t sbus_call_dp_dp_sudoHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message) + (struct tevent_req *req, + uint32_t* _error) { - return sbus_method_in_raw_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message); + return sbus_method_in_raw_out_u_recv(req, _error); } struct tevent_req * diff --git a/src/sss_iface/sbus_sss_client_async.h b/src/sss_iface/sbus_sss_client_async.h index d400cb4040f..3d4bf800d35 100644 --- a/src/sss_iface/sbus_sss_client_async.h +++ b/src/sss_iface/sbus_sss_client_async.h @@ -192,7 +192,6 @@ errno_t sbus_call_dp_dp_getAccountDomain_recv (TALLOC_CTX *mem_ctx, struct tevent_req *req, - uint16_t* _dp_error, uint32_t* _error, const char ** _domain_name); @@ -211,11 +210,8 @@ sbus_call_dp_dp_getAccountInfo_send errno_t sbus_call_dp_dp_getAccountInfo_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message); + (struct tevent_req *req, + uint32_t* _error); struct tevent_req * sbus_call_dp_dp_getDomains_send @@ -227,11 +223,8 @@ sbus_call_dp_dp_getDomains_send errno_t sbus_call_dp_dp_getDomains_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message); + (struct tevent_req *req, + uint32_t* _error); struct tevent_req * sbus_call_dp_dp_hostHandler_send @@ -246,11 +239,8 @@ sbus_call_dp_dp_hostHandler_send errno_t sbus_call_dp_dp_hostHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message); + (struct tevent_req *req, + uint32_t* _error); struct tevent_req * sbus_call_dp_dp_pamHandler_send @@ -280,11 +270,8 @@ sbus_call_dp_dp_resolverHandler_send errno_t sbus_call_dp_dp_resolverHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message); + (struct tevent_req *req, + uint32_t* _error); struct tevent_req * sbus_call_dp_dp_sudoHandler_send @@ -294,11 +281,8 @@ sbus_call_dp_dp_sudoHandler_send errno_t sbus_call_dp_dp_sudoHandler_recv - (TALLOC_CTX *mem_ctx, - struct tevent_req *req, - uint16_t* _dp_error, - uint32_t* _error, - const char ** _error_message); + (struct tevent_req *req, + uint32_t* _error); struct tevent_req * sbus_call_monitor_RegisterService_send diff --git a/src/sss_iface/sbus_sss_interface.h b/src/sss_iface/sbus_sss_interface.h index 138ced6276d..ea8587fc6ae 100644 --- a/src/sss_iface/sbus_sss_interface.h +++ b/src/sss_iface/sbus_sss_interface.h @@ -497,88 +497,88 @@ /* Method: sssd.dataprovider.getAccountDomain */ #define SBUS_METHOD_SYNC_sssd_dataprovider_getAccountDomain(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, uint32_t, uint32_t*, const char **); \ sbus_method_sync("getAccountDomain", \ &_sbus_sss_args_sssd_dataprovider_getAccountDomain, \ NULL, \ - _sbus_sss_invoke_in_uusu_out_qus_send, \ + _sbus_sss_invoke_in_uusu_out_us_send, \ _sbus_sss_key_uusu_0_1_2, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_getAccountDomain(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, const char *, uint32_t); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*, const char **); \ sbus_method_async("getAccountDomain", \ &_sbus_sss_args_sssd_dataprovider_getAccountDomain, \ NULL, \ - _sbus_sss_invoke_in_uusu_out_qus_send, \ + _sbus_sss_invoke_in_uusu_out_us_send, \ _sbus_sss_key_uusu_0_1_2, \ (handler_send), (handler_recv), (data)); \ }) /* Method: sssd.dataprovider.getAccountInfo */ #define SBUS_METHOD_SYNC_sssd_dataprovider_getAccountInfo(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint32_t*); \ sbus_method_sync("getAccountInfo", \ &_sbus_sss_args_sssd_dataprovider_getAccountInfo, \ NULL, \ - _sbus_sss_invoke_in_uusssu_out_qus_send, \ + _sbus_sss_invoke_in_uusssu_out_u_send, \ _sbus_sss_key_uusssu_0_1_2_3_4, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_getAccountInfo(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*); \ sbus_method_async("getAccountInfo", \ &_sbus_sss_args_sssd_dataprovider_getAccountInfo, \ NULL, \ - _sbus_sss_invoke_in_uusssu_out_qus_send, \ + _sbus_sss_invoke_in_uusssu_out_u_send, \ _sbus_sss_key_uusssu_0_1_2_3_4, \ (handler_send), (handler_recv), (data)); \ }) /* Method: sssd.dataprovider.getDomains */ #define SBUS_METHOD_SYNC_sssd_dataprovider_getDomains(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), const char *, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), const char *, uint32_t*); \ sbus_method_sync("getDomains", \ &_sbus_sss_args_sssd_dataprovider_getDomains, \ NULL, \ - _sbus_sss_invoke_in_s_out_qus_send, \ + _sbus_sss_invoke_in_s_out_u_send, \ _sbus_sss_key_s_0, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_getDomains(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), const char *); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*); \ sbus_method_async("getDomains", \ &_sbus_sss_args_sssd_dataprovider_getDomains, \ NULL, \ - _sbus_sss_invoke_in_s_out_qus_send, \ + _sbus_sss_invoke_in_s_out_u_send, \ _sbus_sss_key_s_0, \ (handler_send), (handler_recv), (data)); \ }) /* Method: sssd.dataprovider.hostHandler */ #define SBUS_METHOD_SYNC_sssd_dataprovider_hostHandler(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), uint32_t, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), uint32_t, const char *, const char *, uint32_t, uint32_t*); \ sbus_method_sync("hostHandler", \ &_sbus_sss_args_sssd_dataprovider_hostHandler, \ NULL, \ - _sbus_sss_invoke_in_ussu_out_qus_send, \ + _sbus_sss_invoke_in_ussu_out_u_send, \ _sbus_sss_key_ussu_0_1, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_hostHandler(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), uint32_t, const char *, const char *, uint32_t); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*); \ sbus_method_async("hostHandler", \ &_sbus_sss_args_sssd_dataprovider_hostHandler, \ NULL, \ - _sbus_sss_invoke_in_ussu_out_qus_send, \ + _sbus_sss_invoke_in_ussu_out_u_send, \ _sbus_sss_key_ussu_0_1, \ (handler_send), (handler_recv), (data)); \ }) @@ -607,44 +607,44 @@ /* Method: sssd.dataprovider.resolverHandler */ #define SBUS_METHOD_SYNC_sssd_dataprovider_resolverHandler(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint32_t*); \ sbus_method_sync("resolverHandler", \ &_sbus_sss_args_sssd_dataprovider_resolverHandler, \ NULL, \ - _sbus_sss_invoke_in_uuusu_out_qus_send, \ + _sbus_sss_invoke_in_uuusu_out_u_send, \ _sbus_sss_key_uuusu_0_1_2_3, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_resolverHandler(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*); \ sbus_method_async("resolverHandler", \ &_sbus_sss_args_sssd_dataprovider_resolverHandler, \ NULL, \ - _sbus_sss_invoke_in_uuusu_out_qus_send, \ + _sbus_sss_invoke_in_uuusu_out_u_send, \ _sbus_sss_key_uuusu_0_1_2_3, \ (handler_send), (handler_recv), (data)); \ }) /* Method: sssd.dataprovider.sudoHandler */ #define SBUS_METHOD_SYNC_sssd_dataprovider_sudoHandler(handler, data) ({ \ - SBUS_CHECK_SYNC((handler), (data), DBusMessageIter *, uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_SYNC((handler), (data), DBusMessageIter *, uint32_t*); \ sbus_method_sync("sudoHandler", \ &_sbus_sss_args_sssd_dataprovider_sudoHandler, \ NULL, \ - _sbus_sss_invoke_in_raw_out_qus_send, \ + _sbus_sss_invoke_in_raw_out_u_send, \ NULL, \ (handler), (data)); \ }) #define SBUS_METHOD_ASYNC_sssd_dataprovider_sudoHandler(handler_send, handler_recv, data) ({ \ SBUS_CHECK_SEND((handler_send), (data), DBusMessageIter *); \ - SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \ + SBUS_CHECK_RECV((handler_recv), uint32_t*); \ sbus_method_async("sudoHandler", \ &_sbus_sss_args_sssd_dataprovider_sudoHandler, \ NULL, \ - _sbus_sss_invoke_in_raw_out_qus_send, \ + _sbus_sss_invoke_in_raw_out_u_send, \ NULL, \ (handler_send), (handler_recv), (data)); \ }) diff --git a/src/sss_iface/sbus_sss_invokers.c b/src/sss_iface/sbus_sss_invokers.c index ef035241d14..c0a609636c1 100644 --- a/src/sss_iface/sbus_sss_invokers.c +++ b/src/sss_iface/sbus_sss_invokers.c @@ -561,14 +561,14 @@ static void _sbus_sss_invoke_in_pam_data_out_pam_response_done(struct tevent_req return; } -struct _sbus_sss_invoke_in_raw_out_qus_state { - struct _sbus_sss_invoker_args_qus out; +struct _sbus_sss_invoke_in_raw_out_u_state { + struct _sbus_sss_invoker_args_u out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, DBusMessageIter *, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, DBusMessageIter *, uint32_t*); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, DBusMessageIter *); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*); } handler; struct sbus_request *sbus_req; @@ -577,18 +577,18 @@ struct _sbus_sss_invoke_in_raw_out_qus_state { }; static void -_sbus_sss_invoke_in_raw_out_qus_step +_sbus_sss_invoke_in_raw_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_raw_out_qus_done +_sbus_sss_invoke_in_raw_out_u_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_raw_out_qus_send +_sbus_sss_invoke_in_raw_out_u_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -598,12 +598,12 @@ _sbus_sss_invoke_in_raw_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_raw_out_qus_state *state; + struct _sbus_sss_invoke_in_raw_out_u_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_raw_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_raw_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -619,7 +619,7 @@ _sbus_sss_invoke_in_raw_out_qus_send state->read_iterator = read_iterator; state->write_iterator = write_iterator; - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_raw_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_raw_out_u_step, req); if (ret != EOK) { goto done; } @@ -644,19 +644,19 @@ _sbus_sss_invoke_in_raw_out_qus_send return req; } -static void _sbus_sss_invoke_in_raw_out_qus_step +static void _sbus_sss_invoke_in_raw_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_raw_out_qus_state *state; + struct _sbus_sss_invoke_in_raw_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_u_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -666,12 +666,12 @@ static void _sbus_sss_invoke_in_raw_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->read_iterator, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->read_iterator, &state->out.arg0); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -687,7 +687,7 @@ static void _sbus_sss_invoke_in_raw_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_raw_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_raw_out_u_done, req); ret = EAGAIN; goto done; } @@ -702,23 +702,23 @@ static void _sbus_sss_invoke_in_raw_out_qus_step } } -static void _sbus_sss_invoke_in_raw_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_raw_out_u_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_raw_out_qus_state *state; + struct _sbus_sss_invoke_in_raw_out_u_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_u_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1263,15 +1263,15 @@ static void _sbus_sss_invoke_in_s_out_b_done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_s_out_qus_state { +struct _sbus_sss_invoke_in_s_out_s_state { struct _sbus_sss_invoker_args_s *in; - struct _sbus_sss_invoker_args_qus out; + struct _sbus_sss_invoker_args_s out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, const char **); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, const char *); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, const char **); } handler; struct sbus_request *sbus_req; @@ -1280,18 +1280,18 @@ struct _sbus_sss_invoke_in_s_out_qus_state { }; static void -_sbus_sss_invoke_in_s_out_qus_step +_sbus_sss_invoke_in_s_out_s_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_s_out_qus_done +_sbus_sss_invoke_in_s_out_s_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_s_out_qus_send +_sbus_sss_invoke_in_s_out_s_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -1301,12 +1301,12 @@ _sbus_sss_invoke_in_s_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_s_out_qus_state *state; + struct _sbus_sss_invoke_in_s_out_s_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_s_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -1335,7 +1335,7 @@ _sbus_sss_invoke_in_s_out_qus_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_s_step, req); if (ret != EOK) { goto done; } @@ -1360,19 +1360,19 @@ _sbus_sss_invoke_in_s_out_qus_send return req; } -static void _sbus_sss_invoke_in_s_out_qus_step +static void _sbus_sss_invoke_in_s_out_s_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_s_out_qus_state *state; + struct _sbus_sss_invoke_in_s_out_s_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -1382,12 +1382,12 @@ static void _sbus_sss_invoke_in_s_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, &state->out.arg0); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -1403,7 +1403,7 @@ static void _sbus_sss_invoke_in_s_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_s_done, req); ret = EAGAIN; goto done; } @@ -1418,23 +1418,23 @@ static void _sbus_sss_invoke_in_s_out_qus_step } } -static void _sbus_sss_invoke_in_s_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_s_out_qus_state *state; + struct _sbus_sss_invoke_in_s_out_s_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -1444,15 +1444,15 @@ static void _sbus_sss_invoke_in_s_out_qus_done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_s_out_s_state { +struct _sbus_sss_invoke_in_s_out_u_state { struct _sbus_sss_invoker_args_s *in; - struct _sbus_sss_invoker_args_s out; + struct _sbus_sss_invoker_args_u out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, uint32_t*); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, const char *); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*); } handler; struct sbus_request *sbus_req; @@ -1461,18 +1461,18 @@ struct _sbus_sss_invoke_in_s_out_s_state { }; static void -_sbus_sss_invoke_in_s_out_s_step +_sbus_sss_invoke_in_s_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_s_out_s_done +_sbus_sss_invoke_in_s_out_u_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_s_out_s_send +_sbus_sss_invoke_in_s_out_u_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -1482,12 +1482,12 @@ _sbus_sss_invoke_in_s_out_s_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_s_out_s_state *state; + struct _sbus_sss_invoke_in_s_out_u_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_s_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -1516,7 +1516,7 @@ _sbus_sss_invoke_in_s_out_s_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_s_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_u_step, req); if (ret != EOK) { goto done; } @@ -1541,19 +1541,19 @@ _sbus_sss_invoke_in_s_out_s_send return req; } -static void _sbus_sss_invoke_in_s_out_s_step +static void _sbus_sss_invoke_in_s_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_s_out_s_state *state; + struct _sbus_sss_invoke_in_s_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_u_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -1568,7 +1568,7 @@ static void _sbus_sss_invoke_in_s_out_s_step goto done; } - ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -1584,7 +1584,7 @@ static void _sbus_sss_invoke_in_s_out_s_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_s_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_u_done, req); ret = EAGAIN; goto done; } @@ -1599,14 +1599,14 @@ static void _sbus_sss_invoke_in_s_out_s_step } } -static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_s_out_u_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_s_out_s_state *state; + struct _sbus_sss_invoke_in_s_out_u_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_u_state); ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); @@ -1615,7 +1615,7 @@ static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq) return; } - ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -2679,15 +2679,15 @@ static void _sbus_sss_invoke_in_ussu_out__done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_ussu_out_qus_state { +struct _sbus_sss_invoke_in_ussu_out_u_state { struct _sbus_sss_invoker_args_ussu *in; - struct _sbus_sss_invoker_args_qus out; + struct _sbus_sss_invoker_args_u out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t, uint32_t*); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*); } handler; struct sbus_request *sbus_req; @@ -2696,18 +2696,18 @@ struct _sbus_sss_invoke_in_ussu_out_qus_state { }; static void -_sbus_sss_invoke_in_ussu_out_qus_step +_sbus_sss_invoke_in_ussu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_ussu_out_qus_done +_sbus_sss_invoke_in_ussu_out_u_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_ussu_out_qus_send +_sbus_sss_invoke_in_ussu_out_u_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -2717,12 +2717,12 @@ _sbus_sss_invoke_in_ussu_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_ussu_out_qus_state *state; + struct _sbus_sss_invoke_in_ussu_out_u_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_ussu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_ussu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -2751,7 +2751,7 @@ _sbus_sss_invoke_in_ussu_out_qus_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_ussu_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_ussu_out_u_step, req); if (ret != EOK) { goto done; } @@ -2776,19 +2776,19 @@ _sbus_sss_invoke_in_ussu_out_qus_send return req; } -static void _sbus_sss_invoke_in_ussu_out_qus_step +static void _sbus_sss_invoke_in_ussu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_ussu_out_qus_state *state; + struct _sbus_sss_invoke_in_ussu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_u_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -2798,12 +2798,12 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -2819,7 +2819,7 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_ussu_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_ussu_out_u_done, req); ret = EAGAIN; goto done; } @@ -2834,23 +2834,23 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step } } -static void _sbus_sss_invoke_in_ussu_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_ussu_out_u_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_ussu_out_qus_state *state; + struct _sbus_sss_invoke_in_ussu_out_u_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_u_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -3033,15 +3033,15 @@ static void _sbus_sss_invoke_in_usu_out__done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_uusssu_out_qus_state { +struct _sbus_sss_invoke_in_uusssu_out_u_state { struct _sbus_sss_invoker_args_uusssu *in; - struct _sbus_sss_invoker_args_qus out; + struct _sbus_sss_invoker_args_u out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint32_t*); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*); } handler; struct sbus_request *sbus_req; @@ -3050,18 +3050,18 @@ struct _sbus_sss_invoke_in_uusssu_out_qus_state { }; static void -_sbus_sss_invoke_in_uusssu_out_qus_step +_sbus_sss_invoke_in_uusssu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_uusssu_out_qus_done +_sbus_sss_invoke_in_uusssu_out_u_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_uusssu_out_qus_send +_sbus_sss_invoke_in_uusssu_out_u_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -3071,12 +3071,12 @@ _sbus_sss_invoke_in_uusssu_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_uusssu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusssu_out_u_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusssu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusssu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -3105,7 +3105,7 @@ _sbus_sss_invoke_in_uusssu_out_qus_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusssu_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusssu_out_u_step, req); if (ret != EOK) { goto done; } @@ -3130,19 +3130,19 @@ _sbus_sss_invoke_in_uusssu_out_qus_send return req; } -static void _sbus_sss_invoke_in_uusssu_out_qus_step +static void _sbus_sss_invoke_in_uusssu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_uusssu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusssu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_u_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -3152,12 +3152,12 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, state->in->arg5, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, state->in->arg5, &state->out.arg0); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -3173,7 +3173,7 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusssu_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusssu_out_u_done, req); ret = EAGAIN; goto done; } @@ -3188,23 +3188,23 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step } } -static void _sbus_sss_invoke_in_uusssu_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_uusssu_out_u_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_uusssu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusssu_out_u_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_u_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -3214,15 +3214,15 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_uusu_out_qus_state { +struct _sbus_sss_invoke_in_uusu_out_us_state { struct _sbus_sss_invoker_args_uusu *in; - struct _sbus_sss_invoker_args_qus out; + struct _sbus_sss_invoker_args_us out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t, uint32_t*, const char **); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*, const char **); } handler; struct sbus_request *sbus_req; @@ -3231,18 +3231,18 @@ struct _sbus_sss_invoke_in_uusu_out_qus_state { }; static void -_sbus_sss_invoke_in_uusu_out_qus_step +_sbus_sss_invoke_in_uusu_out_us_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_uusu_out_qus_done +_sbus_sss_invoke_in_uusu_out_us_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_uusu_out_qus_send +_sbus_sss_invoke_in_uusu_out_us_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -3252,12 +3252,12 @@ _sbus_sss_invoke_in_uusu_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_uusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusu_out_us_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusu_out_us_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -3286,7 +3286,7 @@ _sbus_sss_invoke_in_uusu_out_qus_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusu_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusu_out_us_step, req); if (ret != EOK) { goto done; } @@ -3311,19 +3311,19 @@ _sbus_sss_invoke_in_uusu_out_qus_send return req; } -static void _sbus_sss_invoke_in_uusu_out_qus_step +static void _sbus_sss_invoke_in_uusu_out_us_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_uusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusu_out_us_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_us_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -3333,12 +3333,12 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_us(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -3354,7 +3354,7 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusu_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusu_out_us_done, req); ret = EAGAIN; goto done; } @@ -3369,23 +3369,23 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step } } -static void _sbus_sss_invoke_in_uusu_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_uusu_out_us_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_uusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uusu_out_us_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_us_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_us(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -3395,15 +3395,15 @@ static void _sbus_sss_invoke_in_uusu_out_qus_done(struct tevent_req *subreq) return; } -struct _sbus_sss_invoke_in_uuusu_out_qus_state { +struct _sbus_sss_invoke_in_uuusu_out_u_state { struct _sbus_sss_invoker_args_uuusu *in; - struct _sbus_sss_invoker_args_qus out; + struct _sbus_sss_invoker_args_u out; struct { enum sbus_handler_type type; void *data; - errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); + errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint32_t*); struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t); - errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **); + errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*); } handler; struct sbus_request *sbus_req; @@ -3412,18 +3412,18 @@ struct _sbus_sss_invoke_in_uuusu_out_qus_state { }; static void -_sbus_sss_invoke_in_uuusu_out_qus_step +_sbus_sss_invoke_in_uuusu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data); static void -_sbus_sss_invoke_in_uuusu_out_qus_done +_sbus_sss_invoke_in_uuusu_out_u_done (struct tevent_req *subreq); struct tevent_req * -_sbus_sss_invoke_in_uuusu_out_qus_send +_sbus_sss_invoke_in_uuusu_out_u_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sbus_request *sbus_req, @@ -3433,12 +3433,12 @@ _sbus_sss_invoke_in_uuusu_out_qus_send DBusMessageIter *write_iterator, const char **_key) { - struct _sbus_sss_invoke_in_uuusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uuusu_out_u_state *state; struct tevent_req *req; const char *key; errno_t ret; - req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uuusu_out_qus_state); + req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uuusu_out_u_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); return NULL; @@ -3467,7 +3467,7 @@ _sbus_sss_invoke_in_uuusu_out_qus_send goto done; } - ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uuusu_out_qus_step, req); + ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uuusu_out_u_step, req); if (ret != EOK) { goto done; } @@ -3492,19 +3492,19 @@ _sbus_sss_invoke_in_uuusu_out_qus_send return req; } -static void _sbus_sss_invoke_in_uuusu_out_qus_step +static void _sbus_sss_invoke_in_uuusu_out_u_step (struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *private_data) { - struct _sbus_sss_invoke_in_uuusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uuusu_out_u_state *state; struct tevent_req *subreq; struct tevent_req *req; errno_t ret; req = talloc_get_type(private_data, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_u_state); switch (state->handler.type) { case SBUS_HANDLER_SYNC: @@ -3514,12 +3514,12 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step goto done; } - ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, &state->out.arg0); if (ret != EOK) { goto done; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); goto done; case SBUS_HANDLER_ASYNC: if (state->handler.send == NULL || state->handler.recv == NULL) { @@ -3535,7 +3535,7 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step goto done; } - tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uuusu_out_qus_done, req); + tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uuusu_out_u_done, req); ret = EAGAIN; goto done; } @@ -3550,23 +3550,23 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step } } -static void _sbus_sss_invoke_in_uuusu_out_qus_done(struct tevent_req *subreq) +static void _sbus_sss_invoke_in_uuusu_out_u_done(struct tevent_req *subreq) { - struct _sbus_sss_invoke_in_uuusu_out_qus_state *state; + struct _sbus_sss_invoke_in_uuusu_out_u_state *state; struct tevent_req *req; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_qus_state); + state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_u_state); - ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2); + ret = state->handler.recv(state, subreq, &state->out.arg0); talloc_zfree(subreq); if (ret != EOK) { tevent_req_error(req, ret); return; } - ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out); + ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out); if (ret != EOK) { tevent_req_error(req, ret); return; diff --git a/src/sss_iface/sbus_sss_invokers.h b/src/sss_iface/sbus_sss_invokers.h index 823ee995556..6737c522626 100644 --- a/src/sss_iface/sbus_sss_invokers.h +++ b/src/sss_iface/sbus_sss_invokers.h @@ -42,22 +42,22 @@ _sbus_sss_declare_invoker(, ); _sbus_sss_declare_invoker(, u); _sbus_sss_declare_invoker(pam_data, pam_response); -_sbus_sss_declare_invoker(raw, qus); +_sbus_sss_declare_invoker(raw, u); _sbus_sss_declare_invoker(s, ); _sbus_sss_declare_invoker(s, as); _sbus_sss_declare_invoker(s, b); -_sbus_sss_declare_invoker(s, qus); _sbus_sss_declare_invoker(s, s); +_sbus_sss_declare_invoker(s, u); _sbus_sss_declare_invoker(sqq, q); _sbus_sss_declare_invoker(ss, o); _sbus_sss_declare_invoker(ssau, ); _sbus_sss_declare_invoker(u, ); _sbus_sss_declare_invoker(usq, ); _sbus_sss_declare_invoker(ussu, ); -_sbus_sss_declare_invoker(ussu, qus); +_sbus_sss_declare_invoker(ussu, u); _sbus_sss_declare_invoker(usu, ); -_sbus_sss_declare_invoker(uusssu, qus); -_sbus_sss_declare_invoker(uusu, qus); -_sbus_sss_declare_invoker(uuusu, qus); +_sbus_sss_declare_invoker(uusssu, u); +_sbus_sss_declare_invoker(uusu, us); +_sbus_sss_declare_invoker(uuusu, u); #endif /* _SBUS_SSS_INVOKERS_H_ */ diff --git a/src/sss_iface/sbus_sss_symbols.c b/src/sss_iface/sbus_sss_symbols.c index 0219f370d34..606acdfe5b2 100644 --- a/src/sss_iface/sbus_sss_symbols.c +++ b/src/sss_iface/sbus_sss_symbols.c @@ -225,7 +225,6 @@ _sbus_sss_args_sssd_dataprovider_getAccountDomain = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, {.type = "s", .name = "domain_name"}, {NULL} @@ -244,9 +243,7 @@ _sbus_sss_args_sssd_dataprovider_getAccountInfo = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, - {.type = "s", .name = "error_message"}, {NULL} } }; @@ -258,9 +255,7 @@ _sbus_sss_args_sssd_dataprovider_getDomains = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, - {.type = "s", .name = "error_message"}, {NULL} } }; @@ -275,9 +270,7 @@ _sbus_sss_args_sssd_dataprovider_hostHandler = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, - {.type = "s", .name = "error_message"}, {NULL} } }; @@ -305,9 +298,7 @@ _sbus_sss_args_sssd_dataprovider_resolverHandler = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, - {.type = "s", .name = "error_message"}, {NULL} } }; @@ -318,9 +309,7 @@ _sbus_sss_args_sssd_dataprovider_sudoHandler = { {NULL} }, .output = (const struct sbus_argument[]){ - {.type = "q", .name = "dp_error"}, {.type = "u", .name = "error"}, - {.type = "s", .name = "error_message"}, {NULL} } }; diff --git a/src/sss_iface/sss_iface.xml b/src/sss_iface/sss_iface.xml index 02b98789de4..2e7c809a113 100644 --- a/src/sss_iface/sss_iface.xml +++ b/src/sss_iface/sss_iface.xml @@ -107,18 +107,14 @@ - - - - @@ -126,15 +122,11 @@ - - - - @@ -143,16 +135,13 @@ - - - diff --git a/src/tests/cmocka/common_mock_resp.h b/src/tests/cmocka/common_mock_resp.h index c277682fd89..6565da74d56 100644 --- a/src/tests/cmocka/common_mock_resp.h +++ b/src/tests/cmocka/common_mock_resp.h @@ -47,7 +47,7 @@ mock_prctx(TALLOC_CTX *mem_ctx); * sss_dp_get_account_recv call by calling mock_account_recv. * * The mocked sss_sp_get_account_recv shall return the return values - * given with parameters dp_err, dp_ret and msg and optionally also call + * given with parameters dp_ret and optionally also call * the acct_cb_t callback, if given with the pvt pointer as user data. * The callback can for instance populate the cache, thus simulating * Data Provider lookup. @@ -58,8 +58,7 @@ mock_prctx(TALLOC_CTX *mem_ctx); typedef int (*acct_cb_t)(void *); typedef int (*resolver_cb_t)(void *); -void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg, - acct_cb_t acct_cb, void *pvt); +void mock_account_recv(uint32_t dp_ret, acct_cb_t acct_cb, void *pvt); void mock_account_recv_simple(void); diff --git a/src/tests/cmocka/common_mock_resp_dp.c b/src/tests/cmocka/common_mock_resp_dp.c index 493231d0da0..f61c14b047b 100644 --- a/src/tests/cmocka/common_mock_resp_dp.c +++ b/src/tests/cmocka/common_mock_resp_dp.c @@ -43,15 +43,11 @@ sss_dp_get_account_send(TALLOC_CTX *mem_ctx, errno_t sss_dp_get_account_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - dbus_uint16_t *dp_err, - dbus_uint32_t *dp_ret, - const char **err_msg) + dbus_uint32_t *err) { acct_cb_t cb; - *dp_err = sss_mock_type(dbus_uint16_t); - *dp_ret = sss_mock_type(dbus_uint32_t); - *err_msg = sss_mock_ptr_type(char *); + *err = sss_mock_type(dbus_uint32_t); cb = sss_mock_ptr_type(acct_cb_t); if (cb) { @@ -76,15 +72,11 @@ sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx, errno_t sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - dbus_uint16_t *dp_err, - dbus_uint32_t *dp_ret, - const char **err_msg) + dbus_uint32_t *err) { resolver_cb_t cb; - *dp_err = sss_mock_type(dbus_uint16_t); - *dp_ret = sss_mock_type(dbus_uint32_t); - *err_msg = sss_mock_ptr_type(char *); + *err = sss_mock_type(dbus_uint32_t); cb = sss_mock_ptr_type(resolver_cb_t); if (cb) { @@ -97,9 +89,7 @@ sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx, void mock_resolver_recv(uint16_t dp_err, uint32_t dp_ret, char *msg, resolver_cb_t cb, void *pvt) { - will_return(sss_dp_resolver_get_recv, dp_err); will_return(sss_dp_resolver_get_recv, dp_ret); - will_return(sss_dp_resolver_get_recv, msg); will_return(sss_dp_resolver_get_recv, cb); if (cb) { @@ -148,15 +138,11 @@ sss_dp_get_ssh_host_recv(TALLOC_CTX *mem_ctx, errno_t sss_dp_req_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, - dbus_uint16_t *dp_err, - dbus_uint32_t *dp_ret, - char **err_msg) + dbus_uint32_t *err) { acct_cb_t cb; - *dp_err = sss_mock_type(dbus_uint16_t); - *dp_ret = sss_mock_type(dbus_uint32_t); - *err_msg = sss_mock_ptr_type(char *); + *err = sss_mock_type(dbus_uint32_t); cb = sss_mock_ptr_type(acct_cb_t); if (cb) { @@ -166,12 +152,10 @@ sss_dp_req_recv(TALLOC_CTX *mem_ctx, return test_request_recv(req); } -void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg, - acct_cb_t acct_cb, void *pvt) +void mock_account_recv(uint32_t dp_ret, acct_cb_t acct_cb, + void *pvt) { - will_return(sss_dp_get_account_recv, dp_err); will_return(sss_dp_get_account_recv, dp_ret); - will_return(sss_dp_get_account_recv, msg); will_return(sss_dp_get_account_recv, acct_cb); if (acct_cb) { @@ -181,7 +165,7 @@ void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg, void mock_account_recv_simple(void) { - return mock_account_recv(0, 0, NULL, NULL, NULL); + return mock_account_recv(0, NULL, NULL); } struct tevent_req * diff --git a/src/tests/cmocka/test_krb5_wait_queue.c b/src/tests/cmocka/test_krb5_wait_queue.c index 9f8473b0612..63f3b9fbb3f 100644 --- a/src/tests/cmocka/test_krb5_wait_queue.c +++ b/src/tests/cmocka/test_krb5_wait_queue.c @@ -35,7 +35,6 @@ struct krb5_mocked_auth_state { time_t us_delay; int ret; int pam_status; - int dp_err; }; static void krb5_mocked_auth_done(struct tevent_context *ev, @@ -64,7 +63,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, state->us_delay = sss_mock_type(time_t); state->ret = sss_mock_type(int); state->pam_status = sss_mock_type(int); - state->dp_err = sss_mock_type(int); tv = tevent_timeval_current_ofs(0, state->us_delay); @@ -97,8 +95,7 @@ static void krb5_mocked_auth_done(struct tevent_context *ev, } int krb5_auth_recv(struct tevent_req *req, - int *_pam_status, - int *_dp_err) + int *_pam_status) { struct krb5_mocked_auth_state *state; @@ -108,10 +105,6 @@ int krb5_auth_recv(struct tevent_req *req, *_pam_status = state->pam_status; } - if (_dp_err != NULL) { - *_dp_err = state->dp_err; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -163,8 +156,7 @@ static void test_krb5_wait_mock(struct test_krb5_wait_queue *test_ctx, const char *username, time_t us_delay, int ret, - int pam_status, - int dp_err) + int pam_status) { test_ctx->pd->user = discard_const(username); @@ -172,13 +164,12 @@ static void test_krb5_wait_mock(struct test_krb5_wait_queue *test_ctx, will_return(krb5_auth_send, us_delay); will_return(krb5_auth_send, ret); will_return(krb5_auth_send, pam_status); - will_return(krb5_auth_send, dp_err); } static void test_krb5_wait_mock_success(struct test_krb5_wait_queue *test_ctx, const char *username) { - return test_krb5_wait_mock(test_ctx, username, 200, 0, 0, 0); + return test_krb5_wait_mock(test_ctx, username, 200, 0, 0); } static void test_krb5_wait_queue_single_done(struct tevent_req *req); @@ -210,9 +201,8 @@ static void test_krb5_wait_queue_single_done(struct tevent_req *req) tevent_req_callback_data(req, struct test_krb5_wait_queue); errno_t ret; int pam_status; - int dp_err; - ret = krb5_auth_queue_recv(req, &pam_status, &dp_err); + ret = krb5_auth_queue_recv(req, &pam_status); talloc_free(req); assert_int_equal(ret, EOK); @@ -253,9 +243,8 @@ static void test_krb5_wait_queue_multi_done(struct tevent_req *req) tevent_req_callback_data(req, struct test_krb5_wait_queue); errno_t ret; int pam_status; - int dp_err; - ret = krb5_auth_queue_recv(req, &pam_status, &dp_err); + ret = krb5_auth_queue_recv(req, &pam_status); talloc_free(req); assert_int_equal(ret, EOK); @@ -279,7 +268,7 @@ static void test_krb5_wait_queue_fail_odd(void **state) test_ctx->num_auths = 10; for (i=0; i < test_ctx->num_auths; i++) { - test_krb5_wait_mock(test_ctx, "krb5_user", 0, i+1 % 2, PAM_SUCCESS, 0); + test_krb5_wait_mock(test_ctx, "krb5_user", 0, i+1 % 2, PAM_SUCCESS); req = krb5_auth_queue_send(test_ctx, test_ctx->tctx->ev, @@ -300,9 +289,8 @@ static void test_krb5_wait_queue_fail_odd_done(struct tevent_req *req) tevent_req_callback_data(req, struct test_krb5_wait_queue); errno_t ret; int pam_status; - int dp_err; - ret = krb5_auth_queue_recv(req, &pam_status, &dp_err); + ret = krb5_auth_queue_recv(req, &pam_status); talloc_free(req); assert_int_equal(ret, test_ctx->num_finished_auths+1 % 2); diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index b5a6162166e..c947cf9a2fe 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -857,7 +857,7 @@ void test_sss_nss_getpwnam_search(void **state) struct ldb_result *res; mock_input_user_or_group("testuser_search"); - mock_account_recv(0, 0, NULL, test_sss_nss_getpwnam_search_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_getpwnam_search_acct_cb, sss_nss_test_ctx); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM); mock_fill_user(); set_cmd_cb(test_sss_nss_getpwnam_search_check); @@ -936,7 +936,7 @@ void test_sss_nss_getpwnam_update(void **state) /* Mock client command */ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM); /* Call this function when user is updated by the mock DP request */ - mock_account_recv(0, 0, NULL, test_sss_nss_getpwnam_update_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_getpwnam_update_acct_cb, sss_nss_test_ctx); /* Call this function to check what the responder returned to the client */ set_cmd_cb(test_sss_nss_getpwnam_update_check); /* Mock output buffer */ @@ -1327,7 +1327,7 @@ void test_sss_nss_getpwuid_search(void **state) struct ldb_result *res; mock_input_id(sss_nss_test_ctx, getpwuid_srch.pw_uid); - mock_account_recv(0, 0, NULL, test_sss_nss_getpwuid_search_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_getpwuid_search_acct_cb, sss_nss_test_ctx); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID); mock_fill_user(); set_cmd_cb(test_sss_nss_getpwuid_search_check); @@ -1406,7 +1406,7 @@ void test_sss_nss_getpwuid_update(void **state) /* Mock client command */ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID); /* Call this function when id is updated by the mock DP request */ - mock_account_recv(0, 0, NULL, test_sss_nss_getpwuid_update_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_getpwuid_update_acct_cb, sss_nss_test_ctx); /* Call this function to check what the responder returned to the client */ set_cmd_cb(test_sss_nss_getpwuid_update_check); /* Mock output buffer */ @@ -3354,7 +3354,7 @@ void test_sss_nss_initgr_search(void **state) struct ldb_result *res; mock_input_user_or_group("testinitgr_srch"); - mock_account_recv(0, 0, NULL, test_sss_nss_initgr_search_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_initgr_search_acct_cb, sss_nss_test_ctx); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR); will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); set_cmd_cb(test_sss_nss_initgr_search_check); @@ -3474,7 +3474,7 @@ void test_sss_nss_initgr_update(void **state) assert_int_equal(ret, EOK); mock_input_user_or_group("testinitgr_update"); - mock_account_recv(0, 0, NULL, test_sss_nss_initgr_update_acct_cb, sss_nss_test_ctx); + mock_account_recv(0, test_sss_nss_initgr_update_acct_cb, sss_nss_test_ctx); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR); will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); set_cmd_cb(test_sss_nss_initgr_update_check); @@ -3594,7 +3594,7 @@ void test_sss_nss_initgr_update_two_expire_attributes(void **state) assert_int_equal(ret, EOK); mock_input_user_or_group("testinitgr_2attr"); - mock_account_recv(0, 0, NULL, + mock_account_recv(0, test_sss_nss_initgr_update_acct_2expire_attributes_cb, sss_nss_test_ctx); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR); @@ -3991,7 +3991,7 @@ void test_sss_nss_getnamebysid_update(void **state) /* Mock client command */ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETNAMEBYSID); /* Call this function when user is updated by the mock DP request */ - mock_account_recv(0, 0, NULL, test_sss_nss_getnamebysid_update_acct_cb, + mock_account_recv(0L, test_sss_nss_getnamebysid_update_acct_cb, sss_nss_test_ctx); /* Call this function to check what the responder returned to the client */ set_cmd_cb(test_sss_nss_getnamebysid_update_check); diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c index 715ac04a9e9..6d97c0aa547 100644 --- a/src/tests/cmocka/test_pam_srv.c +++ b/src/tests/cmocka/test_pam_srv.c @@ -669,7 +669,7 @@ static void mock_input_pam_passkey(TALLOC_CTX *mem_ctx, } if (acct_cb != NULL) { - mock_account_recv(0, 0, NULL, acct_cb, discard_const(passkey)); + mock_account_recv(0, acct_cb, discard_const(passkey)); } } @@ -843,7 +843,7 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, will_return(__wrap_sss_packet_get_body, buf_size); if (acct_cb != NULL) { - mock_account_recv(0, 0, NULL, acct_cb, discard_const(cert)); + mock_account_recv(0, acct_cb, discard_const(cert)); } if (name != NULL) { From 23894fc5766cdf34b0967fb77da0155bc0ca9148 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 11 Mar 2026 09:08:04 -0400 Subject: [PATCH 19/39] Update LDAP provider initialization for new failover - Servers are hardcoded --- Makefile.am | 3 +- src/providers/ldap/ldap_common.h | 12 ++++ src/providers/ldap/ldap_init.c | 105 ++++++++++++++++++++++++++++--- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8b29d6c5cc2..372c047b944 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4508,7 +4508,8 @@ libsss_krb5_common_la_LDFLAGS = \ libsss_ldap_la_SOURCES = \ src/providers/ldap/ldap_init.c \ - src/providers/ldap/ldap_access.c + src/providers/ldap/ldap_access.c \ + $(SSSD_NEW_FAILOVER_OBJ) libsss_ldap_la_CFLAGS = \ $(AM_CFLAGS) \ $(OPENLDAP_CFLAGS) diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index bc44ceb0e81..f887aad84b4 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -30,6 +30,7 @@ #include "providers/fail_over.h" #include "providers/krb5/krb5_common.h" #include "lib/idmap/sss_idmap.h" +#include "providers/failover/failover.h" #define PWD_POL_OPT_NONE "none" #define PWD_POL_OPT_SHADOW "shadow" @@ -78,6 +79,9 @@ struct sdap_id_ctx { struct sdap_server_opts *srv_opts; + /* New failover context */ + struct sss_failover_ctx *fctx; + /* Enumeration/cleanup periodic task. Only the enumeration or the cleanup * task is started depending on the value of the domain's enumeration * setting, this is why there is only one task pointer for both tasks. */ @@ -108,6 +112,14 @@ struct sdap_resolver_ctx { struct timeval last_purge; }; +struct ldap_init_ctx { + struct sdap_options *options; + struct sdap_id_ctx *id_ctx; + struct sdap_auth_ctx *auth_ctx; + struct sdap_resolver_ctx *resolver_ctx; + struct sss_failover_ctx *fctx; +}; + struct tevent_req * sdap_online_check_handler_send(TALLOC_CTX *mem_ctx, struct sdap_id_ctx *id_ctx, diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index a22654da409..039fdf0d9fc 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -33,17 +33,14 @@ #include "providers/ldap/ldap_resolver_enum.h" #include "providers/fail_over_srv.h" #include "providers/be_refresh.h" - -struct ldap_init_ctx { - struct sdap_options *options; - struct sdap_id_ctx *id_ctx; - struct sdap_auth_ctx *auth_ctx; - struct sdap_resolver_ctx *resolver_ctx; -}; +#include "providers/failover/failover.h" +#include "providers/failover/failover_vtable.h" +#include "providers/failover/ldap/failover_ldap.h" static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sdap_id_ctx *id_ctx, + struct sss_failover_ctx *fctx, struct sdap_options *options, struct sdap_auth_ctx **_auth_ctx) { @@ -55,6 +52,7 @@ static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx, } auth_ctx->be = be_ctx; + auth_ctx->fctx = fctx; auth_ctx->opts = options; auth_ctx->service = id_ctx->conn->service; auth_ctx->chpass_service = NULL; @@ -238,6 +236,88 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, return EOK; } +static struct sss_failover_ctx * +sssm_ldap_init_failover(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts) +{ + struct sss_failover_ctx *fctx; + struct sss_failover_group *group; + struct sss_failover_server *server; + errno_t ret; + + /* Setup new failover. */ + fctx = sss_failover_init(mem_ctx, be_ctx->ev, "LDAP", + be_ctx->be_res->resolv, + be_ctx->be_res->family_order); + if (fctx == NULL) { + return NULL; + } + + /* Add primary servers */ + group = sss_failover_group_new(fctx, "primary"); + if (group == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_setup_dns_discovery(group); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_1.ldap.test", + "ldap://fake_1.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_2.ldap.test", + "ldap://fake_2.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "master.ldap.test", + "ldap://master.ldap.test", 389, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + sss_failover_vtable_set_connect(fctx, + sss_failover_ldap_connect_send, + sss_failover_ldap_connect_recv, + opts); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(fctx); + return NULL; + } + + return fctx; +} + errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, @@ -288,9 +368,20 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx, goto done; } + /* Setup new failover. */ + init_ctx->fctx = sssm_ldap_init_failover(init_ctx, be_ctx, init_ctx->id_ctx->opts); + if (init_ctx->fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + ret = ENOMEM; + goto done; + } + + init_ctx->id_ctx->fctx = init_ctx->fctx; + /* Initialize auth_ctx only if one of the target is enabled. */ if (dp_target_enabled(provider, module_name, DPT_AUTH, DPT_CHPASS)) { ret = ldap_init_auth_ctx(init_ctx, be_ctx, init_ctx->id_ctx, + init_ctx->fctx, init_ctx->options, &init_ctx->auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create auth context " From 22973b18b18598e562619b3ff62d505069254265 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Thu, 12 Mar 2026 09:10:51 -0400 Subject: [PATCH 20/39] Port LDAP provider code to new failover --- Makefile.am | 1 + src/providers/ad/ad_gpo.c | 4 +- src/providers/ad/ad_resolver.c | 3 +- src/providers/failover/ldap/failover_ldap.h | 1 + src/providers/ipa/ipa_subdomains_ext_groups.c | 2 +- src/providers/ldap/ldap_access.c | 3 +- src/providers/ldap/ldap_auth.c | 78 ++---- src/providers/ldap/ldap_common.c | 33 +-- src/providers/ldap/ldap_common.h | 20 +- src/providers/ldap/ldap_id.c | 246 ++++++------------ src/providers/ldap/ldap_id_enum.c | 3 +- src/providers/ldap/ldap_id_netgroup.c | 62 +---- src/providers/ldap/ldap_id_services.c | 75 ++---- src/providers/ldap/ldap_id_subid.c | 76 ++---- src/providers/ldap/ldap_init.c | 15 +- src/providers/ldap/ldap_resolver_enum.c | 3 +- src/providers/ldap/sdap_access.c | 129 ++------- src/providers/ldap/sdap_access.h | 2 - src/providers/ldap/sdap_async.h | 15 +- src/providers/ldap/sdap_async_ad.h | 2 +- src/providers/ldap/sdap_async_autofs.c | 135 ++-------- src/providers/ldap/sdap_async_enum.c | 226 ++++++---------- src/providers/ldap/sdap_async_enum.h | 8 +- src/providers/ldap/sdap_async_initgroups.c | 62 ++--- src/providers/ldap/sdap_async_initgroups_ad.c | 13 +- src/providers/ldap/sdap_async_iphost.c | 24 +- src/providers/ldap/sdap_async_ipnetwork.c | 23 +- src/providers/ldap/sdap_async_resolver_enum.c | 140 +++------- src/providers/ldap/sdap_async_resolver_enum.h | 3 +- src/providers/ldap/sdap_async_services.c | 24 +- src/providers/ldap/sdap_async_sudo.c | 67 ++--- src/providers/ldap/sdap_async_sudo_hostinfo.c | 1 - src/providers/ldap/sdap_autofs.c | 59 +---- src/providers/ldap/sdap_autofs.h | 1 - src/providers/ldap/sdap_dyndns.c | 33 +-- src/providers/ldap/sdap_hostid.c | 54 +--- src/providers/ldap/sdap_iphost.c | 73 +----- src/providers/ldap/sdap_ipnetwork.c | 74 +----- src/providers/ldap/sdap_refresh.c | 3 +- src/providers/ldap/sdap_reinit.c | 2 +- 40 files changed, 476 insertions(+), 1322 deletions(-) diff --git a/Makefile.am b/Makefile.am index 372c047b944..48e5f89b55d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4429,6 +4429,7 @@ libsss_ldap_common_la_SOURCES = \ src/util/sss_sockets.c \ src/util/sss_ldap.c \ src/util/cert_derb64_to_ldap_filter.c \ + $(SSSD_NEW_FAILOVER_OBJ) \ $(NULL) libsss_ldap_common_la_CFLAGS = \ $(AM_CFLAGS) \ diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index 1aa6568c4ac..20052c2f356 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -2255,7 +2255,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) subreq = groups_by_user_send(state, state->ev, state->access_ctx->ad_id_ctx->sdap_id_ctx, - sdom, state->conn, + sdom, search_bases, state->host_fqdn, BE_FILTER_NAME, @@ -2293,7 +2293,7 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) ret = groups_by_user_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (ret == EAGAIN) { + if (ret == ERR_NO_MORE_SERVERS) { DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); ret = process_offline_gpos(state, state->user, diff --git a/src/providers/ad/ad_resolver.c b/src/providers/ad/ad_resolver.c index 5b7a53e99be..342837a3b7f 100644 --- a/src/providers/ad/ad_resolver.c +++ b/src/providers/ad/ad_resolver.c @@ -413,8 +413,7 @@ ad_resolver_enum_sdom(struct tevent_req *req, subreq = sdap_dom_resolver_enum_send(state, state->ev, sdap_resolver_ctx, id_ctx->sdap_id_ctx, - sd, - id_ctx->ldap_ctx); + sd); if (subreq == NULL) { /* The ptask API will reschedule the enumeration on its own on * failure */ diff --git a/src/providers/failover/ldap/failover_ldap.h b/src/providers/failover/ldap/failover_ldap.h index ba90f6eeac8..3978adcf260 100644 --- a/src/providers/failover/ldap/failover_ldap.h +++ b/src/providers/failover/ldap/failover_ldap.h @@ -30,6 +30,7 @@ struct sss_failover_ldap_connection { struct sdap_server_opts *srv_opts; struct sdap_handle *sh; char *uri; + bool no_mpg_user_fallback; }; struct tevent_req * diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c index 7eaa060d5dc..56298eb59be 100644 --- a/src/providers/ipa/ipa_subdomains_ext_groups.c +++ b/src/providers/ipa/ipa_subdomains_ext_groups.c @@ -1053,7 +1053,7 @@ static void ipa_add_trusted_memberships_get_next(struct tevent_req *req) * directly fetch the group with the corresponding DN. */ subreq = groups_get_send(state, state->ev, state->sdap_id_ctx, state->group_sdom, - state->sdap_id_ctx->conn, + NULL, fq_name, BE_FILTER_NAME, false, false, false); diff --git a/src/providers/ldap/ldap_access.c b/src/providers/ldap/ldap_access.c index 4ec4702f907..b25d27a52c7 100644 --- a/src/providers/ldap/ldap_access.c +++ b/src/providers/ldap/ldap_access.c @@ -55,8 +55,7 @@ sdap_pam_access_handler_send(TALLOC_CTX *mem_ctx, state->pd = pd; subreq = sdap_access_send(state, params->ev, params->be_ctx, - params->domain, access_ctx, - access_ctx->id_ctx->conn, pd); + params->domain, access_ctx, pd); if (subreq == NULL) { pd->pam_status = PAM_SYSTEM_ERR; goto immediately; diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index 5970d9a3d8d..81102481996 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -674,14 +674,14 @@ struct auth_state { struct sss_auth_token *authtok; struct sdap_service *sdap_service; - struct sdap_handle *sh; + struct sss_failover_ldap_connection *conn; char *dn; enum pwexpire pw_expire_type; void *pw_expire_data; }; -static struct tevent_req *auth_connect_send(struct tevent_req *req); +static errno_t auth_connect_send(struct tevent_req *req); static void auth_get_dn_done(struct tevent_req *subreq); static void auth_do_bind(struct tevent_req *req); static void auth_connect_done(struct tevent_req *subreq); @@ -737,8 +737,8 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx, goto fail; } - if (auth_connect_send(req) == NULL) { - ret = ENOMEM; + ret = auth_connect_send(req); + if (ret != EOK) { goto fail; } @@ -750,14 +750,14 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx, return req; } -static struct tevent_req *auth_connect_send(struct tevent_req *req) +static errno_t auth_connect_send(struct tevent_req *req) { - struct tevent_req *subreq; struct auth_state *state = tevent_req_data(req, struct auth_state); bool use_tls; bool skip_conn_auth = false; const char *sasl_mech; + errno_t ret; /* Check for undocumented debugging feature to disable TLS * for authentication. This should never be used in production @@ -792,26 +792,18 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req) } } - if (ldap_is_ldapi_url(state->sdap_service->uri)) { + if (ldap_is_ldapi_url(state->ctx->fctx->active_server->uri)) { /* Don't force TLS on if we're a unix domain socket */ use_tls = false; } - subreq = sdap_cli_resolve_and_connect_send(state, state->ev, - state->ctx->opts, - state->ctx->be, - state->sdap_service, false, - use_tls ? CON_TLS_ON : CON_TLS_OFF, - skip_conn_auth); - - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return NULL; - } - - tevent_req_set_callback(subreq, auth_connect_done, req); + ret = sss_failover_transaction_ex_send( + state, state->ev, state->ctx->fctx, req, auth_connect_done, false, + !skip_conn_auth, true, + use_tls ? SSS_FAILOVER_TRANSACTION_TLS_ON + : SSS_FAILOVER_TRANSACTION_TLS_OFF); - return subreq; + return ret; } static bool check_encryption_used(LDAP *ldap) @@ -849,33 +841,19 @@ static void auth_connect_done(struct tevent_req *subreq) struct tevent_req); struct auth_state *state = tevent_req_data(req, struct auth_state); - int ret; - ret = sdap_cli_resolve_and_connect_recv(subreq, state, NULL, &state->sh, - NULL); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - /* As sdap_cli_resolve_and_connect_recv() returns EIO in case all the - * servers are down and we have to go offline, let's treat it - * accordingly here and allow the PAM responder to switch to offline - * authentication. - * - * Unfortunately, there's not much pattern within our code and the way - * to indicate we're going down in this part of the code is returning an - * ETIMEDOUT. - */ - if (ret == EIO) { - tevent_req_error(req, ETIMEDOUT); - } else { - if (auth_connect_send(req) == NULL) { - tevent_req_error(req, ENOMEM); - } - } + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - if (!ldap_is_ldapi_url(state->sdap_service->uri) && - !check_encryption_used(state->sh->ldap) && + if (!ldap_is_ldapi_url(state->conn->uri) && + !check_encryption_used(state->conn->sh->ldap) && !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS)) { DEBUG(SSSDBG_CRIT_FAILURE, "Aborting the authentication request.\n"); sss_log(SSS_LOG_CRIT, "Aborting the authentication request.\n"); @@ -887,7 +865,7 @@ static void auth_connect_done(struct tevent_req *subreq) /* The cached user entry was missing the bind DN. Need to look * it up based on user name in order to perform the bind */ subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain, - state->sh, state->ctx->opts, state->username); + state->conn->sh, state->ctx->opts, state->username); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -929,7 +907,7 @@ static void auth_do_bind(struct tevent_req *req) SDAP_USE_PPOLICY); int timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT); - subreq = sdap_auth_send(state, state->ev, state->sh, + subreq = sdap_auth_send(state, state->ev, state->conn->sh, NULL, NULL, state->dn, state->authtok, timeout, use_ppolicy, @@ -964,9 +942,7 @@ static void auth_bind_user_done(struct tevent_req *subreq) break; case ETIMEDOUT: case ERR_NETWORK_IO: - if (auth_connect_send(req) == NULL) { - tevent_req_error(req, ENOMEM); - } + tevent_req_error(req, ERR_SERVER_FAILURE); return; default: tevent_req_error(req, ret); @@ -983,7 +959,7 @@ static errno_t auth_recv(struct tevent_req *req, TALLOC_CTX *memctx, struct auth_state *state = tevent_req_data(req, struct auth_state); if (sh != NULL) { - *sh = talloc_steal(memctx, state->sh); + *sh = talloc_steal(memctx, state->conn->sh); if (*sh == NULL) return ENOMEM; } @@ -1116,6 +1092,7 @@ static void sdap_pam_auth_handler_done(struct tevent_req *subreq) case ERR_AUTH_FAILED: state->pd->pam_status = PAM_AUTH_ERR; break; + case ERR_NO_MORE_SERVERS: case ETIMEDOUT: case ERR_NETWORK_IO: state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; @@ -1317,9 +1294,9 @@ struct sdap_pam_chpass_handler_state { struct tevent_context *ev; struct sdap_auth_ctx *auth_ctx; struct pam_data *pd; - struct sdap_handle *sh; char *dn; enum pwexpire pw_expire_type; + struct sdap_handle *sh; }; static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq); @@ -1497,6 +1474,7 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq) } } break; + case ERR_NO_MORE_SERVERS: case ETIMEDOUT: case ERR_NETWORK_IO: state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 124040ea1be..29c9305a161 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -824,31 +824,6 @@ sdap_attrs_get_sid_str(TALLOC_CTX *mem_ctx, return EOK; } -struct sdap_id_conn_ctx * -sdap_id_ctx_conn_add(struct sdap_id_ctx *id_ctx, - struct sdap_service *sdap_service) -{ - struct sdap_id_conn_ctx *conn; - errno_t ret; - - conn = talloc_zero(id_ctx, struct sdap_id_conn_ctx); - if (conn == NULL) { - return NULL; - } - conn->service = talloc_steal(conn, sdap_service); - conn->id_ctx = id_ctx; - - /* Create a connection cache */ - ret = sdap_id_conn_cache_create(conn, conn, &conn->conn_cache); - if (ret != EOK) { - talloc_free(conn); - return NULL; - } - DLIST_ADD_END(id_ctx->conn, conn, struct sdap_id_conn_ctx *); - - return conn; -} - static int sdap_id_ctx_destructor(struct sdap_id_ctx *id_ctx) { be_ptask_destroy(&id_ctx->task); @@ -868,13 +843,7 @@ sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx, talloc_set_destructor(sdap_ctx, sdap_id_ctx_destructor); sdap_ctx->be = bectx; - - /* There should be at least one connection context */ - sdap_ctx->conn = sdap_id_ctx_conn_add(sdap_ctx, sdap_service); - if (sdap_ctx->conn == NULL) { - talloc_free(sdap_ctx); - return NULL; - } + sdap_ctx->service = sdap_service; return sdap_ctx; } diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index f887aad84b4..0c54d9cd06e 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -26,7 +26,6 @@ #include "providers/backend.h" #include "providers/ldap/sdap.h" -#include "providers/ldap/sdap_id_op.h" #include "providers/fail_over.h" #include "providers/krb5/krb5_common.h" #include "lib/idmap/sss_idmap.h" @@ -58,8 +57,6 @@ struct sdap_id_conn_ctx { struct sdap_id_ctx *id_ctx; struct sdap_service *service; - /* LDAP connection cache */ - struct sdap_id_conn_cache *conn_cache; /* dlinklist pointers */ struct sdap_id_conn_ctx *prev, *next; /* do not go offline, try another connection */ @@ -74,8 +71,8 @@ struct sdap_id_ctx { /* If using GSSAPI or GSS-SPNEGO */ struct krb5_service *krb5_service; - /* connection to a server */ - struct sdap_id_conn_ctx *conn; + + struct sdap_service *service; struct sdap_server_opts *srv_opts; @@ -95,6 +92,7 @@ struct sdap_id_ctx { struct sdap_auth_ctx { struct be_ctx *be; + struct sss_failover_ctx *fctx; struct sdap_options *opts; struct sdap_service *service; struct sdap_service *chpass_service; @@ -164,8 +162,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, + struct sss_failover_ctx *fctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, bool noexist_delete); errno_t sdap_handle_acct_req_recv(struct tevent_req *req, @@ -307,7 +305,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *name, int filter_type, bool noexist_delete, @@ -319,7 +317,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_search_base **search_bases, const char *filter_value, int filter_type, @@ -335,7 +333,7 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *name, bool noexist_delete); int ldap_netgroup_get_recv(struct tevent_req *req); @@ -345,7 +343,7 @@ services_get_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *name, const char *protocol, int filter_type, @@ -499,7 +497,7 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char* filter_value); int subid_ranges_get_recv(struct tevent_req *req); diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index faa02af742f..8731aa47e2e 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -35,6 +35,8 @@ #include "providers/ldap/sdap_async.h" #include "providers/ldap/sdap_idmap.h" #include "providers/ldap/sdap_users.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" errno_t users_get_handle_no_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, @@ -131,7 +133,8 @@ struct users_get_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; + struct sss_failover_ctx *fctx; struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -150,7 +153,6 @@ struct users_get_state { struct sysdb_attrs *extra_attrs; }; -static int users_get_retry(struct tevent_req *req); static void users_get_connect_done(struct tevent_req *subreq); static void users_get_search(struct tevent_req *req); static void users_get_done(struct tevent_req *subreq); @@ -159,7 +161,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_value, int filter_type, const char *extra_value, @@ -184,18 +186,11 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; + state->fctx = fctx; state->sdom = sdom; - state->conn = conn; state->noexist_delete = noexist_delete; state->extra_attrs = NULL; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; @@ -454,7 +449,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, NULL, &state->attrs, NULL); if (ret != EOK) goto done; - ret = users_get_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + users_get_connect_done); if (ret != EOK) { goto done; } @@ -470,33 +466,20 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, return tevent_req_post(req, ev); } -static int users_get_retry(struct tevent_req *req) -{ - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, users_get_connect_done, req); - return EOK; -} - static void users_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - int ret; + struct users_get_state *state = tevent_req_data(req, + struct users_get_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -520,7 +503,7 @@ static void users_get_search(struct tevent_req *req) state->domain, state->sysdb, state->ctx->opts, state->sdom->user_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -545,16 +528,8 @@ static void users_get_done(struct tevent_req *subreq) ret = sdap_get_users_recv(subreq, NULL, NULL); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = users_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); } if ((ret == ENOENT) && @@ -623,7 +598,8 @@ struct groups_get_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -640,7 +616,6 @@ struct groups_get_state { bool no_members; }; -static int groups_get_retry(struct tevent_req *req); static void groups_get_connect_done(struct tevent_req *subreq); static void groups_get_mpg_done(struct tevent_req *subreq); static void groups_get_search(struct tevent_req *req); @@ -650,7 +625,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_value, int filter_type, bool noexist_delete, @@ -675,18 +650,11 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; + state->fctx = fctx; state->sdom = sdom; - state->conn = conn; state->noexist_delete = noexist_delete; state->no_members = no_members; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; @@ -852,7 +820,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, if (ret != EOK) goto done; - ret = groups_get_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + groups_get_connect_done); if (ret != EOK) { goto done; } @@ -868,33 +837,19 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, return tevent_req_post(req, ev); } -static int groups_get_retry(struct tevent_req *req) -{ - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, groups_get_connect_done, req); - return EOK; -} - static void groups_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - int ret; - - ret = sdap_id_op_connect_recv(subreq); + struct groups_get_state *state = tevent_req_data(req, + struct groups_get_state); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -917,7 +872,7 @@ static void groups_get_search(struct tevent_req *req) subreq = sdap_get_groups_send(state, state->ev, state->sdom, state->ctx->opts, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -940,27 +895,15 @@ static void groups_get_done(struct tevent_req *subreq) ret = sdap_get_groups_recv(subreq, NULL, NULL); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = groups_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - - if (ret && ret != ENOENT) { + if (ret != EOK && ret != ENOENT) { + ret = ERR_SERVER_FAILURE; tevent_req_error(req, ret); - return; } if (ret == ENOENT && sss_domain_is_mpg(state->domain) == true - && !state->conn->no_mpg_user_fallback) { + && !state->fctx->no_mpg_user_fallback) { /* The requested filter did not find a group. Before giving up, we must * also check if the GID can be resolved through a primary group of a * user @@ -969,7 +912,7 @@ static void groups_get_done(struct tevent_req *subreq) state->ev, state->ctx, state->sdom, - state->conn, + state->fctx, state->filter_value, state->filter_type, NULL, @@ -1101,8 +1044,9 @@ int groups_get_recv(struct tevent_req *req) struct groups_by_user_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; + struct sss_failover_ctx *fctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -1119,7 +1063,6 @@ struct groups_by_user_state { bool noexist_delete; }; -static int groups_by_user_retry(struct tevent_req *req); static void groups_by_user_connect_done(struct tevent_req *subreq); static void groups_by_user_done(struct tevent_req *subreq); @@ -1127,7 +1070,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_search_base **search_bases, const char *filter_value, int filter_type, @@ -1146,17 +1089,10 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; - state->conn = conn; + state->fctx = fctx; state->sdom = sdom; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - state->filter_value = filter_value; state->filter_type = filter_type; state->extra_value = extra_value; @@ -1174,7 +1110,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, NULL, &state->attrs, NULL); if (ret != EOK) goto fail; - ret = groups_by_user_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + groups_by_user_connect_done); if (ret != EOK) { goto fail; } @@ -1187,46 +1124,30 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, return req; } -static int groups_by_user_retry(struct tevent_req *req) -{ - struct groups_by_user_state *state = tevent_req_data(req, - struct groups_by_user_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, groups_by_user_connect_done, req); - return EOK; -} - static void groups_by_user_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct groups_by_user_state *state = tevent_req_data(req, struct groups_by_user_state); - int ret; - - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_get_initgr_send(state, state->ev, state->sdom, - sdap_id_op_handle(state->op), + state->conn->sh, state->ctx, state->user_map, state->user_map_cnt, - state->conn, + state->fctx, state->search_bases, state->filter_value, state->filter_type, @@ -1250,19 +1171,6 @@ static void groups_by_user_done(struct tevent_req *subreq) ret = sdap_get_initgr_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - - if (ret != EOK) { - /* retry */ - ret = groups_by_user_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - switch (ret) { case ENOENT: if (state->noexist_delete == true) { @@ -1292,6 +1200,7 @@ static void groups_by_user_done(struct tevent_req *subreq) case EOK: break; default: + ret = ERR_SERVER_FAILURE; tevent_req_error(req, ret); return; } @@ -1315,7 +1224,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_value, int filter_type, bool noexist_delete); @@ -1339,6 +1248,7 @@ bool sdap_is_enum_request(struct dp_id_data *ar) /* A generic LDAP account info handler */ struct sdap_handle_acct_req_state { struct dp_id_data *ar; + struct sss_failover_ctx *fctx; const char *err; }; @@ -1349,8 +1259,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, + struct sss_failover_ctx *fctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, bool noexist_delete) { struct tevent_req *req; @@ -1365,6 +1275,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, return NULL; } state->ar = ar; + state->fctx = fctx; if (ar == NULL) { ret = EINVAL; @@ -1379,7 +1290,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, switch (ar->entry_type & BE_REQ_TYPE_MASK) { case BE_REQ_USER: /* user */ subreq = users_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1389,7 +1300,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, case BE_REQ_GROUP: /* group */ subreq = groups_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, noexist_delete, false, false); @@ -1405,7 +1316,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = groups_by_user_send(state, be_ctx->ev, id_ctx, - sdom, conn, NULL, + sdom, state->fctx, NULL, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1424,7 +1335,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, goto done; } subreq = subid_ranges_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value); #else ret = ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED; @@ -1441,7 +1352,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = ldap_netgroup_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, noexist_delete); break; @@ -1455,7 +1366,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = services_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->extra_value, ar->filter_type, @@ -1470,7 +1381,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, noexist_delete); @@ -1484,7 +1395,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, noexist_delete); @@ -1499,7 +1410,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, noexist_delete); @@ -1507,7 +1418,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, case BE_REQ_BY_CERT: subreq = users_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, state->fctx, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1637,7 +1548,7 @@ struct get_user_and_group_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ctx *fctx; struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -1658,7 +1569,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_val, int filter_type, bool noexist_delete) @@ -1677,23 +1588,16 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, state->ev = ev; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; + state->fctx = fctx; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_val = filter_val; state->filter_type = filter_type; subreq = groups_get_send(req, state->ev, state->id_ctx, - state->sdom, state->conn, + state->sdom, state->fctx, state->filter_val, state->filter_type, state->noexist_delete, false, false); if (subreq == NULL) { @@ -1733,7 +1637,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) tevent_req_done(req); return; } else if (ret != ENOENT) { - tevent_req_error(req, EIO); + tevent_req_error(req, ret); return; } @@ -1747,7 +1651,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) } subreq = users_get_send(req, state->ev, state->id_ctx, - state->sdom, user_conn, + state->sdom, state->fctx, state->filter_val, state->filter_type, NULL, state->noexist_delete, false); if (subreq == NULL) { @@ -1770,10 +1674,6 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) ret = users_get_recv(subreq); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } if (ret == ENOENT) { if (state->noexist_delete == true) { /* The search ran to completion, but nothing was found. @@ -1787,11 +1687,11 @@ static void get_user_and_group_users_done(struct tevent_req *subreq) } } } else if (ret != EOK) { - tevent_req_error(req, EIO); + tevent_req_error(req, ret); return; } - /* Both ret and sdap->ret are EOK. Matching user found */ + /* Matching user found */ tevent_req_done(req); return; } @@ -1834,7 +1734,7 @@ sdap_account_info_handler_send(TALLOC_CTX *mem_ctx, } subreq = sdap_handle_acct_req_send(state, params->be_ctx, data, id_ctx, - id_ctx->opts->sdom, id_ctx->conn, true); + id_ctx->fctx, id_ctx->opts->sdom, true); if (subreq == NULL) { ret = ENOMEM; goto immediately; diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index 684dc70d8e5..685baf73151 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/ldap_id_enum.c @@ -166,8 +166,7 @@ ldap_id_enumeration_send(TALLOC_CTX *mem_ctx, state->dom = ectx->sdom->dom; state->id_ctx = talloc_get_type_abort(ectx->pvt, struct sdap_id_ctx); - subreq = sdap_dom_enum_send(state, ev, state->id_ctx, ectx->sdom, - state->id_ctx->conn); + subreq = sdap_dom_enum_send(state, ev, state->id_ctx, ectx->sdom); if (subreq == NULL) { /* The ptask API will reschedule the enumeration on its own on * failure */ diff --git a/src/providers/ldap/ldap_id_netgroup.c b/src/providers/ldap/ldap_id_netgroup.c index 9240441b264..2bd70c34fb1 100644 --- a/src/providers/ldap/ldap_id_netgroup.c +++ b/src/providers/ldap/ldap_id_netgroup.c @@ -33,9 +33,10 @@ struct ldap_netgroup_get_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; + struct sss_failover_ctx *fctx; struct sdap_domain *sdom; struct sdap_id_op *op; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -51,7 +52,6 @@ struct ldap_netgroup_get_state { bool noexist_delete; }; -static int ldap_netgroup_get_retry(struct tevent_req *req); static void ldap_netgroup_get_connect_done(struct tevent_req *subreq); static void ldap_netgroup_get_done(struct tevent_req *subreq); @@ -59,7 +59,7 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *name, bool noexist_delete) { @@ -73,17 +73,10 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; + state->fctx = fctx; state->sdom = sdom; - state->conn = conn; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->name = name; @@ -109,7 +102,8 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, NULL, &state->attrs, NULL); if (ret != EOK) goto fail; - ret = ldap_netgroup_get_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + ldap_netgroup_get_connect_done); if (ret != EOK) { goto fail; } @@ -122,35 +116,19 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, return req; } -static int ldap_netgroup_get_retry(struct tevent_req *req) -{ - struct ldap_netgroup_get_state *state = tevent_req_data(req, - struct ldap_netgroup_get_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, ldap_netgroup_get_connect_done, req); - return EOK; -} - static void ldap_netgroup_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct ldap_netgroup_get_state *state = tevent_req_data(req, struct ldap_netgroup_get_state); - int ret; - - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -158,7 +136,7 @@ static void ldap_netgroup_get_connect_done(struct tevent_req *subreq) state->domain, state->sysdb, state->ctx->opts, state->sdom->netgroup_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, state->timeout); if (!subreq) { @@ -181,21 +159,9 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq) ret = sdap_get_netgroups_recv(subreq, state, NULL, &state->count, &state->netgroups); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - - if (ret != EOK) { - /* retry */ - ret = ldap_netgroup_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); return; } diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c index 019710b918b..239f63b6569 100644 --- a/src/providers/ldap/ldap_id_services.c +++ b/src/providers/ldap/ldap_id_services.c @@ -29,15 +29,17 @@ #include "db/sysdb_services.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" struct sdap_services_get_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; + struct sss_failover_ctx *fctx; const char *name; const char *protocol; @@ -50,8 +52,6 @@ struct sdap_services_get_state { bool noexist_delete; }; -static errno_t -services_get_retry(struct tevent_req *req); static void services_get_connect_done(struct tevent_req *subreq); static void @@ -62,7 +62,7 @@ services_get_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *name, const char *protocol, int filter_type, @@ -81,21 +81,14 @@ services_get_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; + state->fctx = fctx; state->name = name; state->protocol = protocol; state->filter_type = filter_type; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_MINOR_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto error; - } - switch(filter_type) { case BE_FILTER_NAME: attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_NAME].name; @@ -146,7 +139,8 @@ services_get_send(TALLOC_CTX *mem_ctx, &state->attrs, NULL); if (ret != EOK) goto error; - ret = services_get_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + services_get_connect_done); if (ret != EOK) goto error; return req; @@ -157,37 +151,21 @@ services_get_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t -services_get_retry(struct tevent_req *req) -{ - errno_t ret; - struct sdap_services_get_state *state = - tevent_req_data(req, struct sdap_services_get_state); - struct tevent_req *subreq; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, services_get_connect_done, req); - return EOK; -} - static void services_get_connect_done(struct tevent_req *subreq) { - errno_t ret; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sdap_services_get_state *state = tevent_req_data(req, struct sdap_services_get_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -195,7 +173,7 @@ services_get_connect_done(struct tevent_req *subreq) state->domain, state->sysdb, state->id_ctx->opts, state->sdom->service_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -221,25 +199,8 @@ services_get_done(struct tevent_req *subreq) ret = sdap_get_services_recv(NULL, subreq, NULL); talloc_zfree(subreq); - /* Check whether we need to try again with another - * failover server. - */ - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = services_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* Return to the mainloop to retry */ - return; - } - - /* An error occurred. */ - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); return; } @@ -257,8 +218,8 @@ services_get_done(struct tevent_req *subreq) case BE_FILTER_IDNUM: port = strtouint16(state->name, &endptr, 10); - if (errno || *endptr || (state->name == endptr)) { - tevent_req_error(req, (errno ? errno : EINVAL)); + if (*endptr || (state->name == endptr)) { + tevent_req_error(req, EINVAL); return; } diff --git a/src/providers/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c index 1095a97ee6a..3aed4e81ca3 100644 --- a/src/providers/ldap/ldap_id_subid.c +++ b/src/providers/ldap/ldap_id_subid.c @@ -30,7 +30,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_value, int filter_type, const char *extra_value, @@ -38,7 +38,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, bool set_non_posix); int users_get_recv(struct tevent_req *req); -static int subid_ranges_get_retry(struct tevent_req *req); static void subid_ranges_get_connect_done(struct tevent_req *subreq); static void subid_ranges_resolve_owner(struct tevent_req *req); static void subid_ranges_resolve_owner_done(struct tevent_req *subreq); @@ -49,8 +48,9 @@ static void subid_ranges_get_done(struct tevent_req *subreq); struct subid_ranges_get_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; + struct sss_failover_ctx *fctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *op; struct sss_domain_info *domain; @@ -64,7 +64,7 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, const char *filter_value) { struct tevent_req *req; @@ -78,8 +78,8 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; + state->fctx = fctx; state->sdom = sdom; - state->conn = conn; state->owner_name = talloc_strdup(state, filter_value); if (!state->owner_name) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed\n"); @@ -87,16 +87,10 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, goto done; } - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - state->domain = sdom->dom; - ret = subid_ranges_get_retry(req); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + subid_ranges_get_connect_done); if (ret != EOK) { goto done; } @@ -112,33 +106,20 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, return tevent_req_post(req, ev); } -static int subid_ranges_get_retry(struct tevent_req *req) -{ - struct subid_ranges_get_state *state = tevent_req_data(req, - struct subid_ranges_get_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, subid_ranges_get_connect_done, req); - return EOK; -} - static void subid_ranges_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - int ret; + struct subid_ranges_get_state *state = tevent_req_data(req, + struct subid_ranges_get_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -193,7 +174,7 @@ static void subid_ranges_resolve_owner(struct tevent_req *req) DEBUG(SSSDBG_TRACE_FUNC, "'%s' needs to be looked up online\n", state->owner_name); subreq = users_get_send(state, state->ev, state->ctx, - state->sdom, state->conn, + state->sdom, state->fctx, state->owner_name, BE_FILTER_NAME, NULL, false, false); @@ -210,16 +191,10 @@ static void subid_ranges_resolve_owner_done(struct tevent_req *subreq) struct tevent_req); struct subid_ranges_get_state *state = tevent_req_data(req, struct subid_ranges_get_state); - int ret; - ret = users_get_recv(subreq); + users_get_recv(subreq); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - state->owner_dn = get_user_dn(req, state->domain, state->owner_name); if (state->owner_dn == NULL) { DEBUG(SSSDBG_TRACE_FUNC, @@ -258,7 +233,7 @@ static void subid_ranges_get_search(struct tevent_req *req) } subreq = sdap_search_bases_send(state, state->ev, state->ctx->opts, - sdap_id_op_handle(state->op), + state->conn->sh, state->sdom->subid_ranges_search_bases, state->ctx->opts->subid_map, false, /* allow_paging */ @@ -288,23 +263,8 @@ static void subid_ranges_get_done(struct tevent_req *subreq) ret = sdap_search_bases_recv(subreq, state, &num_results, &results); talloc_zfree(subreq); if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = subid_ranges_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - return; - } - - if (ret && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve subid ranges.\n"); + ret = ERR_SERVER_FAILURE; tevent_req_error(req, ret); return; } diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index 039fdf0d9fc..3d3b504bfe5 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -54,7 +54,7 @@ static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx, auth_ctx->be = be_ctx; auth_ctx->fctx = fctx; auth_ctx->opts = options; - auth_ctx->service = id_ctx->conn->service; + auth_ctx->service = id_ctx->service; auth_ctx->chpass_service = NULL; *_auth_ctx = auth_ctx; @@ -168,7 +168,7 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, if (should_call_gssapi_init(options)) { ret = sdap_gssapi_init(id_ctx, options->basic, be_ctx, - id_ctx->conn->service, &id_ctx->krb5_service); + id_ctx->service, &id_ctx->krb5_service); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sdap_gssapi_init failed [%d][%s].\n", @@ -324,7 +324,6 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx, const char *module_name, void **_module_data) { - struct sdap_service *sdap_service; struct ldap_init_ctx *init_ctx; errno_t ret; @@ -343,15 +342,7 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx, goto done; } - /* Always initialize id_ctx since it is needed everywhere. */ - ret = get_sdap_service(init_ctx, be_ctx, init_ctx->options, &sdap_service); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service " - "[%d]: %s\n", ret, sss_strerror(ret)); - goto done; - } - - init_ctx->id_ctx = sdap_id_ctx_new(init_ctx, be_ctx, sdap_service); + init_ctx->id_ctx = sdap_id_ctx_new(init_ctx, be_ctx, NULL); if (init_ctx->id_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP ID context\n"); ret = ENOMEM; diff --git a/src/providers/ldap/ldap_resolver_enum.c b/src/providers/ldap/ldap_resolver_enum.c index 3098255b5d9..74ba366cfe7 100644 --- a/src/providers/ldap/ldap_resolver_enum.c +++ b/src/providers/ldap/ldap_resolver_enum.c @@ -252,8 +252,7 @@ ldap_resolver_enumeration_send(TALLOC_CTX *mem_ctx, subreq = sdap_dom_resolver_enum_send(state, ev, state->resolver_ctx, state->resolver_ctx->id_ctx, - state->resolver_ctx->id_ctx->opts->sdom, - state->resolver_ctx->id_ctx->conn); + state->resolver_ctx->id_ctx->opts->sdom); if (subreq == NULL) { /* The ptask API will reschedule the enumeration on its own on * failure */ diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 593f3d8f91f..933c1f838a6 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -72,7 +72,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, const char *username, struct ldb_message *user_entry, enum sdap_pwpolicy_mode pwpol_mod); @@ -82,7 +81,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, const char *username, struct ldb_message *user_entry); @@ -110,7 +108,6 @@ struct sdap_access_req_ctx { struct pam_data *pd; struct tevent_context *ev; struct sdap_access_ctx *access_ctx; - struct sdap_id_conn_ctx *conn; struct be_ctx *be_ctx; struct sss_domain_info *domain; struct ldb_message *user_entry; @@ -128,7 +125,6 @@ sdap_access_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, struct pam_data *pd) { errno_t ret; @@ -148,7 +144,6 @@ sdap_access_send(TALLOC_CTX *mem_ctx, state->pd = pd; state->ev = ev; state->access_ctx = access_ctx; - state->conn = conn; state->current_rule = 0; DEBUG(SSSDBG_TRACE_FUNC, @@ -225,7 +220,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state, subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx, state->domain, state->access_ctx, - state->conn, state->pd->user, state->user_entry, PWP_LOCKOUT_ONLY); @@ -244,7 +238,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state, subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx, state->domain, state->access_ctx, - state->conn, state->pd->user, state->user_entry, PWP_LOCKOUT_EXPIRE); @@ -263,7 +256,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state, subreq = sdap_access_filter_send(state, state->ev, state->be_ctx, state->domain, state->access_ctx, - state->conn, state->pd->user, state->user_entry); if (subreq == NULL) { @@ -825,8 +817,7 @@ struct sdap_access_filter_req_ctx { struct tevent_context *ev; struct sdap_access_ctx *access_ctx; struct sdap_options *opts; - struct sdap_id_conn_ctx *conn; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct sysdb_handle *handle; struct sss_domain_info *domain; /* cached result of access control checks */ @@ -835,7 +826,6 @@ struct sdap_access_filter_req_ctx { }; static errno_t sdap_access_decide_offline(bool cached_ac); -static int sdap_access_filter_retry(struct tevent_req *req); static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq); static errno_t sdap_access_ppolicy_get_lockout_step(struct tevent_req *req); static void sdap_access_filter_connect_done(struct tevent_req *subreq); @@ -845,7 +835,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, const char *username, struct ldb_message *user_entry) { @@ -870,7 +859,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, state->filter = NULL; state->username = username; state->opts = access_ctx->id_ctx->opts; - state->conn = conn; state->ev = ev; state->access_ctx = access_ctx; state->domain = domain; @@ -925,15 +913,8 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Checking filter against LDAP\n"); - state->sdap_op = sdap_id_op_create(state, - state->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - ret = sdap_access_filter_retry(req); + ret = sss_failover_transaction_send(state, ev, access_ctx->id_ctx->fctx, req, + sdap_access_filter_connect_done); if (ret != EOK) { goto done; } @@ -965,37 +946,20 @@ static errno_t sdap_access_decide_offline(bool cached_ac) } } -static int sdap_access_filter_retry(struct tevent_req *req) -{ - struct sdap_access_filter_req_ctx *state = - tevent_req_data(req, struct sdap_access_filter_req_ctx); - struct tevent_req *subreq; - int ret; - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: %d (%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, sdap_access_filter_connect_done, req); - return EOK; -} - static void sdap_access_filter_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sdap_access_filter_req_ctx *state = tevent_req_data(req, struct sdap_access_filter_req_ctx); - int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -1005,7 +969,7 @@ static void sdap_access_filter_connect_done(struct tevent_req *subreq) subreq = sdap_get_generic_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->basedn, LDAP_SCOPE_BASE, state->filter, NULL, @@ -1037,18 +1001,8 @@ static void sdap_access_filter_done(struct tevent_req *subreq) &num_results, &results); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - if (ret == ERR_INVALID_FILTER) { - sss_log(SSS_LOG_ERR, MALFORMED_FILTER, state->filter); - DEBUG(SSSDBG_CRIT_FAILURE, MALFORMED_FILTER, state->filter); - ret = ERR_ACCESS_DENIED; - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_get_generic_send() returned error [%d][%s]\n", - ret, sss_strerror(ret)); - } - + ret = ERR_SERVER_FAILURE; goto done; } @@ -1396,7 +1350,6 @@ errno_t sdap_access_rhost(struct ldb_message *user_entry, char *pam_rhost) } static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq); -static int sdap_access_ppolicy_retry(struct tevent_req *req); static errno_t sdap_access_ppolicy_step(struct tevent_req *req); static void sdap_access_ppolicy_step_done(struct tevent_req *subreq); @@ -1406,8 +1359,7 @@ struct sdap_access_ppolicy_req_ctx { struct tevent_context *ev; struct sdap_access_ctx *access_ctx; struct sdap_options *opts; - struct sdap_id_conn_ctx *conn; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct sysdb_handle *handle; struct sss_domain_info *domain; /* cached results of access control checks */ @@ -1425,7 +1377,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, const char *username, struct ldb_message *user_entry, enum sdap_pwpolicy_mode pwpol_mode) @@ -1443,7 +1394,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx, state->filter = NULL; state->username = username; state->opts = access_ctx->id_ctx->opts; - state->conn = conn; state->ev = ev; state->access_ctx = access_ctx; state->domain = domain; @@ -1471,15 +1421,8 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Checking ppolicy against LDAP\n"); - state->sdap_op = sdap_id_op_create(state, - state->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - ret = sdap_access_ppolicy_retry(req); + ret = sss_failover_transaction_send(state, ev, access_ctx->id_ctx->fctx, + req, sdap_access_ppolicy_connect_done); if (ret != EOK) { goto done; } @@ -1496,25 +1439,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx, return req; } -static int sdap_access_ppolicy_retry(struct tevent_req *req) -{ - struct sdap_access_ppolicy_req_ctx *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx); - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: %d (%s)\n", - ret, sss_strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, sdap_access_ppolicy_connect_done, req); - return EOK; -} - static const char** get_default_ppolicy_dns(TALLOC_CTX *mem_ctx, struct sdap_domain *sdom) { @@ -1548,11 +1472,13 @@ static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -1624,7 +1550,7 @@ sdap_access_ppolicy_get_lockout_step(struct tevent_req *req) subreq = sdap_get_generic_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->ppolicy_dns[state->ppolicy_dns_index], LDAP_SCOPE_BASE, NULL, attrs, @@ -1748,14 +1674,6 @@ static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq) done: if (ret != EAGAIN) { - /* release connection */ - tret = sdap_id_op_done(state->sdap_op, ret); - if (tret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_get_generic_send() returned error [%d][%s]\n", - ret, sss_strerror(ret)); - } - if (ret == EOK) { tevent_req_done(req); } else { @@ -1778,7 +1696,7 @@ errno_t sdap_access_ppolicy_step(struct tevent_req *req) subreq = sdap_get_generic_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->basedn, LDAP_SCOPE_BASE, NULL, attrs, @@ -1902,8 +1820,11 @@ static void sdap_access_ppolicy_step_done(struct tevent_req *subreq) ret = sdap_get_generic_recv(subreq, state, &num_results, &results); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { + if (ret == ERR_NO_MORE_SERVERS) { + ret = sdap_access_decide_offline(state->cached_access); + } else if (ret == ERR_SERVER_FAILURE) { + goto done; + } else if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_done() returned error [%d][%s]\n", ret, sss_strerror(ret)); diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h index 2a13a9fbe17..0a57ebbc63a 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -27,7 +27,6 @@ #include "providers/backend.h" #include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_id_op.h" /* Attributes in sysdb, used for caching last values of lockout or filter * access control checks. @@ -101,7 +100,6 @@ sdap_access_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, - struct sdap_id_conn_ctx *conn, struct pam_data *pd); errno_t sdap_access_recv(struct tevent_req *req); diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index d342b5d9d28..3f0b8f77984 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -28,8 +28,11 @@ #include #include "providers/backend.h" #include "providers/ldap/sdap.h" -#include "providers/ldap/sdap_id_op.h" +#include "providers/ldap/ldap_common.h" #include "providers/fail_over.h" +#include "providers/failover/failover.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" #define AD_TOKENGROUPS_ATTR "tokenGroups" @@ -161,7 +164,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct sdap_id_ctx *id_ctx, struct sdap_attr_map *user_map, size_t user_map_cnt, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ldap_connection *conn, struct sdap_search_base **search_bases, const char *name, int filter_type, @@ -411,7 +414,7 @@ struct tevent_req * enum_services_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge); errno_t @@ -438,7 +441,7 @@ struct tevent_req * enum_iphosts_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge); errno_t @@ -466,7 +469,7 @@ struct tevent_req * enum_ipnetworks_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge); errno_t @@ -476,7 +479,7 @@ struct tevent_req * sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, diff --git a/src/providers/ldap/sdap_async_ad.h b/src/providers/ldap/sdap_async_ad.h index a5f47a1a946..4ca49a92f6c 100644 --- a/src/providers/ldap/sdap_async_ad.h +++ b/src/providers/ldap/sdap_async_ad.h @@ -50,7 +50,7 @@ struct tevent_req * sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_options *opts, struct sss_domain_info *domain, char **sids); diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c index 0ea1ce3de8d..0f395827d56 100644 --- a/src/providers/ldap/sdap_async_autofs.c +++ b/src/providers/ldap/sdap_async_autofs.c @@ -640,7 +640,6 @@ struct sdap_autofs_setautomntent_state { struct sdap_options *opts; struct sdap_handle *sh; struct sysdb_ctx *sysdb; - struct sdap_id_op *sdap_op; struct sss_domain_info *dom; const char *mapname; @@ -658,7 +657,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, struct sss_domain_info *dom, struct sysdb_ctx *sysdb, struct sdap_handle *sh, - struct sdap_id_op *op, struct sdap_options *opts, const char *mapname) { @@ -681,7 +679,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, state->sh = sh; state->sysdb = sysdb; state->opts = opts; - state->sdap_op = op; state->dom = dom; state->mapname = mapname; @@ -965,12 +962,11 @@ sdap_autofs_setautomntent_recv(struct tevent_req *req) struct sdap_autofs_get_map_state { struct sdap_id_ctx *id_ctx; + struct sss_failover_ldap_connection *conn; struct sdap_options *opts; - struct sdap_id_op *sdap_op; const char *mapname; }; -static errno_t sdap_autofs_get_map_retry(struct tevent_req *req); static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq); static void sdap_autofs_get_map_done(struct tevent_req *subreq); @@ -991,50 +987,15 @@ struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, state->opts = id_ctx->opts; state->mapname = mapname; - state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto done; - } - - ret = sdap_autofs_get_map_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } - -done: - if (ret == EOK) { - tevent_req_done(req); - } else { + ret = sss_failover_transaction_send(state, id_ctx->be->ev, id_ctx->fctx, req, + sdap_autofs_get_map_connect_done); + if (ret != EOK) { tevent_req_error(req, ret); } - tevent_req_post(req, id_ctx->be->ev); return req; } -static errno_t sdap_autofs_get_map_retry(struct tevent_req *req) -{ - struct sdap_autofs_get_map_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct sdap_autofs_get_map_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: " - "%d(%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, sdap_autofs_get_map_connect_done, req); - - return EAGAIN; -} - static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) { struct tevent_req *req; @@ -1047,18 +1008,16 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_autofs_get_map_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed " - "[%d]: %s\n", ret, strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - DEBUG(SSSDBG_TRACE_FUNC, "LDAP connection successful\n"); - ret = sss_filter_sanitize(state, state->mapname, &safe_mapname); if (ret != EOK) { tevent_req_error(req, ret); @@ -1084,7 +1043,7 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) } subreq = sdap_search_bases_return_first_send(state, state->id_ctx->be->ev, - state->opts, sdap_id_op_handle(state->sdap_op), + state->opts, state->conn->sh, state->opts->sdom->autofs_search_bases, state->opts->autofs_mobject_map, false, dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -1112,15 +1071,8 @@ static void sdap_autofs_get_map_done(struct tevent_req *subreq) &reply); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - /* retry */ - ret = sdap_autofs_get_map_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { + ret = ERR_SERVER_FAILURE; tevent_req_error(req, ret); return; } @@ -1161,12 +1113,11 @@ errno_t sdap_autofs_get_map_recv(struct tevent_req *req) struct sdap_autofs_get_entry_state { struct sdap_id_ctx *id_ctx; struct sdap_options *opts; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; const char *mapname; const char *entryname; }; -static errno_t sdap_autofs_get_entry_retry(struct tevent_req *req); static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq); static void sdap_autofs_get_entry_done(struct tevent_req *subreq); @@ -1189,50 +1140,16 @@ struct tevent_req *sdap_autofs_get_entry_send(TALLOC_CTX *mem_ctx, state->mapname = mapname; state->entryname = entryname; - state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto done; - } - - ret = sdap_autofs_get_entry_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } + ret = sss_failover_transaction_send(state, id_ctx->be->ev, id_ctx->fctx, req, + sdap_autofs_get_entry_connect_done); -done: - if (ret == EOK) { - tevent_req_done(req); - } else { + if (ret != EOK) { tevent_req_error(req, ret); } - tevent_req_post(req, id_ctx->be->ev); return req; } -static errno_t sdap_autofs_get_entry_retry(struct tevent_req *req) -{ - struct sdap_autofs_get_entry_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct sdap_autofs_get_entry_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: " - "%d(%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, sdap_autofs_get_entry_connect_done, req); - - return EAGAIN; -} - static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq) { struct tevent_req *req; @@ -1247,13 +1164,13 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_autofs_get_entry_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed " - "[%d]: %s\n", ret, strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -1304,7 +1221,7 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq) } subreq = sdap_search_bases_return_first_send(state, state->id_ctx->be->ev, - state->opts, sdap_id_op_handle(state->sdap_op), + state->opts, state->conn->sh, state->opts->sdom->autofs_search_bases, state->opts->autofs_entry_map, false, dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -1339,16 +1256,8 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq) &reply); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - /* retry */ - ret = sdap_autofs_get_entry_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { - tevent_req_error(req, ret); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c index c48838028d6..4292f5ee43a 100644 --- a/src/providers/ldap/sdap_async_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -36,7 +36,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge); static errno_t enum_users_recv(struct tevent_req *req); @@ -44,7 +44,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge); static errno_t enum_groups_recv(struct tevent_req *req); @@ -54,20 +54,13 @@ struct sdap_dom_enum_ex_state { struct sdap_id_ctx *ctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *user_conn; - struct sdap_id_conn_ctx *group_conn; - struct sdap_id_conn_ctx *svc_conn; - struct sdap_id_op *user_op; - struct sdap_id_op *group_op; - struct sdap_id_op *svc_op; + struct sss_failover_ldap_connection *conn; + struct sss_failover_ldap_connection *group_conn; + struct sss_failover_ldap_connection *svc_conn; bool purge; }; -static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, - struct sdap_id_op *op, - tevent_req_fn tcb); -static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq); static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq); static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq); static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq); @@ -79,10 +72,7 @@ struct tevent_req * sdap_dom_enum_ex_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *user_conn, - struct sdap_id_conn_ctx *group_conn, - struct sdap_id_conn_ctx *svc_conn) + struct sdap_domain *sdom) { struct tevent_req *req; struct sdap_dom_enum_ex_state *state; @@ -95,9 +85,6 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; state->sdom = sdom; - state->user_conn = user_conn; - state->group_conn = group_conn; - state->svc_conn = svc_conn; ctx->last_enum = tevent_timeval_current(); t = dp_opt_get_int(ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT); @@ -105,17 +92,10 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx, state->purge = true; } - state->user_op = sdap_id_op_create(state, user_conn->conn_cache); - if (state->user_op == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for users\n"); - ret = EIO; - goto fail; - } - - ret = sdap_dom_enum_ex_retry(req, state->user_op, - sdap_dom_enum_ex_get_users); + ret = sss_failover_transaction_send(state, ev, ctx->fctx, req, + sdap_dom_enum_ex_get_users); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_ex_retry failed\n"); + DEBUG(SSSDBG_OP_FAILURE, "sss_failover_transaction_send failed\n"); goto fail; } @@ -127,45 +107,6 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx, return req; } -static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, - struct sdap_id_op *op, - tevent_req_fn tcb) -{ - struct sdap_dom_enum_ex_state *state = tevent_req_data(req, - struct sdap_dom_enum_ex_state); - struct tevent_req *subreq; - errno_t ret; - - subreq = sdap_id_op_connect_send(op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: %d\n", ret); - return ret; - } - - tevent_req_set_callback(subreq, tcb, req); - return EOK; -} - -static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq) -{ - errno_t ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - ret = sdap_id_op_connect_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Domain enumeration failed to connect to " \ - "LDAP server: (%d)[%s]\n", ret, strerror(ret)); - tevent_req_error(req, ret); - return false; - } - - return true; -} - static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, @@ -173,13 +114,19 @@ static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); - if (sdap_dom_enum_ex_connected(subreq) == false) { + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = enum_users_send(state, state->ev, state->ctx, state->sdom, - state->user_op, state->purge); + state->conn, state->purge); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -197,33 +144,19 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) ret = enum_users_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->user_op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_dom_enum_ex_retry(req, state->user_op, - sdap_dom_enum_ex_get_users); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + if (ret == ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); + tevent_req_done(req); return; } else if (ret != EOK && ret != ENOENT) { - /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "User enumeration failed: %d: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } - state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache); - if (state->group_op == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for groups\n"); - tevent_req_error(req, EIO); - return; - } - - ret = sdap_dom_enum_ex_retry(req, state->group_op, - sdap_dom_enum_ex_get_groups); + ret = sss_failover_transaction_send(state, state->ev, state->ctx->fctx, req, + sdap_dom_enum_ex_get_groups); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -239,13 +172,19 @@ static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); - if (sdap_dom_enum_ex_connected(subreq) == false) { + state->group_conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->group_conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = enum_groups_send(state, state->ev, state->ctx, state->sdom, - state->group_op, state->purge); + state->group_conn, state->purge); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -263,17 +202,7 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) ret = enum_groups_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->group_op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_dom_enum_ex_retry(req, state->group_op, - sdap_dom_enum_ex_get_groups); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - return; - } else if (ret != EOK && ret != ENOENT) { + if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "Group enumeration failed: %d: %s\n", ret, sss_strerror(ret)); @@ -281,16 +210,9 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) return; } + ret = sss_failover_transaction_send(state, state->ev, state->ctx->fctx, req, + sdap_dom_enum_ex_get_svcs); - state->svc_op = sdap_id_op_create(state, state->svc_conn->conn_cache); - if (state->svc_op == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for svcs\n"); - tevent_req_error(req, EIO); - return; - } - - ret = sdap_dom_enum_ex_retry(req, state->svc_op, - sdap_dom_enum_ex_get_svcs); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -304,12 +226,18 @@ static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq) struct sdap_dom_enum_ex_state *state = tevent_req_data(req, struct sdap_dom_enum_ex_state); - if (sdap_dom_enum_ex_connected(subreq) == false) { + state->svc_conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->svc_conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = enum_services_send(state, state->ev, state->ctx, - state->svc_op, state->purge); + state->svc_conn, state->purge); if (!subreq) { tevent_req_error(req, ENOMEM); return; @@ -327,21 +255,14 @@ static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq) ret = enum_services_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->svc_op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_dom_enum_ex_retry(req, state->user_op, - sdap_dom_enum_ex_get_svcs); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + if (ret == ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); + tevent_req_done(req); return; - } else if (ret != EOK && ret != ENOENT) { - /* Non-recoverable error */ + } else if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Service enumeration failed: %d: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } @@ -384,10 +305,9 @@ struct tevent_req * sdap_dom_enum_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn) + struct sdap_domain *sdom) { - return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom, conn, conn, conn); + return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom); } errno_t sdap_dom_enum_recv(struct tevent_req *req) @@ -400,7 +320,7 @@ struct enum_users_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; char *filter; const char **attrs; @@ -412,7 +332,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge) { struct tevent_req *req, *subreq; @@ -426,7 +346,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, state->ev = ev; state->sdom = sdom; state->ctx = ctx; - state->op = op; + state->conn = conn; use_mapping = sdap_idmap_domain_has_algorithmic_mapping( ctx->opts->idmap_ctx, @@ -466,7 +386,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, goto fail; } - if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) { + if (conn->srv_opts && conn->srv_opts->max_user_value && !purge) { /* If we have lastUSN available and we're not doing a full * refresh, limit to changes with a higher entryUSN value. */ @@ -474,9 +394,9 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, state->filter, "(%s>=%s)(!(%s=%s))", ctx->opts->user_map[SDAP_AT_USER_USN].name, - ctx->srv_opts->max_user_value, + conn->srv_opts->max_user_value, ctx->opts->user_map[SDAP_AT_USER_USN].name, - ctx->srv_opts->max_user_value); + conn->srv_opts->max_user_value); if (!state->filter) { DEBUG(SSSDBG_MINOR_FAILURE, @@ -508,7 +428,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, state->sdom->dom->sysdb, state->ctx->opts, state->sdom->user_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, SDAP_ENUM_SEARCH_TIMEOUT), @@ -546,19 +466,19 @@ static void enum_users_done(struct tevent_req *subreq) } if (usn_value) { - talloc_zfree(state->ctx->srv_opts->max_user_value); - state->ctx->srv_opts->max_user_value = + talloc_zfree(state->conn->srv_opts->max_user_value); + state->conn->srv_opts->max_user_value = talloc_steal(state->ctx, usn_value); errno = 0; usn_number = strtoul(usn_value, &endptr, 10); if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value) - && (usn_number > state->ctx->srv_opts->last_usn)) { - state->ctx->srv_opts->last_usn = usn_number; + && (usn_number > state->conn->srv_opts->last_usn)) { + state->conn->srv_opts->last_usn = usn_number; } } DEBUG(SSSDBG_CONF_SETTINGS, "Users higher USN value: [%s]\n", - state->ctx->srv_opts->max_user_value); + state->conn->srv_opts->max_user_value); tevent_req_done(req); } @@ -575,7 +495,7 @@ struct enum_groups_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; char *filter; const char **attrs; @@ -587,7 +507,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge) { struct tevent_req *req, *subreq; @@ -603,7 +523,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, state->ev = ev; state->sdom = sdom; state->ctx = ctx; - state->op = op; + state->conn = conn; if (sdom->dom->type == DOM_TYPE_APPLICATION) { non_posix = true; @@ -652,14 +572,14 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, goto fail; } - if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) { + if (state->conn->srv_opts && state->conn->srv_opts->max_group_value && !purge) { state->filter = talloc_asprintf_append_buffer( state->filter, "(%s>=%s)(!(%s=%s))", ctx->opts->group_map[SDAP_AT_GROUP_USN].name, - ctx->srv_opts->max_group_value, + state->conn->srv_opts->max_group_value, ctx->opts->group_map[SDAP_AT_GROUP_USN].name, - ctx->srv_opts->max_group_value); + state->conn->srv_opts->max_group_value); if (!state->filter) { DEBUG(SSSDBG_MINOR_FAILURE, "Failed to build base filter\n"); @@ -688,7 +608,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, subreq = sdap_get_groups_send(state, state->ev, state->sdom, state->ctx->opts, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, SDAP_ENUM_SEARCH_TIMEOUT), @@ -726,19 +646,19 @@ static void enum_groups_done(struct tevent_req *subreq) } if (usn_value) { - talloc_zfree(state->ctx->srv_opts->max_group_value); - state->ctx->srv_opts->max_group_value = + talloc_zfree(state->conn->srv_opts->max_group_value); + state->conn->srv_opts->max_group_value = talloc_steal(state->ctx, usn_value); errno = 0; usn_number = strtoul(usn_value, &endptr, 10); if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value) - && (usn_number > state->ctx->srv_opts->last_usn)) { - state->ctx->srv_opts->last_usn = usn_number; + && (usn_number > state->conn->srv_opts->last_usn)) { + state->conn->srv_opts->last_usn = usn_number; } } DEBUG(SSSDBG_CONF_SETTINGS, "Groups higher USN value: [%s]\n", - state->ctx->srv_opts->max_group_value); + state->conn->srv_opts->max_group_value); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_async_enum.h b/src/providers/ldap/sdap_async_enum.h index 2da38f98891..9e728213397 100644 --- a/src/providers/ldap/sdap_async_enum.h +++ b/src/providers/ldap/sdap_async_enum.h @@ -30,10 +30,7 @@ struct tevent_req * sdap_dom_enum_ex_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *user_conn, - struct sdap_id_conn_ctx *group_conn, - struct sdap_id_conn_ctx *svc_conn); + struct sdap_domain *sdom); errno_t sdap_dom_enum_ex_recv(struct tevent_req *req); @@ -41,8 +38,7 @@ struct tevent_req * sdap_dom_enum_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn); + struct sdap_domain *sdom); errno_t sdap_dom_enum_recv(struct tevent_req *req); diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index c5ce04dc079..23f5e65cc99 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2651,7 +2651,8 @@ struct sdap_get_initgr_state { struct sdap_domain *sdom; struct sdap_handle *sh; struct sdap_id_ctx *id_ctx; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *user_op; const char *filter_value; const char **grp_attrs; @@ -2671,7 +2672,6 @@ struct sdap_get_initgr_state { }; static errno_t sdap_get_initgr_next_base(struct tevent_req *req); -static errno_t sdap_get_initgr_user_connect(struct tevent_req *req); static void sdap_get_initgr_user_connect_done(struct tevent_req *subreq); static void sdap_get_initgr_user(struct tevent_req *subreq); static void sdap_get_initgr_done(struct tevent_req *subreq); @@ -2683,7 +2683,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct sdap_id_ctx *id_ctx, struct sdap_attr_map *user_map, size_t user_map_cnt, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_search_base **search_bases, const char *filter_value, int filter_type, @@ -2717,7 +2717,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, state->sdom = sdom; state->sh = sh; state->id_ctx = id_ctx; - state->conn = conn; + state->fctx = fctx; state->filter_value = filter_value; state->grp_attrs = grp_attrs; state->orig_user = NULL; @@ -2863,7 +2863,9 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, state->dom->name, state->dom->domain_id); - ret = sdap_get_initgr_user_connect(req); + + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + sdap_get_initgr_user_connect_done); done: if (ret != EOK) { @@ -2874,46 +2876,22 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, return req; } -static errno_t sdap_get_initgr_user_connect(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_get_initgr_state *state; - int ret = EOK; - struct sdap_id_conn_ctx *user_conn = NULL; - - state = tevent_req_data(req, struct sdap_get_initgr_state); - - /* Prefer LDAP over GC for users */ - user_conn = get_ldap_conn_from_sdom_pvt(state->id_ctx->opts, state->sdom); - state->user_op = sdap_id_op_create(state, user_conn == NULL - ? state->conn->conn_cache - : user_conn->conn_cache); - if (state->user_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - return ENOMEM; - } - - subreq = sdap_id_op_connect_send(state->user_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed\n"); - return ret; - } - - tevent_req_set_callback(subreq, sdap_get_initgr_user_connect_done, req); - return EOK; -} - static void sdap_get_initgr_user_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); int ret; - ret = sdap_id_op_connect_recv(subreq); + struct sdap_get_initgr_state *state = + tevent_req_data(req, struct sdap_get_initgr_state); + + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -2943,7 +2921,7 @@ static errno_t sdap_get_initgr_next_base(struct tevent_req *req) state->user_search_bases[state->user_base_iter]->basedn); subreq = sdap_get_generic_send( - state, state->ev, state->opts, sdap_id_op_handle(state->user_op), + state, state->ev, state->opts, state->conn->sh, state->user_search_bases[state->user_base_iter]->basedn, state->user_search_bases[state->user_base_iter]->scope, state->filter, state->user_attrs, @@ -3111,18 +3089,18 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) */ subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, state->id_ctx, - state->conn, + state->fctx, state->opts, state->sysdb, state->dom, - state->sh, + state->conn->sh, cname, orig_dn, state->timeout, state->use_id_mapping); } else { subreq = sdap_initgr_rfc2307bis_send( state, state->ev, state->opts, - state->sdom, state->sh, + state->sdom, state->conn->sh, cname, orig_dn); } if (!subreq) { @@ -3394,7 +3372,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) } subreq = groups_get_send(req, state->ev, state->id_ctx, - state->id_ctx->opts->sdom, state->conn, + state->id_ctx->opts->sdom, state->fctx, gid, BE_FILTER_IDNUM, false, false, false); if (!subreq) { diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index 0eed0ca0f2b..1cc7bca06d7 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -250,6 +250,7 @@ sdap_ad_tokengroups_update_members(const char *username, struct sdap_ad_resolve_sids_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; + struct sss_failover_ctx *fctx; struct sdap_id_conn_ctx *conn; struct sdap_options *opts; struct sss_domain_info *domain; @@ -266,7 +267,7 @@ struct tevent_req * sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_options *opts, struct sss_domain_info *domain, char **sids) @@ -284,7 +285,7 @@ sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; - state->conn = conn; + state->fctx = fctx; state->opts = opts; state->domain = get_domains_head(domain); state->sids = sids; @@ -345,8 +346,8 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req) } subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain, - state->conn, state->current_sid, - BE_FILTER_SECID, false, true, false); + state->fctx, state->current_sid, BE_FILTER_SECID, + false, true, false); if (subreq == NULL) { return ENOMEM; } @@ -377,8 +378,8 @@ static void sdap_ad_resolve_sids_done(struct tevent_req *subreq) state->current_sid); } else if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s, " - "ret: %d]: %s\n", state->current_sid, ret, - strerror(ret)); + "ret: %d]: %s\n", state->current_sid, + ret, strerror(ret)); goto done; } diff --git a/src/providers/ldap/sdap_async_iphost.c b/src/providers/ldap/sdap_async_iphost.c index 4b4dcadbe5f..846ed5f959a 100644 --- a/src/providers/ldap/sdap_async_iphost.c +++ b/src/providers/ldap/sdap_async_iphost.c @@ -507,7 +507,7 @@ sdap_get_iphost_recv(TALLOC_CTX *mem_ctx, struct enum_iphosts_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; struct sss_domain_info *domain; struct sysdb_ctx *sysdb; @@ -522,7 +522,7 @@ struct tevent_req * enum_iphosts_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge) { errno_t ret; @@ -537,9 +537,9 @@ enum_iphosts_send(TALLOC_CTX *memctx, state->id_ctx = id_ctx; state->domain = id_ctx->be->domain; state->sysdb = id_ctx->be->domain->sysdb; - state->op = op; + state->conn = conn; - if (id_ctx->srv_opts && id_ctx->srv_opts->max_iphost_value && !purge) { + if (conn->srv_opts && conn->srv_opts->max_iphost_value && !purge) { state->filter = talloc_asprintf( state, "(&(objectclass=%s)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))", @@ -547,9 +547,9 @@ enum_iphosts_send(TALLOC_CTX *memctx, id_ctx->opts->iphost_map[SDAP_AT_IPHOST_NAME].name, id_ctx->opts->iphost_map[SDAP_AT_IPHOST_NUMBER].name, id_ctx->opts->iphost_map[SDAP_AT_IPHOST_USN].name, - id_ctx->srv_opts->max_iphost_value, + conn->srv_opts->max_iphost_value, id_ctx->opts->iphost_map[SDAP_AT_IPHOST_USN].name, - id_ctx->srv_opts->max_iphost_value); + conn->srv_opts->max_iphost_value); } else { state->filter = talloc_asprintf( state, @@ -575,7 +575,7 @@ enum_iphosts_send(TALLOC_CTX *memctx, state->domain, state->sysdb, state->id_ctx->opts, state->id_ctx->opts->sdom->iphost_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -614,19 +614,19 @@ enum_iphosts_op_done(struct tevent_req *subreq) } if (usn_value) { - talloc_zfree(state->id_ctx->srv_opts->max_iphost_value); - state->id_ctx->srv_opts->max_iphost_value = + talloc_zfree(state->conn->srv_opts->max_iphost_value); + state->conn->srv_opts->max_iphost_value = talloc_steal(state->id_ctx, usn_value); errno = 0; usn_number = strtoul(usn_value, &endptr, 10); if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value) - && (usn_number > state->id_ctx->srv_opts->last_usn)) { - state->id_ctx->srv_opts->last_usn = usn_number; + && (usn_number > state->conn->srv_opts->last_usn)) { + state->conn->srv_opts->last_usn = usn_number; } } DEBUG(SSSDBG_FUNC_DATA, "IP host higher USN value: [%s]\n", - state->id_ctx->srv_opts->max_iphost_value); + state->conn->srv_opts->max_iphost_value); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_async_ipnetwork.c b/src/providers/ldap/sdap_async_ipnetwork.c index 5e5b18158c0..ff1fec89bb5 100644 --- a/src/providers/ldap/sdap_async_ipnetwork.c +++ b/src/providers/ldap/sdap_async_ipnetwork.c @@ -493,6 +493,7 @@ sdap_get_ipnetwork_recv(TALLOC_CTX *mem_ctx, struct enum_ipnetworks_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *op; struct sss_domain_info *domain; struct sysdb_ctx *sysdb; @@ -508,7 +509,7 @@ struct tevent_req * enum_ipnetworks_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge) { errno_t ret; @@ -523,9 +524,9 @@ enum_ipnetworks_send(TALLOC_CTX *memctx, state->id_ctx = id_ctx; state->domain = id_ctx->be->domain; state->sysdb = id_ctx->be->domain->sysdb; - state->op = op; + state->conn = conn; - if (id_ctx->srv_opts && id_ctx->srv_opts->max_ipnetwork_value && !purge) { + if (conn->srv_opts && conn->srv_opts->max_ipnetwork_value && !purge) { state->filter = talloc_asprintf( state, "(&(objectclass=%s)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))", @@ -533,9 +534,9 @@ enum_ipnetworks_send(TALLOC_CTX *memctx, id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NAME].name, id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NUMBER].name, id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_USN].name, - id_ctx->srv_opts->max_ipnetwork_value, + conn->srv_opts->max_ipnetwork_value, id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_USN].name, - id_ctx->srv_opts->max_ipnetwork_value); + conn->srv_opts->max_ipnetwork_value); } else { state->filter = talloc_asprintf( state, @@ -560,7 +561,7 @@ enum_ipnetworks_send(TALLOC_CTX *memctx, subreq = sdap_get_ipnetwork_send(state, state->ev, state->domain, state->sysdb, state->id_ctx->opts, state->id_ctx->opts->sdom->ipnetwork_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -599,19 +600,19 @@ enum_ipnetworks_op_done(struct tevent_req *subreq) } if (usn_value) { - talloc_zfree(state->id_ctx->srv_opts->max_ipnetwork_value); - state->id_ctx->srv_opts->max_ipnetwork_value = + talloc_zfree(state->conn->srv_opts->max_ipnetwork_value); + state->conn->srv_opts->max_ipnetwork_value = talloc_steal(state->id_ctx, usn_value); errno = 0; usn_number = strtoul(usn_value, &endptr, 10); if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value) - && (usn_number > state->id_ctx->srv_opts->last_usn)) { - state->id_ctx->srv_opts->last_usn = usn_number; + && (usn_number > state->conn->srv_opts->last_usn)) { + state->conn->srv_opts->last_usn = usn_number; } } DEBUG(SSSDBG_FUNC_DATA, "IP network higher USN value: [%s]\n", - state->id_ctx->srv_opts->max_ipnetwork_value); + state->conn->srv_opts->max_ipnetwork_value); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_async_resolver_enum.c b/src/providers/ldap/sdap_async_resolver_enum.c index bb4693b09c8..973cb95d4e1 100644 --- a/src/providers/ldap/sdap_async_resolver_enum.c +++ b/src/providers/ldap/sdap_async_resolver_enum.c @@ -25,10 +25,6 @@ #include "providers/ldap/ldap_resolver_enum.h" #include "providers/ldap/sdap_async_resolver_enum.h" -static errno_t sdap_dom_resolver_enum_retry(struct tevent_req *req, - struct sdap_id_op *op, - tevent_req_fn tcb); -static bool sdap_dom_resolver_enum_connected(struct tevent_req *subreq); static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq); static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq); static void sdap_dom_resolver_enum_get_ipnetwork(struct tevent_req *subreq); @@ -40,9 +36,8 @@ struct sdap_dom_resolver_enum_state { struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; - struct sdap_id_op *iphost_op; - struct sdap_id_op *ipnetwork_op; + struct sss_failover_ldap_connection *iphost_conn; + struct sss_failover_ldap_connection *ipnetwork_conn; bool purge; }; @@ -52,8 +47,7 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_resolver_ctx *resolver_ctx, struct sdap_id_ctx *id_ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn) + struct sdap_domain *sdom) { struct tevent_req *req; struct sdap_dom_resolver_enum_state *state; @@ -67,7 +61,6 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx, state->resolver_ctx = resolver_ctx; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; state->resolver_ctx->last_enum = tevent_timeval_current(); t = dp_opt_get_int(resolver_ctx->id_ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT); @@ -75,17 +68,10 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx, state->purge = true; } - state->iphost_op = sdap_id_op_create(state, conn->conn_cache); - if (state->iphost_op == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for iphosts\n"); - ret = EIO; - goto fail; - } - - ret = sdap_dom_resolver_enum_retry(req, state->iphost_op, - sdap_dom_resolver_enum_get_iphost); + ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req, + sdap_dom_resolver_enum_get_iphost); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_retry failed\n"); + DEBUG(SSSDBG_OP_FAILURE, "sss_failover_transaction_send failed\n"); goto fail; } @@ -97,55 +83,6 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx, return req; } -static errno_t -sdap_dom_resolver_enum_retry(struct tevent_req *req, - struct sdap_id_op *op, - tevent_req_fn tcb) -{ - struct sdap_dom_resolver_enum_state *state; - struct tevent_req *subreq; - errno_t ret; - - state = tevent_req_data(req, struct sdap_dom_resolver_enum_state); - subreq = sdap_id_op_connect_send(op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: %d\n", ret); - return ret; - } - - tevent_req_set_callback(subreq, tcb, req); - return EOK; -} - -static bool sdap_dom_resolver_enum_connected(struct tevent_req *subreq) -{ - errno_t ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_dom_resolver_enum_state *state = tevent_req_data(req, - struct sdap_dom_resolver_enum_state); - - ret = sdap_id_op_connect_recv(subreq); - talloc_zfree(subreq); - - if (ret != EOK) { - if (be_is_offline(state->id_ctx->be)) { - DEBUG(SSSDBG_TRACE_FUNC, - "Backend is marked offline, retry later!\n"); - tevent_req_done(req); - } else { - DEBUG(SSSDBG_MINOR_FAILURE, - "Domain enumeration failed to connect to " \ - "LDAP server: (%d)[%s]\n", ret, strerror(ret)); - tevent_req_error(req, ret); - } - return false; - } - - return true; -} - static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, @@ -154,13 +91,19 @@ static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq) state = tevent_req_data(req, struct sdap_dom_resolver_enum_state); - if (sdap_dom_resolver_enum_connected(subreq) == false) { + state->iphost_conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->iphost_conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = enum_iphosts_send(state, state->ev, state->id_ctx, - state->iphost_op, + state->iphost_conn, state->purge); if (subreq == NULL) { tevent_req_error(req, ENOMEM); @@ -182,34 +125,19 @@ static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq) ret = enum_iphosts_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->iphost_op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_dom_resolver_enum_retry(req, state->iphost_op, - sdap_dom_resolver_enum_get_iphost); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + if (ret == ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); + tevent_req_done(req); return; } else if (ret != EOK && ret != ENOENT) { - /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "IP hosts enumeration failed: %d: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } - state->ipnetwork_op = sdap_id_op_create(state, state->conn->conn_cache); - if (state->ipnetwork_op == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_id_op_create failed for IP networks\n"); - tevent_req_error(req, EIO); - return; - } - - ret = sdap_dom_resolver_enum_retry(req, state->ipnetwork_op, - sdap_dom_resolver_enum_get_ipnetwork); + ret = sss_failover_transaction_send(state, state->ev, state->id_ctx->fctx, req, + sdap_dom_resolver_enum_get_ipnetwork); if (ret != EOK) { tevent_req_error(req, ret); return; @@ -226,13 +154,19 @@ static void sdap_dom_resolver_enum_get_ipnetwork(struct tevent_req *subreq) state = tevent_req_data(req, struct sdap_dom_resolver_enum_state); - if (sdap_dom_resolver_enum_connected(subreq) == false) { + state->ipnetwork_conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->ipnetwork_conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = enum_ipnetworks_send(state, state->ev, state->id_ctx, - state->ipnetwork_op, + state->ipnetwork_conn, state->purge); if (subreq == NULL) { tevent_req_error(req, ENOMEM); @@ -254,22 +188,14 @@ static void sdap_dom_resolver_enum_ipnetwork_done(struct tevent_req *subreq) ret = enum_ipnetworks_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->ipnetwork_op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_dom_resolver_enum_retry(req, state->ipnetwork_op, - sdap_dom_resolver_enum_get_ipnetwork); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + if (ret == ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n"); + tevent_req_done(req); return; } else if (ret != EOK && ret != ENOENT) { - /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, - "IP networks enumeration failed: %d: %s\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); + "IP networks enumeration failed: %d: %s\n", ret, sss_strerror(ret)); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } diff --git a/src/providers/ldap/sdap_async_resolver_enum.h b/src/providers/ldap/sdap_async_resolver_enum.h index e096b7483fd..45496b1f9cc 100644 --- a/src/providers/ldap/sdap_async_resolver_enum.h +++ b/src/providers/ldap/sdap_async_resolver_enum.h @@ -28,8 +28,7 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_resolver_ctx *resolver_ctx, struct sdap_id_ctx *id_ctx, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn); + struct sdap_domain *sdom); errno_t sdap_dom_resolver_enum_recv(struct tevent_req *req); diff --git a/src/providers/ldap/sdap_async_services.c b/src/providers/ldap/sdap_async_services.c index 5fa3bcad565..687b59e93bc 100644 --- a/src/providers/ldap/sdap_async_services.c +++ b/src/providers/ldap/sdap_async_services.c @@ -511,7 +511,7 @@ sdap_get_services_recv(TALLOC_CTX *mem_ctx, struct enum_services_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; struct sss_domain_info *domain; struct sysdb_ctx *sysdb; @@ -526,7 +526,7 @@ struct tevent_req * enum_services_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, bool purge) { errno_t ret; @@ -541,9 +541,9 @@ enum_services_send(TALLOC_CTX *memctx, state->id_ctx = id_ctx; state->domain = id_ctx->be->domain; state->sysdb = id_ctx->be->domain->sysdb; - state->op = op; + state->conn = conn; - if (id_ctx->srv_opts && id_ctx->srv_opts->max_service_value && !purge) { + if (state->conn->srv_opts && state->conn->srv_opts->max_service_value && !purge) { state->filter = talloc_asprintf( state, "(&(objectclass=%s)(%s=*)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))", @@ -552,9 +552,9 @@ enum_services_send(TALLOC_CTX *memctx, id_ctx->opts->service_map[SDAP_AT_SERVICE_PORT].name, id_ctx->opts->service_map[SDAP_AT_SERVICE_PROTOCOL].name, id_ctx->opts->service_map[SDAP_AT_SERVICE_USN].name, - id_ctx->srv_opts->max_service_value, + state->conn->srv_opts->max_service_value, id_ctx->opts->service_map[SDAP_AT_SERVICE_USN].name, - id_ctx->srv_opts->max_service_value); + state->conn->srv_opts->max_service_value); } else { state->filter = talloc_asprintf( state, @@ -579,7 +579,7 @@ enum_services_send(TALLOC_CTX *memctx, state->domain, state->sysdb, state->id_ctx->opts, state->id_ctx->opts->sdom->service_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -618,19 +618,19 @@ enum_services_op_done(struct tevent_req *subreq) } if (usn_value) { - talloc_zfree(state->id_ctx->srv_opts->max_service_value); - state->id_ctx->srv_opts->max_service_value = + talloc_zfree(state->conn->srv_opts->max_service_value); + state->conn->srv_opts->max_service_value = talloc_steal(state->id_ctx, usn_value); errno = 0; usn_number = strtoul(usn_value, &endptr, 10); if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value) - && (usn_number > state->id_ctx->srv_opts->last_usn)) { - state->id_ctx->srv_opts->last_usn = usn_number; + && (usn_number > state->conn->srv_opts->last_usn)) { + state->conn->srv_opts->last_usn = usn_number; } } DEBUG(SSSDBG_FUNC_DATA, "Services higher USN value: [%s]\n", - state->id_ctx->srv_opts->max_service_value); + state->conn->srv_opts->max_service_value); tevent_req_done(req); } diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c index 0a9be2f9ce2..3e2592a93dc 100644 --- a/src/providers/ldap/sdap_async_sudo.c +++ b/src/providers/ldap/sdap_async_sudo.c @@ -33,6 +33,9 @@ #include "providers/ldap/sdap_sudo.h" #include "providers/ldap/sdap_sudo_shared.h" #include "db/sysdb_sudo.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/failover.h" struct sdap_sudo_load_sudoers_state { struct sysdb_attrs **rules; @@ -281,7 +284,7 @@ struct sdap_sudo_refresh_state { struct sdap_sudo_ctx *sudo_ctx; struct tevent_context *ev; struct sdap_options *opts; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -292,7 +295,6 @@ struct sdap_sudo_refresh_state { size_t num_rules; }; -static errno_t sdap_sudo_refresh_retry(struct tevent_req *req); static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq); static void sdap_sudo_refresh_hostinfo_done(struct tevent_req *subreq); static errno_t sdap_sudo_refresh_sudoers(struct tevent_req *req); @@ -327,13 +329,6 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, state->sysdb = id_ctx->be->domain->sysdb; state->update_usn = update_usn; - state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto immediately; - } - state->search_filter = talloc_strdup(state, search_filter); if (state->search_filter == NULL) { ret = ENOMEM; @@ -346,11 +341,9 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, goto immediately; } - ret = sdap_sudo_refresh_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } + ret = sss_failover_transaction_send(state, state->ev, id_ctx->fctx, req, + sdap_sudo_refresh_connect_done); + return req; immediately: if (ret == EOK) { @@ -363,26 +356,6 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t sdap_sudo_refresh_retry(struct tevent_req *req) -{ - struct sdap_sudo_refresh_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct sdap_sudo_refresh_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: " - "%d(%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, sdap_sudo_refresh_connect_done, req); - - return EAGAIN; -} - static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) { struct tevent_req *req; @@ -392,13 +365,13 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed " - "[%d]: %s\n", ret, strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -473,7 +446,7 @@ static errno_t sdap_sudo_refresh_sudoers(struct tevent_req *req) subreq = sdap_sudo_load_sudoers_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, filter); if (subreq == NULL) { talloc_free(filter); @@ -587,17 +560,9 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - /* retry */ - ret = sdap_sudo_refresh_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { - tevent_req_error(req, ret); - return; + ret = ERR_SERVER_FAILURE; + goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Received %zu rules\n", rules_count); @@ -643,7 +608,7 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) /* remember new usn */ ret = sysdb_get_highest_usn(state, rules, rules_count, &usn); if (ret == EOK) { - sdap_sudo_set_usn(state->sudo_ctx->id_ctx->srv_opts, usn); + sdap_sudo_set_usn(state->conn->srv_opts, usn); } else { DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get highest USN [%d]: %s\n", ret, sss_strerror(ret)); diff --git a/src/providers/ldap/sdap_async_sudo_hostinfo.c b/src/providers/ldap/sdap_async_sudo_hostinfo.c index a3c3e10680a..109f84c7a67 100644 --- a/src/providers/ldap/sdap_async_sudo_hostinfo.c +++ b/src/providers/ldap/sdap_async_sudo_hostinfo.c @@ -31,7 +31,6 @@ #include "util/util.h" #include "providers/ldap/sdap.h" -#include "providers/ldap/sdap_id_op.h" #include "providers/ldap/sdap_sudo.h" #include "resolv/async_resolv.h" diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c index 463309d9ac2..f33457490d0 100644 --- a/src/providers/ldap/sdap_autofs.c +++ b/src/providers/ldap/sdap_autofs.c @@ -58,12 +58,10 @@ sdap_autofs_invalidate_maps(struct sdap_id_ctx *id_ctx, struct sdap_autofs_enumerate_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; const char *map_name; }; -static errno_t -sdap_autofs_enumerate_retry(struct tevent_req *req); static void sdap_autofs_enumerate_connect_done(struct tevent_req *subreq); static void @@ -86,14 +84,8 @@ sdap_autofs_enumerate_send(TALLOC_CTX *mem_ctx, state->ctx = ctx; state->map_name = map_name; - state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - - ret = sdap_autofs_enumerate_retry(req); + ret = sss_failover_transaction_send(state, ev, ctx->fctx, req, + sdap_autofs_enumerate_connect_done); if (ret != EOK) { goto fail; } @@ -106,23 +98,6 @@ sdap_autofs_enumerate_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t -sdap_autofs_enumerate_retry(struct tevent_req *req) -{ - struct sdap_autofs_enumerate_state *state = - tevent_req_data(req, struct sdap_autofs_enumerate_state); - struct tevent_req *subreq; - int ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, sdap_autofs_enumerate_connect_done, req); - return EOK; -} - static void sdap_autofs_enumerate_connect_done(struct tevent_req *subreq) { @@ -130,21 +105,21 @@ sdap_autofs_enumerate_connect_done(struct tevent_req *subreq) struct tevent_req); struct sdap_autofs_enumerate_state *state = tevent_req_data(req, struct sdap_autofs_enumerate_state); - int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_autofs_setautomntent_send(state, state->ev, state->ctx->be->domain, state->ctx->be->domain->sysdb, - sdap_id_op_handle(state->op), - state->op, + state->conn->sh, state->ctx->opts, state->map_name); if (!subreq) { @@ -169,22 +144,6 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq) ret = sdap_autofs_setautomntent_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_autofs_enumerate_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - return; - } - - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - if (ret == ENOENT) { ret = sysdb_delete_autofsmap(state->ctx->be->domain, state->map_name); if (ret != EOK && ret != ENOENT) { diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h index f89890caea4..ec6bc139982 100644 --- a/src/providers/ldap/sdap_autofs.h +++ b/src/providers/ldap/sdap_autofs.h @@ -36,7 +36,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, struct sss_domain_info *dom, struct sysdb_ctx *sysdb, struct sdap_handle *sh, - struct sdap_id_op *op, struct sdap_options *opts, const char *mapname); diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 2491552a0ca..f04906be96b 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -30,7 +30,6 @@ #include "providers/be_dyndns.h" #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/sdap_dyndns.h" -#include "providers/ldap/sdap_id_op.h" #include "providers/ldap/ldap_common.h" static struct tevent_req * @@ -522,6 +521,7 @@ sdap_dyndns_update_recv(struct tevent_req *req) /* A request to get addresses to update with */ struct sdap_dyndns_get_addrs_state { struct sdap_id_op* sdap_op; + struct sss_failover_ldap_connection *conn; struct sss_iface_addr *addresses; const char *network_filter; }; @@ -579,7 +579,6 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx, { errno_t ret; struct tevent_req *req; - struct tevent_req *subreq; struct sdap_dyndns_get_addrs_state *state; req = tevent_req_create(mem_ctx, &state, @@ -600,22 +599,10 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx, } /* Detect DYNDNS address from LDAP connection */ - state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache); - if (!state->sdap_op) { - ret = ENOMEM; - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - goto done; - } state->network_filter = network_filter; - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - ret = EIO; - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret)); - goto done; - } - tevent_req_set_callback(subreq, sdap_dyndns_get_addrs_done, req); + ret = sss_failover_transaction_send(state, ev, sdap_ctx->fctx, req, + sdap_dyndns_get_addrs_done); ret = EAGAIN; done: @@ -641,17 +628,17 @@ sdap_dyndns_get_addrs_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_dyndns_get_addrs_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to LDAP server: [%d](%s)\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - ret = sdap_dyndns_add_ldap_conn(state, sdap_id_op_handle(state->sdap_op)); + ret = sdap_dyndns_add_ldap_conn(state, state->conn->sh); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses from LDAP connection\n"); tevent_req_error(req, ret); diff --git a/src/providers/ldap/sdap_hostid.c b/src/providers/ldap/sdap_hostid.c index 8b9b3a9ed7a..cb8dd281c01 100644 --- a/src/providers/ldap/sdap_hostid.c +++ b/src/providers/ldap/sdap_hostid.c @@ -28,7 +28,7 @@ struct hosts_get_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; struct sss_domain_info *domain; const char *name; const char *alias; @@ -37,8 +37,6 @@ struct hosts_get_state { struct sysdb_attrs **hosts; }; -static errno_t -hosts_get_retry(struct tevent_req *req); static void hosts_get_connect_done(struct tevent_req *subreq); static void @@ -61,18 +59,12 @@ hosts_get_send(TALLOC_CTX *memctx, state->ev = ev; state->id_ctx = id_ctx; - state->op = sdap_id_op_create(state, id_ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - state->domain = id_ctx->be->domain; state->name = name; state->alias = alias; - ret = hosts_get_retry(req); + ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req, + hosts_get_connect_done); if (ret != EOK) { goto fail; } @@ -85,23 +77,6 @@ hosts_get_send(TALLOC_CTX *memctx, return req; } -static errno_t -hosts_get_retry(struct tevent_req *req) -{ - struct hosts_get_state *state = tevent_req_data(req, - struct hosts_get_state); - struct tevent_req *subreq; - errno_t ret = EOK; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, hosts_get_connect_done, req); - return EOK; -} - static void hosts_get_connect_done(struct tevent_req *subreq) { @@ -109,18 +84,18 @@ hosts_get_connect_done(struct tevent_req *subreq) struct tevent_req); struct hosts_get_state *state = tevent_req_data(req, struct hosts_get_state); - errno_t ret; - - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_host_info_send(state, state->ev, - sdap_id_op_handle(state->op), + state->conn->sh, state->id_ctx->opts, state->name, state->id_ctx->opts->host_map, state->id_ctx->opts->sdom->host_search_bases); @@ -146,17 +121,8 @@ hosts_get_done(struct tevent_req *subreq) &state->count, &state->hosts); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = hosts_get_retry(req); - if (ret != EOK) { - goto done; - } - return; - } - if (ret != EOK && ret != ENOENT) { + ret = ERR_SERVER_FAILURE; goto done; } diff --git a/src/providers/ldap/sdap_iphost.c b/src/providers/ldap/sdap_iphost.c index 348709ebc0f..6bfe78362fb 100644 --- a/src/providers/ldap/sdap_iphost.c +++ b/src/providers/ldap/sdap_iphost.c @@ -28,10 +28,9 @@ struct sdap_ip_host_get_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; uint32_t filter_type; const char *filter_value; @@ -42,15 +41,14 @@ struct sdap_ip_host_get_state { bool noexist_delete; }; -static errno_t -sdap_ip_host_get_retry(struct tevent_req *req); +static void +sdap_ip_host_get_connect_done(struct tevent_req *subreq); static struct tevent_req * sdap_iphost_get_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, uint32_t filter_type, const char *filter_value, bool noexist_delete) @@ -69,20 +67,12 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; state->filter_type = filter_type; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (state->op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - switch(filter_type) { case BE_FILTER_NAME: attr_name = id_ctx->opts->iphost_map[SDAP_AT_IPHOST_NAME].name; @@ -115,8 +105,8 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx, if (ret != EOK) { goto fail; } - - ret = sdap_ip_host_get_retry(req); + ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req, + sdap_ip_host_get_connect_done); if (ret != EOK) { goto fail; } @@ -129,27 +119,6 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx, return req; } -static void -sdap_ip_host_get_connect_done(struct tevent_req *subreq); - -static errno_t -sdap_ip_host_get_retry(struct tevent_req *req) -{ - struct sdap_ip_host_get_state *state; - struct tevent_req *subreq; - errno_t ret = EOK; - - state = tevent_req_data(req, struct sdap_ip_host_get_state); - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - return ret; - } - - tevent_req_set_callback(subreq, sdap_ip_host_get_connect_done, req); - - return EOK; -} static void sdap_ip_host_get_done(struct tevent_req *subreq); @@ -159,16 +128,17 @@ sdap_ip_host_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_ip_host_get_state *state; - errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ip_host_get_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -176,7 +146,7 @@ sdap_ip_host_get_connect_done(struct tevent_req *subreq) state->domain, state->sysdb, state->id_ctx->opts, state->sdom->iphost_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -202,24 +172,8 @@ sdap_ip_host_get_done(struct tevent_req *subreq) ret = sdap_get_iphost_recv(NULL, subreq, NULL); talloc_zfree(subreq); - /* Check whether we need to try again with another - * failover server. */ - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_ip_host_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* Return to the mainloop to retry */ - return; - } - - /* An error occurred. */ - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); return; } @@ -294,7 +248,6 @@ sdap_iphost_handler_send(TALLOC_CTX *mem_ctx, subreq = sdap_iphost_get_send(state, params->ev, resolver_ctx->id_ctx, resolver_ctx->id_ctx->opts->sdom, - resolver_ctx->id_ctx->conn, resolver_data->filter_type, resolver_data->filter_value, true); diff --git a/src/providers/ldap/sdap_ipnetwork.c b/src/providers/ldap/sdap_ipnetwork.c index 43fae2dba23..65524aa8660 100644 --- a/src/providers/ldap/sdap_ipnetwork.c +++ b/src/providers/ldap/sdap_ipnetwork.c @@ -28,10 +28,9 @@ struct sdap_ipnetwork_get_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; struct sdap_domain *sdom; - struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; uint32_t filter_type; const char *filter_value; @@ -42,15 +41,14 @@ struct sdap_ipnetwork_get_state { bool noexist_delete; }; -static errno_t -sdap_ipnetwork_get_retry(struct tevent_req *req); +static void +sdap_ipnetwork_get_connect_done(struct tevent_req *subreq); static struct tevent_req * sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, uint32_t filter_type, const char *filter_value, bool noexist_delete) @@ -69,20 +67,12 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; state->sdom = sdom; - state->conn = conn; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; state->filter_value = filter_value; state->filter_type = filter_type; state->noexist_delete = noexist_delete; - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (state->op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - switch(filter_type) { case BE_FILTER_NAME: attr_name = id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NAME].name; @@ -115,8 +105,8 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx, if (ret != EOK) { goto fail; } - - ret = sdap_ipnetwork_get_retry(req); + ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req, + sdap_ipnetwork_get_connect_done); if (ret != EOK) { goto fail; } @@ -129,28 +119,6 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx, return req; } -static void -sdap_ipnetwork_get_connect_done(struct tevent_req *subreq); - -static errno_t -sdap_ipnetwork_get_retry(struct tevent_req *req) -{ - struct sdap_ipnetwork_get_state *state; - struct tevent_req *subreq; - errno_t ret = EOK; - - state = tevent_req_data(req, struct sdap_ipnetwork_get_state); - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - return ret; - } - - tevent_req_set_callback(subreq, sdap_ipnetwork_get_connect_done, req); - - return EOK; -} - static void sdap_ipnetwork_get_done(struct tevent_req *subreq); @@ -159,16 +127,17 @@ sdap_ipnetwork_get_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_ipnetwork_get_state *state; - errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ipnetwork_get_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -176,7 +145,7 @@ sdap_ipnetwork_get_connect_done(struct tevent_req *subreq) state->domain, state->sysdb, state->id_ctx->opts, state->sdom->ipnetwork_search_bases, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), @@ -202,24 +171,8 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq) ret = sdap_get_ipnetwork_recv(NULL, subreq, NULL); talloc_zfree(subreq); - /* Check whether we need to try again with another - * failover server. */ - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - ret = sdap_ipnetwork_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* Return to the mainloop to retry */ - return; - } - - /* An error occurred. */ - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); return; } @@ -296,7 +249,6 @@ sdap_ipnetwork_handler_send(TALLOC_CTX *mem_ctx, subreq = sdap_ipnetwork_get_send(state, params->ev, resolver_ctx->id_ctx, resolver_ctx->id_ctx->opts->sdom, - resolver_ctx->id_ctx->conn, resolver_data->filter_type, resolver_data->filter_value, true); diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c index 562c8352459..1152c1b728b 100644 --- a/src/providers/ldap/sdap_refresh.c +++ b/src/providers/ldap/sdap_refresh.c @@ -130,7 +130,8 @@ static errno_t sdap_refresh_step(struct tevent_req *req) subreq = sdap_handle_acct_req_send(state, state->be_ctx, state->account_req, state->id_ctx, - state->sdom, state->id_ctx->conn, true); + state->id_ctx->fctx, + state->sdom, true); if (subreq == NULL) { ret = ENOMEM; goto done; diff --git a/src/providers/ldap/sdap_reinit.c b/src/providers/ldap/sdap_reinit.c index 1764ecd6ba5..10946965e45 100644 --- a/src/providers/ldap/sdap_reinit.c +++ b/src/providers/ldap/sdap_reinit.c @@ -80,7 +80,7 @@ struct tevent_req* sdap_reinit_cleanup_send(TALLOC_CTX *mem_ctx, } subreq = sdap_dom_enum_send(id_ctx, be_ctx->ev, id_ctx, - id_ctx->opts->sdom, id_ctx->conn); + id_ctx->opts->sdom); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to issue enumeration request\n"); ret = ENOMEM; From da7790b18b470f24b5e2795714559bf2be587944 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 17 Mar 2026 15:24:43 -0400 Subject: [PATCH 21/39] ldap: Remove sdap_online_check.c This will be done differently inside the failover code --- Makefile.am | 1 - src/providers/ldap/ldap_init.c | 4 - src/providers/ldap/sdap.c | 24 -- src/providers/ldap/sdap.h | 2 - src/providers/ldap/sdap_online_check.c | 291 ------------------------- 5 files changed, 322 deletions(-) delete mode 100644 src/providers/ldap/sdap_online_check.c diff --git a/Makefile.am b/Makefile.am index 48e5f89b55d..9a26c6434c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4407,7 +4407,6 @@ libsss_ldap_common_la_SOURCES = \ src/providers/ldap/sdap_async_services.c \ src/providers/ldap/sdap_async_iphost.c \ src/providers/ldap/sdap_async_ipnetwork.c \ - src/providers/ldap/sdap_online_check.c \ src/providers/ldap/sdap_ad_groups.c \ src/providers/ldap/sdap_child_helpers.c \ src/providers/ldap/sdap_fd_events.c \ diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index 3d3b504bfe5..95441a5f15e 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -408,10 +408,6 @@ errno_t sssm_ldap_id_init(TALLOC_CTX *mem_ctx, sdap_account_info_handler_send, sdap_account_info_handler_recv, id_ctx, struct sdap_id_ctx, struct dp_id_data, struct dp_reply_std); - dp_set_method(dp_methods, DPM_CHECK_ONLINE, - sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx, - struct sdap_id_ctx, void, struct dp_reply_std); - dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, default_account_domain_send, default_account_domain_recv, NULL, void, struct dp_get_acct_domain_data, struct dp_reply_std); diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index 5c63f8f46ef..f0731157c1b 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -1565,30 +1565,6 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, return EOK; } -void sdap_steal_server_opts(struct sdap_id_ctx *id_ctx, - struct sdap_server_opts **srv_opts) -{ - if (!id_ctx || !srv_opts || !*srv_opts) { - return; - } - - if (!id_ctx->srv_opts) { - id_ctx->srv_opts = talloc_move(id_ctx, srv_opts); - return; - } - - /* discard if same as previous so we do not reset max usn values - * unnecessarily, only update last_usn. */ - if (strcmp(id_ctx->srv_opts->server_id, (*srv_opts)->server_id) == 0) { - id_ctx->srv_opts->last_usn = (*srv_opts)->last_usn; - talloc_zfree(*srv_opts); - return; - } - - talloc_zfree(id_ctx->srv_opts); - id_ctx->srv_opts = talloc_move(id_ctx, srv_opts); -} - static bool attr_is_filtered(const char *attr, const char **filter) { int i; diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 35c23c2e132..b4593d8cb7e 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -747,8 +747,6 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, struct sysdb_attrs *rootdse, struct sdap_options *opts, struct sdap_server_opts **srv_opts); -void sdap_steal_server_opts(struct sdap_id_ctx *id_ctx, - struct sdap_server_opts **srv_opts); char *sdap_make_oc_list(TALLOC_CTX *mem_ctx, struct sdap_attr_map *map); diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c deleted file mode 100644 index f70e6a2423f..00000000000 --- a/src/providers/ldap/sdap_online_check.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - Authors: - Pavel Březina - - Copyright (C) 2016 Red Hat - - 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 . -*/ - -#include -#include -#include -#include "util/util.h" -#include "providers/backend.h" -#include "providers/ldap/sdap_async.h" -#include "providers/ldap/ldap_common.h" - -struct sdap_online_check_state { - struct sdap_id_ctx *id_ctx; - struct be_ctx *be_ctx; -}; - -static void sdap_online_check_connect_done(struct tevent_req *subreq); -static void sdap_online_check_reinit_done(struct tevent_req *subreq); - -static struct tevent_req *sdap_online_check_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx) -{ - struct sdap_online_check_state *state; - struct tevent_req *subreq; - struct tevent_req *req; - struct be_ctx *be_ctx; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, struct sdap_online_check_state); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); - return NULL; - } - - state->id_ctx = id_ctx; - state->be_ctx = be_ctx = id_ctx->be; - - subreq = sdap_cli_resolve_and_connect_send(state, be_ctx->ev, id_ctx->opts, - be_ctx, id_ctx->conn->service, - false, CON_TLS_DFL, false); - if (subreq == NULL) { - ret = ENOMEM; - tevent_req_error(req, ret); - tevent_req_post(req, be_ctx->ev); - } else { - tevent_req_set_callback(subreq, sdap_online_check_connect_done, req); - } - - return req; -} - -static void sdap_online_check_connect_done(struct tevent_req *subreq) -{ - struct sdap_online_check_state *state; - struct sdap_server_opts *srv_opts; - struct sdap_id_ctx *id_ctx; - struct tevent_req *req; - bool can_retry; - bool reinit = false; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_online_check_state); - - id_ctx = state->id_ctx; - - ret = sdap_cli_resolve_and_connect_recv(subreq, state, &can_retry, NULL, - &srv_opts); - talloc_zfree(subreq); - if (ret != EOK) { - if (can_retry == false) { - ret = ERR_OFFLINE; - } - - goto done; - } else { - if (id_ctx->srv_opts == NULL) { - srv_opts->max_user_value = 0; - srv_opts->max_group_value = 0; - srv_opts->max_service_value = 0; - srv_opts->max_sudo_value = 0; - srv_opts->max_iphost_value = 0; - srv_opts->max_ipnetwork_value = 0; - } else if (strcmp(srv_opts->server_id, id_ctx->srv_opts->server_id) == 0 - && srv_opts->supports_usn - && id_ctx->srv_opts->last_usn > srv_opts->last_usn) { - id_ctx->srv_opts->max_user_value = 0; - id_ctx->srv_opts->max_group_value = 0; - id_ctx->srv_opts->max_service_value = 0; - id_ctx->srv_opts->max_sudo_value = 0; - id_ctx->srv_opts->max_iphost_value = 0; - id_ctx->srv_opts->max_ipnetwork_value = 0; - id_ctx->srv_opts->last_usn = srv_opts->last_usn; - - reinit = true; - } - - sdap_steal_server_opts(id_ctx, &srv_opts); - } - - if (reinit) { - DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. " - "Cleaning cache.\n"); - subreq = sdap_reinit_cleanup_send(state, state->be_ctx, id_ctx); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization " - "clean up.\n"); - /* not fatal */ - goto done; - } - - tevent_req_set_callback(subreq, sdap_online_check_reinit_done, req); - return; - } - - ret = EOK; - -done: - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static void sdap_online_check_reinit_done(struct tevent_req *subreq) -{ - struct tevent_req *req; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - - ret = sdap_reinit_cleanup_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization " - "clean up [%d]: %s\n", ret, strerror(ret)); - /* not fatal */ - } else { - DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n"); - } - - tevent_req_done(req); -} - -static errno_t sdap_online_check_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -struct sdap_online_check_handler_state { - struct dp_reply_std reply; - struct sdap_id_ctx *id_ctx; -}; - -static void sdap_online_check_handler_done(struct tevent_req *subreq); -static void sdap_online_check_subdomains_done(struct tevent_req *subreq); - -struct tevent_req * -sdap_online_check_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, - void *data, - struct dp_req_params *params) -{ - struct sdap_online_check_handler_state *state; - struct tevent_req *subreq; - struct tevent_req *req; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, - struct sdap_online_check_handler_state); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); - return NULL; - } - - state->id_ctx = id_ctx; - - subreq = sdap_online_check_send(state, id_ctx); - if (subreq == NULL) { - ret = ENOMEM; - goto immediately; - } - - tevent_req_set_callback(subreq, sdap_online_check_handler_done, req); - - return req; - -immediately: - dp_reply_std_set(&state->reply, ret, NULL); - - /* TODO For backward compatibility we always return EOK to DP now. */ - tevent_req_done(req); - tevent_req_post(req, params->ev); - - return req; -} - -static void sdap_online_check_handler_done(struct tevent_req *subreq) -{ - struct sdap_online_check_handler_state *state; - struct tevent_req *req; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_online_check_handler_state); - - ret = sdap_online_check_recv(subreq); - talloc_zfree(subreq); - - if (ret == EOK) { - /* Run a subdomains request, if configured, to refresh the list of - * known sub-domains and other domain-wide configuration data read by - * the configured subdomains provider. */ - subreq = dp_req_send(state->id_ctx->be, state->id_ctx->be->provider, - NULL, "Subdomains Check", 0, NULL, DPT_SUBDOMAINS, - DPM_DOMAINS_HANDLER, 0, NULL , NULL); - if (subreq != NULL) { - tevent_req_set_callback(subreq, sdap_online_check_subdomains_done, req); - return; - } - } - - /* TODO For backward compatibility we always return EOK to DP now. */ - dp_reply_std_set(&state->reply, ret, NULL); - tevent_req_done(req); -} - -static void sdap_online_check_subdomains_done(struct tevent_req *subreq) -{ - struct sdap_online_check_handler_state *state; - struct tevent_req *req; - struct dp_reply_std *reply; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_online_check_handler_state); - - ret = dp_req_recv_ptr(state, subreq, struct dp_reply_std, &reply); - talloc_zfree(subreq); - - if (ret != EOK) { - if (ret == ERR_MISSING_DP_TARGET) { - DEBUG(SSSDBG_TRACE_FUNC, - "Subdomains target not configured, ignored.\n"); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Subdomain online check failed, ignored.\n"); - } - } - - /* We return the EOK of the initial online check here, the result of the - * subdomains request is not important for the online-check request. */ - dp_reply_std_set(&state->reply, EOK, NULL); - tevent_req_done(req); -} - -errno_t sdap_online_check_handler_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct dp_reply_std *data) -{ - struct sdap_online_check_handler_state *state = NULL; - - state = tevent_req_data(req, struct sdap_online_check_handler_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *data = state->reply; - - return EOK; -} From e53b7b9e5f2b9bc4e33ab34f8e4cead88615bb37 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Thu, 21 May 2026 11:31:00 -0400 Subject: [PATCH 22/39] ldap: Remove sdap_service related code --- src/providers/ldap/ldap_auth.c | 7 - src/providers/ldap/ldap_common.c | 387 ------------------------------- src/providers/ldap/ldap_common.h | 31 --- src/providers/ldap/ldap_init.c | 107 --------- 4 files changed, 532 deletions(-) diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index 81102481996..f1a425fbaaf 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -672,7 +672,6 @@ struct auth_state { struct sdap_auth_ctx *ctx; const char *username; struct sss_auth_token *authtok; - struct sdap_service *sdap_service; struct sss_failover_ldap_connection *conn; @@ -718,12 +717,6 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx, state->ctx = ctx; state->username = username; state->authtok = authtok; - if (try_chpass_service && ctx->chpass_service != NULL && - ctx->chpass_service->name != NULL) { - state->sdap_service = ctx->chpass_service; - } else { - state->sdap_service = ctx->service; - } ret = get_user_dn(state, state->ctx->be->domain, SDAP_TYPE_LDAP, state->ctx->opts, state->username, &state->dn, diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 29c9305a161..f7b611888a0 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -69,86 +69,6 @@ errno_t sdap_id_setup_tasks(struct be_ctx *be_ctx, return ret; } -static void sdap_uri_callback(void *private_data, struct fo_server *server) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct sdap_service *service; - struct resolv_hostent *srvaddr; - struct sockaddr *sockaddr; - const char *tmp; - const char *srv_name; - char *new_uri; - socklen_t sockaddr_len; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n"); - return; - } - - service = talloc_get_type(private_data, struct sdap_service); - if (!service) { - talloc_free(tmp_ctx); - return; - } - - tmp = (const char *)fo_get_server_user_data(server); - - srvaddr = fo_get_server_hostent(server); - if (!srvaddr) { - DEBUG(SSSDBG_CRIT_FAILURE, - "FATAL: No hostent available for server (%s)\n", - fo_get_server_str_name(server)); - talloc_free(tmp_ctx); - return; - } - - sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, - fo_get_server_port(server), - &sockaddr_len); - if (sockaddr == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n"); - talloc_free(tmp_ctx); - return; - } - - if (fo_is_srv_lookup(server)) { - if (!tmp) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unknown service, using ldap\n"); - tmp = SSS_LDAP_SRV_NAME; - } - - srv_name = fo_get_server_name(server); - if (srv_name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n"); - talloc_free(tmp_ctx); - return; - } - - new_uri = talloc_asprintf(service, "%s://%s:%d", - tmp, srv_name, - fo_get_server_port(server)); - } else { - new_uri = talloc_strdup(service, tmp); - } - - if (!new_uri) { - DEBUG(SSSDBG_OP_FAILURE, "Failed to copy URI ...\n"); - talloc_free(tmp_ctx); - return; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Constructed uri '%s'\n", new_uri); - - /* free old one and replace with new one */ - talloc_zfree(service->uri); - service->uri = new_uri; - talloc_zfree(service->sockaddr); - service->sockaddr = talloc_steal(service, sockaddr); - service->sockaddr_len = sockaddr_len; - talloc_free(tmp_ctx); -} - errno_t sdap_select_principal_from_keytab_sync(TALLOC_CTX *mem_ctx, const char *princ_str, const char *realm_str, @@ -244,42 +164,6 @@ sdap_set_sasl_options(struct sdap_options *id_opts, return ret; } -static const char * -sdap_gssapi_get_default_realm(TALLOC_CTX *mem_ctx) -{ - char *krb5_realm = NULL; - const char *realm = NULL; - krb5_error_code krberr; - krb5_context context = NULL; - - krberr = sss_krb5_init_context(&context); - if (krberr) { - DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n"); - goto done; - } - - krberr = krb5_get_default_realm(context, &krb5_realm); - if (krberr) { - const char *__err_msg = sss_krb5_get_error_message(context, krberr); - DEBUG(SSSDBG_OP_FAILURE, "Failed to get default realm name: %s\n", - __err_msg); - sss_krb5_free_error_message(context, __err_msg); - goto done; - } - - realm = talloc_strdup(mem_ctx, krb5_realm); - krb5_free_default_realm(context, krb5_realm); - if (!realm) { - DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory\n"); - goto done; - } - - DEBUG(SSSDBG_TRACE_LIBS, "Will use default realm %s\n", realm); -done: - if (context) krb5_free_context(context); - return realm; -} - const char *sdap_gssapi_realm(struct dp_option *opts) { const char *realm; @@ -292,207 +176,6 @@ const char *sdap_gssapi_realm(struct dp_option *opts) return realm; } -int sdap_gssapi_init(TALLOC_CTX *mem_ctx, - struct dp_option *opts, - struct be_ctx *bectx, - struct sdap_service *sdap_service, - struct krb5_service **krb5_service) -{ - int ret; - const char *krb5_servers; - const char *krb5_backup_servers; - const char *krb5_realm; - const char *krb5_opt_realm; - struct krb5_service *service = NULL; - TALLOC_CTX *tmp_ctx; - size_t n_lookahead_primary; - size_t n_lookahead_backup; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) return ENOMEM; - - krb5_servers = dp_opt_get_string(opts, SDAP_KRB5_KDC); - krb5_backup_servers = dp_opt_get_string(opts, SDAP_KRB5_BACKUP_KDC); - - krb5_opt_realm = sdap_gssapi_realm(opts); - if (krb5_opt_realm == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "Missing krb5_realm option, will use libkrb default\n"); - krb5_realm = sdap_gssapi_get_default_realm(tmp_ctx); - if (krb5_realm == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Cannot determine the Kerberos realm, aborting\n"); - ret = EIO; - goto done; - } - } else { - krb5_realm = talloc_strdup(tmp_ctx, krb5_opt_realm); - if (krb5_realm == NULL) { - ret = ENOMEM; - goto done; - } - } - - sss_krb5_parse_lookahead( - dp_opt_get_string(opts, SDAP_KRB5_KDCINFO_LOOKAHEAD), - &n_lookahead_primary, - &n_lookahead_backup); - - ret = krb5_service_init(mem_ctx, bectx, - SSS_KRB5KDC_FO_SRV, krb5_servers, - krb5_backup_servers, krb5_realm, - dp_opt_get_bool(opts, - SDAP_KRB5_USE_KDCINFO), - n_lookahead_primary, - n_lookahead_backup, - &service); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n"); - goto done; - } - - sdap_service->kinit_service_name = talloc_strdup(sdap_service, - service->name); - if (sdap_service->kinit_service_name == NULL) { - ret = ENOMEM; - goto done; - } - - ret = EOK; - *krb5_service = service; -done: - talloc_free(tmp_ctx); - if (ret != EOK) talloc_free(service); - return ret; -} - -static errno_t _sdap_urls_init(struct be_ctx *ctx, - struct sdap_service *service, - const char *service_name, - const char *dns_service_name, - const char *urls, - bool primary) -{ - TALLOC_CTX *tmp_ctx; - char *srv_user_data; - char **list = NULL; - LDAPURLDesc *lud; - errno_t ret = 0; - int i; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - - /* split server parm into a list */ - ret = split_on_separator(tmp_ctx, urls, ',', true, true, &list, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n"); - goto done; - } - - /* now for each URI add a new server to the failover service */ - for (i = 0; list[i]; i++) { - if (be_fo_is_srv_identifier(list[i])) { - if (!primary) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to add server [%s] to failover service: " - "SRV resolution only allowed for primary servers!\n", - list[i]); - continue; - } - - if (!dns_service_name) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Missing DNS service name for service [%s].\n", - service_name); - ret = EINVAL; - goto done; - } - srv_user_data = talloc_strdup(service, dns_service_name); - if (!srv_user_data) { - ret = ENOMEM; - goto done; - } - - ret = be_fo_add_srv_server(ctx, service_name, - dns_service_name, NULL, - BE_FO_PROTO_TCP, false, srv_user_data); - if (ret) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n"); - goto done; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Added service lookup\n"); - continue; - } - - ret = ldap_url_parse(list[i], &lud); - if (ret != LDAP_SUCCESS) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Failed to parse ldap URI (%s)!\n", list[i]); - ret = EINVAL; - goto done; - } - - if (lud->lud_host == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "The LDAP URI (%s) did not contain a host name\n", - list[i]); - ldap_free_urldesc(lud); - continue; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Added URI %s\n", list[i]); - - talloc_steal(service, list[i]); - - /* It could be ipv6 address in square brackets. Remove - * the brackets if needed. */ - ret = remove_ipv6_brackets(lud->lud_host); - if (ret != EOK) { - goto done; - } - - ret = be_fo_add_server(ctx, service->name, lud->lud_host, - lud->lud_port, list[i], primary); - ldap_free_urldesc(lud); - if (ret) { - goto done; - } - } - -done: - talloc_free(tmp_ctx); - return ret; -} - - -static inline errno_t -sdap_primary_urls_init(struct be_ctx *ctx, struct sdap_service *service, - const char *service_name, const char *dns_service_name, - const char *urls) -{ - return _sdap_urls_init(ctx, service, service_name, - dns_service_name, urls, true); -} - -static inline errno_t -sdap_backup_urls_init(struct be_ctx *ctx, struct sdap_service *service, - const char *service_name, const char *dns_service_name, - const char *urls) -{ - return _sdap_urls_init(ctx, service, service_name, - dns_service_name, urls, false); -} - -static int ldap_user_data_cmp(void *ud1, void *ud2) -{ - return strcasecmp((char*) ud1, (char*) ud2); -} - void sdap_service_reset_fo(struct be_ctx *ctx, struct sdap_service *service) { @@ -504,75 +187,6 @@ void sdap_service_reset_fo(struct be_ctx *ctx, be_fo_reset_svc(ctx, service->name); } -int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, - const char *service_name, const char *dns_service_name, - const char *urls, const char *backup_urls, - struct sdap_service **_service) -{ - TALLOC_CTX *tmp_ctx; - struct sdap_service *service; - int ret; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - service = talloc_zero(tmp_ctx, struct sdap_service); - if (!service) { - ret = ENOMEM; - goto done; - } - - ret = be_fo_add_service(ctx, service_name, ldap_user_data_cmp); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n"); - goto done; - } - - service->name = talloc_strdup(service, service_name); - if (!service->name) { - ret = ENOMEM; - goto done; - } - - if (!urls) { - DEBUG(SSSDBG_CONF_SETTINGS, - "No primary servers defined, using service discovery\n"); - urls = BE_SRV_IDENTIFIER; - } - - ret = sdap_primary_urls_init(ctx, service, service_name, dns_service_name, - urls); - if (ret != EOK) { - goto done; - } - - if (backup_urls) { - ret = sdap_backup_urls_init(ctx, service, service_name, - dns_service_name, backup_urls); - if (ret != EOK) { - goto done; - } - } - - ret = be_fo_service_add_callback(memctx, ctx, service->name, - sdap_uri_callback, service); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add failover callback!\n"); - goto done; - } - - ret = EOK; - -done: - if (ret == EOK) { - *_service = talloc_steal(memctx, service); - } - talloc_zfree(tmp_ctx); - return ret; -} - errno_t string_to_shadowpw_days(const char *s, long *d) { long l; @@ -843,7 +457,6 @@ sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx, talloc_set_destructor(sdap_ctx, sdap_id_ctx_destructor); sdap_ctx->be = bectx; - sdap_ctx->service = sdap_service; return sdap_ctx; } diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 0c54d9cd06e..1277fc61403 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -53,18 +53,6 @@ enum ldap_child_command { struct sdap_id_ctx; -struct sdap_id_conn_ctx { - struct sdap_id_ctx *id_ctx; - - struct sdap_service *service; - /* dlinklist pointers */ - struct sdap_id_conn_ctx *prev, *next; - /* do not go offline, try another connection */ - bool ignore_mark_offline; - /* do not fall back to user lookups for mpg domains on this connection */ - bool no_mpg_user_fallback; -}; - struct sdap_id_ctx { struct be_ctx *be; struct sdap_options *opts; @@ -72,8 +60,6 @@ struct sdap_id_ctx { /* If using GSSAPI or GSS-SPNEGO */ struct krb5_service *krb5_service; - struct sdap_service *service; - struct sdap_server_opts *srv_opts; /* New failover context */ @@ -94,8 +80,6 @@ struct sdap_auth_ctx { struct be_ctx *be; struct sss_failover_ctx *fctx; struct sdap_options *opts; - struct sdap_service *service; - struct sdap_service *chpass_service; }; struct sdap_resolver_ctx { @@ -225,22 +209,11 @@ sdap_autofs_get_entry_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, dp_no_output *_no_output); -int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, - const char *service_name, const char *dns_service_name, - const char *urls, const char *backup_urls, - struct sdap_service **_service); - void sdap_service_reset_fo(struct be_ctx *ctx, struct sdap_service *service); const char *sdap_gssapi_realm(struct dp_option *opts); -int sdap_gssapi_init(TALLOC_CTX *mem_ctx, - struct dp_option *opts, - struct be_ctx *bectx, - struct sdap_service *sdap_service, - struct krb5_service **krb5_service); - errno_t sdap_install_offline_callback(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, const char *realm, @@ -461,10 +434,6 @@ sdap_set_sasl_options(struct sdap_options *id_opts, char *default_realm, const char *keytab_path); -struct sdap_id_conn_ctx * -sdap_id_ctx_conn_add(struct sdap_id_ctx *id_ctx, - struct sdap_service *sdap_service); - struct sdap_id_ctx * sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx, struct sdap_service *sdap_service); diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index 95441a5f15e..5e34cd4a9d7 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -54,92 +54,12 @@ static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx, auth_ctx->be = be_ctx; auth_ctx->fctx = fctx; auth_ctx->opts = options; - auth_ctx->service = id_ctx->service; - auth_ctx->chpass_service = NULL; *_auth_ctx = auth_ctx; return EOK; } -static errno_t init_chpass_service(TALLOC_CTX *mem_ctx, - struct be_ctx *be_ctx, - struct sdap_options *opts, - struct sdap_service **_chpass_service) -{ - errno_t ret; - const char *urls; - const char *backup_urls; - const char *dns_service_name; - struct sdap_service *chpass_service; - - dns_service_name = dp_opt_get_string(opts->basic, - SDAP_CHPASS_DNS_SERVICE_NAME); - if (dns_service_name != NULL) { - DEBUG(SSSDBG_TRACE_LIBS, - "Service name for chpass discovery set to %s\n", - dns_service_name); - } - - urls = dp_opt_get_string(opts->basic, SDAP_CHPASS_URI); - backup_urls = dp_opt_get_string(opts->basic, SDAP_CHPASS_BACKUP_URI); - - if (urls != NULL || backup_urls != NULL || dns_service_name != NULL) { - ret = sdap_service_init(mem_ctx, - be_ctx, - "LDAP_CHPASS", - dns_service_name, - urls, - backup_urls, - &chpass_service); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to initialize failover service!\n"); - return ret; - } - } else { - DEBUG(SSSDBG_TRACE_ALL, - "ldap_chpass_uri and ldap_chpass_dns_service_name not set, " - "using ldap_uri.\n"); - chpass_service = NULL; - } - - *_chpass_service = chpass_service; - return EOK; -} - -static errno_t get_sdap_service(TALLOC_CTX *mem_ctx, - struct be_ctx *be_ctx, - struct sdap_options *opts, - struct sdap_service **_sdap_service) -{ - errno_t ret; - const char *urls; - const char *backup_urls; - const char *dns_service_name; - struct sdap_service *sdap_service; - - urls = dp_opt_get_string(opts->basic, SDAP_URI); - backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI); - dns_service_name = dp_opt_get_string(opts->basic, SDAP_DNS_SERVICE_NAME); - if (dns_service_name != NULL) { - DEBUG(SSSDBG_CONF_SETTINGS, - "Service name for discovery set to %s\n", dns_service_name); - } - - ret = sdap_service_init(mem_ctx, be_ctx, "LDAP", - dns_service_name, - urls, - backup_urls, - &sdap_service); - if (ret != EOK) { - return ret; - } - - *_sdap_service = sdap_service; - return EOK; -} - static bool should_call_gssapi_init(struct sdap_options *opts) { const char *sasl_mech; @@ -166,17 +86,6 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, { errno_t ret; - if (should_call_gssapi_init(options)) { - ret = sdap_gssapi_init(id_ctx, options->basic, be_ctx, - id_ctx->service, &id_ctx->krb5_service); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_gssapi_init failed [%d][%s].\n", - ret, sss_strerror(ret)); - return ret; - } - } - setup_ldap_debug(options->basic); ret = setup_tls_config(options->basic); @@ -202,14 +111,6 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, return ret; } - /* Setup SRV lookup plugin */ - ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " - "[%d]: %s\n", ret, sss_strerror(ret)); - return ret; - } - /* Setup periodical refresh of expired records */ ret = sdap_refresh_init(be_ctx, id_ctx); if (ret != EOK && ret != EEXIST) { @@ -445,14 +346,6 @@ errno_t sssm_ldap_chpass_init(TALLOC_CTX *mem_ctx, init_ctx = talloc_get_type(module_data, struct ldap_init_ctx); auth_ctx = init_ctx->auth_ctx; - ret = init_chpass_service(auth_ctx, be_ctx, init_ctx->options, - &auth_ctx->chpass_service); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize chpass service " - "[%d]: %s\n", ret, sss_strerror(ret)); - return ret; - } - dp_set_method(dp_methods, DPM_AUTH_HANDLER, sdap_pam_chpass_handler_send, sdap_pam_chpass_handler_recv, auth_ctx, struct sdap_auth_ctx, struct pam_data, struct pam_data *); From c9bab1df136c0e63ccfd68a2008f9e2ccbef9299 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 18 Mar 2026 09:19:51 -0400 Subject: [PATCH 23/39] minimal: Disable building minimal provider To allow system tests to run in upstream PRCI --- Makefile.am | 30 ------------------------------ contrib/sssd.spec.in | 14 -------------- src/tests/dlopen-tests.c | 2 -- 3 files changed, 46 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9a26c6434c8..f66ddc3c5e5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -423,10 +423,6 @@ sssdlib_LTLIBRARIES += \ $(NULL) endif -sssdlib_LTLIBRARIES += \ - libsss_minimal.la \ - $(NULL) - ldblib_LTLIBRARIES = \ memberof.la @@ -944,10 +940,6 @@ dist_noinst_HEADERS = \ src/providers/idp/idp_id.h \ src/providers/idp/idp_opts.h \ src/providers/idp/idp_private.h \ - src/providers/minimal/minimal.h \ - src/providers/minimal/minimal_id.h \ - src/providers/minimal/minimal_id_services.h \ - src/providers/minimal/minimal_ldap_auth.h \ src/tools/tools_util.h \ src/resolv/async_resolv.h \ src/tests/common.h \ @@ -4773,28 +4765,6 @@ libsss_idp_la_LDFLAGS = \ -module \ $(NULL) -libsss_minimal_la_SOURCES = \ - src/providers/minimal/minimal_init.c \ - src/providers/minimal/minimal_id.c \ - src/providers/minimal/minimal_id_services.c \ - src/providers/minimal/minimal_ldap_auth.c \ - $(SSSD_NEW_FAILOVER_OBJ) \ - $(NULL) - -libsss_minimal_la_CFLAGS = \ - $(AM_CFLAGS) \ - $(NULL) - -libsss_minimal_la_LIBADD = \ - $(SSSD_INTERNAL_LTLIBS) \ - libsss_ldap_common.la \ - $(NULL) - -libsss_minimal_la_LDFLAGS = \ - -avoid-version \ - -module \ - $(NULL) - krb5_child_SOURCES = \ src/providers/krb5/krb5_child.c \ src/providers/krb5/krb5_child_share.c \ diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index 4e4c0088f30..a36182c58f8 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -50,7 +50,6 @@ Requires: sssd-common = %{version}-%{release} Requires: sssd-ipa = %{version}-%{release} Requires: sssd-krb5 = %{version}-%{release} Requires: sssd-ldap = %{version}-%{release} -Requires: sssd-minimal = %{version}-%{release} Requires: sssd-proxy = %{version}-%{release} Suggests: logrotate Suggests: procps-ng @@ -266,15 +265,6 @@ Requires: libsss_certmap = %{version}-%{release} Provides the LDAP back end that the SSSD can utilize to fetch identity data from and authenticate against an LDAP server. -%package minimal -Summary: The minimal back end of the SSSD -License: GPL-3.0-or-later -Requires: sssd-common = %{version}-%{release} - -%description minimal -Provides the minimal back end that the SSSD can utilize as a minimal -identity provider. - %package krb5-common Summary: SSSD helpers needed for Kerberos and GSSAPI authentication License: GPL-3.0-or-later @@ -795,10 +785,6 @@ install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/sssd.conf %{_mandir}/man5/sssd-ldap.5* %{_mandir}/man5/sssd-ldap-attributes.5* -%files minimal -%license COPYING -%{_libdir}/%{name}/libsss_minimal.so - %files krb5-common %license COPYING %attr(775,sssd,sssd) %dir %{pubconfpath}/krb5.include.d diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c index 878f8767fc4..ceaaedc5d5d 100644 --- a/src/tests/dlopen-tests.c +++ b/src/tests/dlopen-tests.c @@ -111,8 +111,6 @@ struct so { { "libsss_idp.so", { LIBPFX"libdlopen_test_providers.so", LIBPFX"libsss_idp.so", NULL } }, #endif /* BUILD_ID_PROVIDER_IDP */ - { "libsss_minimal.so", { LIBPFX"libdlopen_test_providers.so", - LIBPFX"libsss_minimal.so", NULL } }, #ifdef HAVE_PYTHON2_BINDINGS { "_py2hbac.so", { LIBPFX"_py2hbac.so", NULL } }, { "_py2sss.so", { LIBPFX"_py2sss.so", NULL } }, From 18b130f217f4441fdf287909f23ba1ba3ae0cff8 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 24 Mar 2026 12:55:04 -0400 Subject: [PATCH 24/39] ldap: Remove sdap_id_op.c/h files --- Makefile.am | 2 - src/providers/ldap/sdap_id_op.c | 1043 ------------------------------- src/providers/ldap/sdap_id_op.h | 76 --- 3 files changed, 1121 deletions(-) delete mode 100644 src/providers/ldap/sdap_id_op.c delete mode 100644 src/providers/ldap/sdap_id_op.h diff --git a/Makefile.am b/Makefile.am index f66ddc3c5e5..4546497a3c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -898,7 +898,6 @@ dist_noinst_HEADERS = \ src/providers/ldap/sdap_sudo.h \ src/providers/ldap/sdap_sudo_shared.h \ src/providers/ldap/sdap_autofs.h \ - src/providers/ldap/sdap_id_op.h \ src/providers/ldap/ldap_opts.h \ src/providers/ldap/ldap_auth.h \ src/providers/ldap/sdap_range.h \ @@ -4403,7 +4402,6 @@ libsss_ldap_common_la_SOURCES = \ src/providers/ldap/sdap_child_helpers.c \ src/providers/ldap/sdap_fd_events.c \ src/providers/ldap/sdap_hostid.h \ - src/providers/ldap/sdap_id_op.c \ src/providers/ldap/sdap_certmap.c \ src/providers/ldap/sdap_idmap.c \ src/providers/ldap/sdap_idmap.h \ diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c deleted file mode 100644 index ea2b548d053..00000000000 --- a/src/providers/ldap/sdap_id_op.c +++ /dev/null @@ -1,1043 +0,0 @@ -/* - SSSD - - LDAP ID backend operation retry logic and connection cache - - Authors: - Eugene Indenbom - - Copyright (C) 2008-2010 Red Hat - - 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 . -*/ - -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" -#include "providers/ldap/sdap_id_op.h" -#include "util/sss_chain_id.h" - -/* LDAP async connection cache */ -struct sdap_id_conn_cache { - struct sdap_id_conn_ctx *id_conn; - - /* list of all open connections */ - struct sdap_id_conn_data *connections; - /* cached (current) connection */ - struct sdap_id_conn_data *cached_connection; -}; - -/* LDAP async operation tracker: - * - keeps track of connection usage - * - keeps track of operation retries */ -struct sdap_id_op { - /* ID backend context */ - struct sdap_id_conn_cache *conn_cache; - /* double linked list pointers */ - struct sdap_id_op *prev, *next; - /* current connection */ - struct sdap_id_conn_data *conn_data; - /* number of reconnects for this operation */ - int reconnect_retry_count; - /* connection request - * It is required as we need to know which requests to notify - * when shared connection request to sdap_handle completes. - * This member is cleared when sdap_id_op_connect_state - * associated with request is destroyed */ - struct tevent_req *connect_req; - - /* chain id of the request that created this op */ - uint64_t chain_id; -}; - -/* LDAP connection cache connection attempt/established connection data */ -struct sdap_id_conn_data { - /* LDAP connection cache */ - struct sdap_id_conn_cache *conn_cache; - /* double linked list pointers */ - struct sdap_id_conn_data *prev, *next; - /* sdap handle */ - struct sdap_handle *sh; - /* connection request */ - struct tevent_req *connect_req; - /* timer for connection expiration */ - struct tevent_timer *expire_timer; - /* timer for idle connection expiration */ - struct tevent_timer *idle_timer; - /* number of running connection notifies */ - int notify_lock; - /* list of operations using connect */ - struct sdap_id_op *ops; - /* A flag which is signalizing that this - * connection will be disconnected and should - * not be used any more */ - bool disconnecting; -}; - -static void sdap_id_conn_cache_be_offline_cb(void *pvt); -static void sdap_id_conn_cache_fo_reconnect_cb(void *pvt); - -static void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data); -static int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data); -static bool sdap_is_connection_expired(struct sdap_id_conn_data *conn_data, int timeout); -static bool sdap_can_reuse_connection(struct sdap_id_conn_data *conn_data); -static void sdap_id_conn_data_expire_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *pvt); -static int sdap_id_conn_data_set_expire_timer(struct sdap_id_conn_data *conn_data); -static void sdap_id_conn_data_idle_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *pvt); -static int sdap_id_conn_data_start_idle_timer(struct sdap_id_conn_data *conn_data); -static void sdap_id_conn_data_not_idle(struct sdap_id_conn_data *conn_data); -static void sdap_id_conn_data_idle(struct sdap_id_conn_data *conn_data); - -static void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn_data *conn_data); -static int sdap_id_op_destroy(void *pvt); -static bool sdap_id_op_can_reconnect(struct sdap_id_op *op); - -static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret); -static int sdap_id_op_connect_state_destroy(void *pvt); -static int sdap_id_op_connect_step(struct tevent_req *req); -static void sdap_id_op_connect_done(struct tevent_req *subreq); - -/* Create a connection cache */ -int sdap_id_conn_cache_create(TALLOC_CTX *memctx, - struct sdap_id_conn_ctx *id_conn, - struct sdap_id_conn_cache** conn_cache_out) -{ - int ret; - struct sdap_id_conn_cache *conn_cache = talloc_zero(memctx, struct sdap_id_conn_cache); - if (!conn_cache) { - DEBUG(SSSDBG_CRIT_FAILURE, - "talloc_zero(struct sdap_id_conn_cache) failed.\n"); - ret = ENOMEM; - goto fail; - } - - conn_cache->id_conn = id_conn; - - ret = be_add_offline_cb(conn_cache, id_conn->id_ctx->be, - sdap_id_conn_cache_be_offline_cb, conn_cache, - NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n"); - goto fail; - } - - ret = be_add_reconnect_cb(conn_cache, id_conn->id_ctx->be, - sdap_id_conn_cache_fo_reconnect_cb, conn_cache, - NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "be_add_reconnect_cb failed.\n"); - goto fail; - } - - *conn_cache_out = conn_cache; - return EOK; - -fail: - talloc_zfree(conn_cache); - return ret; -} - -/* Callback on BE going offline */ -static void sdap_id_conn_cache_be_offline_cb(void *pvt) -{ - struct sdap_id_conn_cache *conn_cache = talloc_get_type(pvt, struct sdap_id_conn_cache); - struct sdap_id_conn_data *cached_connection = conn_cache->cached_connection; - - /* Release any cached connection on going offline */ - if (cached_connection != NULL) { - conn_cache->cached_connection = NULL; - sdap_id_release_conn_data(cached_connection); - } -} - -/* Callback for attempt to reconnect to primary server */ -static void sdap_id_conn_cache_fo_reconnect_cb(void *pvt) -{ - struct sdap_id_conn_cache *conn_cache = talloc_get_type(pvt, struct sdap_id_conn_cache); - struct sdap_id_conn_data *cached_connection = conn_cache->cached_connection; - - /* Release any cached connection on going offline */ - if (cached_connection != NULL) { - cached_connection->disconnecting = true; - } -} - -/* Release sdap_id_conn_data and destroy it if no longer needed */ -static void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data) -{ - ber_socket_t fd = -1; - Sockbuf *sb; - int ret; - struct sdap_id_conn_cache *conn_cache; - if (!conn_data || conn_data->ops || conn_data->notify_lock) { - /* connection is in use */ - return; - } - - conn_cache = conn_data->conn_cache; - if (conn_data == conn_cache->cached_connection) { - return; - } - - if (conn_data->sh && conn_data->sh->ldap) { - ret = ldap_get_option(conn_data->sh->ldap, LDAP_OPT_SOCKBUF, &sb); - if (ret == LDAP_OPT_SUCCESS) { - if (ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &fd) != 1) { - fd = -1; - } - } - } - - DEBUG(SSSDBG_TRACE_ALL, "Releasing unused connection with fd [%d]\n", fd); - - DLIST_REMOVE(conn_cache->connections, conn_data); - talloc_zfree(conn_data); -} - -/* Destructor for struct sdap_id_conn_data */ -static int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data) -{ - struct sdap_id_op *op; - - /* we clean out list of ops to make sure that order of destruction does not matter */ - while ((op = conn_data->ops) != NULL) { - op->conn_data = NULL; - DLIST_REMOVE(conn_data->ops, op); - } - - return 0; -} - -/* Check whether connection will expire after timeout seconds */ -static bool sdap_is_connection_expired(struct sdap_id_conn_data *conn_data, int timeout) -{ - time_t expire_time; - if (!conn_data || !conn_data->sh || !conn_data->sh->connected) { - return true; - } - - expire_time = conn_data->sh->expire_time; - if ((expire_time != 0) && (expire_time < time( NULL ) + timeout) ) { - return true; - } - - return false; -} - -/* Check whether connection can be reused for next LDAP ID operation */ -static bool sdap_can_reuse_connection(struct sdap_id_conn_data *conn_data) -{ - int timeout; - - if (!conn_data || !conn_data->sh || - !conn_data->sh->connected || conn_data->disconnecting) { - return false; - } - - timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->id_ctx->opts->basic, - SDAP_OPT_TIMEOUT); - return !sdap_is_connection_expired(conn_data, timeout); -} - -/* Set expiration timer for connection if needed */ -static int sdap_id_conn_data_set_expire_timer(struct sdap_id_conn_data *conn_data) -{ - int timeout; - struct timeval tv; - - talloc_zfree(conn_data->expire_timer); - - memset(&tv, 0, sizeof(tv)); - - tv.tv_sec = conn_data->sh->expire_time; - if (tv.tv_sec <= 0) { - return EOK; - } - - timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->id_ctx->opts->basic, - SDAP_OPT_TIMEOUT); - if (timeout > 0) { - tv.tv_sec -= timeout; - } - - if (tv.tv_sec <= time(NULL)) { - DEBUG(SSSDBG_TRACE_ALL, - "Not starting expire timer because connection is already expired\n"); - return EOK; - } - - conn_data->expire_timer = - tevent_add_timer(conn_data->conn_cache->id_conn->id_ctx->be->ev, - conn_data, tv, - sdap_id_conn_data_expire_handler, - conn_data); - if (!conn_data->expire_timer) { - return ENOMEM; - } - - return EOK; -} - -/* Handler for connection expiration timer */ -static void sdap_id_conn_data_expire_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *pvt) -{ - struct sdap_id_conn_data *conn_data = talloc_get_type(pvt, - struct sdap_id_conn_data); - struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache; - - if (conn_cache->cached_connection == conn_data) { - DEBUG(SSSDBG_TRACE_ALL, - "Connection is about to expire, releasing it\n"); - conn_cache->cached_connection = NULL; - sdap_id_release_conn_data(conn_data); - } -} - -/* We could simply cancel the idle timer at the beginning of every operation - * then reschedule it at the end of every operation. However, to reduce the - * overhead associated with canceling and rescheduling the timer, we instead - * update conn_data->sh->idle_time at the beginning and end of each operation, - * then have the timer handler check idle_time and reschedule the timer as - * needed. - * - * Note that sdap_id_conn_data_not_idle() and/or sdap_id_conn_data_idle() may be - * called before sdap_id_conn_data_start_idle_timer() is called for a particular - * connection. - */ - -/* Start idle timer for connection if needed */ -static int sdap_id_conn_data_start_idle_timer(struct sdap_id_conn_data *conn_data) -{ - time_t now; - int idle_timeout; - struct timeval tv; - - now = time(NULL); - conn_data->sh->idle_time = now; - - talloc_zfree(conn_data->idle_timer); - - idle_timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->id_ctx->opts->basic, - SDAP_IDLE_TIMEOUT); - conn_data->sh->idle_timeout = idle_timeout; - DEBUG(SSSDBG_CONF_SETTINGS, "idle timeout is %d\n", idle_timeout); - if (idle_timeout <= 0) { - return EOK; - } - - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = now + idle_timeout; - DEBUG(SSSDBG_TRACE_ALL, - "Scheduling connection idle timer to run at %"SPRItime"\n", tv.tv_sec); - - conn_data->idle_timer = - tevent_add_timer(conn_data->conn_cache->id_conn->id_ctx->be->ev, - conn_data, tv, - sdap_id_conn_data_idle_handler, - conn_data); - if (!conn_data->idle_timer) { - return ENOMEM; - } - - return EOK; -} - -/* Handler for idle connection expiration timer */ -static void sdap_id_conn_data_idle_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *pvt) -{ - struct sdap_id_conn_data *conn_data = talloc_get_type(pvt, - struct sdap_id_conn_data); - struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache; - - time_t now; - time_t idle_time; - int idle_timeout; - struct timeval tv; - - if (conn_cache->cached_connection != conn_data) { - DEBUG(SSSDBG_TRACE_ALL, "Abandoning idle timer for released connection\n"); - return; - } - - now = time(NULL); - idle_time = conn_data->sh->idle_time; - idle_timeout = conn_data->sh->idle_timeout; - - if (idle_time != 0 && idle_time + idle_timeout <= now) { - DEBUG(SSSDBG_TRACE_ALL, - "Connection has reached idle timeout, releasing it\n"); - conn_cache->cached_connection = NULL; - sdap_id_release_conn_data(conn_data); - return; - } - - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = (idle_time == 0 ? now : idle_time) + idle_timeout; - DEBUG(SSSDBG_TRACE_ALL, - "Rescheduling connection idle timer to run at %"SPRItime"\n", tv.tv_sec); - - conn_data->idle_timer = - tevent_add_timer(conn_data->conn_cache->id_conn->id_ctx->be->ev, - conn_data, tv, - sdap_id_conn_data_idle_handler, - conn_data); - if (!conn_data->idle_timer) { - DEBUG(SSSDBG_MINOR_FAILURE, - "sdap_id_conn_data_idle_handler() failed to reschedule connection idle timer"); - } -} - -/* Mark connection as not idle */ -static void sdap_id_conn_data_not_idle(struct sdap_id_conn_data *conn_data) -{ - if (conn_data && conn_data->sh) { - DEBUG(SSSDBG_TRACE_ALL, "Marking connection as not idle\n"); - conn_data->sh->idle_time = 0; - } -} - -/* Mark connection as idle */ -static void sdap_id_conn_data_idle(struct sdap_id_conn_data *conn_data) -{ - if (conn_data && conn_data->sh) { - DEBUG(SSSDBG_TRACE_ALL, "Marking connection as idle\n"); - conn_data->sh->idle_time = time(NULL); - } -} - -/* Create an operation object */ -struct sdap_id_op *sdap_id_op_create(TALLOC_CTX *memctx, struct sdap_id_conn_cache *conn_cache) -{ - struct sdap_id_op *op = talloc_zero(memctx, struct sdap_id_op); - if (!op) { - return NULL; - } - - op->conn_cache = conn_cache; - - /* Remember the current chain id so we can use it when connection is - * established. This is required since the connection might be done - * by other request that was called before. */ - op->chain_id = sss_chain_id_get(); - - talloc_set_destructor((void*)op, sdap_id_op_destroy); - return op; -} - -/* Attach/detach connection to sdap_id_op */ -static void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn_data *conn_data) -{ - struct sdap_id_conn_data *current; - - if (!op) { - DEBUG(SSSDBG_FATAL_FAILURE, "NULL op passed!!!\n"); - return; - } - - current = op->conn_data; - if (conn_data == current) { - return; - } - - if (current) { - DLIST_REMOVE(current->ops, op); - } - - op->conn_data = conn_data; - - if (conn_data) { - sdap_id_conn_data_not_idle(conn_data); - DLIST_ADD_END(conn_data->ops, op, struct sdap_id_op*); - } - - if (current && !current->ops) { - if (current == current->conn_cache->cached_connection) { - sdap_id_conn_data_idle(current); - } else { - sdap_id_release_conn_data(current); - } - } -} - -/* Destructor for sdap_id_op */ -static int sdap_id_op_destroy(void *pvt) -{ - struct sdap_id_op *op = talloc_get_type(pvt, struct sdap_id_op); - - if (op->conn_data) { - DEBUG(SSSDBG_TRACE_ALL, "releasing operation connection\n"); - sdap_id_op_hook_conn_data(op, NULL); - } - - return 0; -} - -/* Check whether retry with reconnect can be performed for the operation */ -static bool sdap_id_op_can_reconnect(struct sdap_id_op *op) -{ - /* we allow 2 retries for failover server configured: - * - one for connection broken during request execution - * - one for the following (probably failed) reconnect attempt */ - int max_retries; - int count; - - count = be_fo_get_server_count(op->conn_cache->id_conn->id_ctx->be, - op->conn_cache->id_conn->service->name); - max_retries = 2 * count -1; - if (max_retries < 1) { - max_retries = 1; - } - - return op->reconnect_retry_count < max_retries; -} - -/* state of connect request */ -struct sdap_id_op_connect_state { - struct sdap_id_conn_ctx *id_conn; - struct tevent_context *ev; - struct sdap_id_op *op; - int result; -}; - -/* Destructor for operation connection request */ -static int sdap_id_op_connect_state_destroy(void *pvt) -{ - struct sdap_id_op_connect_state *state = talloc_get_type(pvt, - struct sdap_id_op_connect_state); - if (state->op != NULL) { - /* clear destroyed connection request */ - state->op->connect_req = NULL; - } - - return 0; -} - -/* Begin to connect to LDAP server */ -struct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op, - TALLOC_CTX *memctx, - int *ret_out) -{ - struct tevent_req *req = NULL; - struct sdap_id_op_connect_state *state; - int ret = EOK; - - if (!memctx) { - DEBUG(SSSDBG_CRIT_FAILURE, "Bug: no memory context passed.\n"); - ret = EINVAL; - goto done; - } - - if (op->connect_req) { - /* Connection already in progress, invalid operation */ - DEBUG(SSSDBG_CRIT_FAILURE, - "Bug: connection request is already running or completed and leaked.\n"); - ret = EINVAL; - goto done; - } - - req = tevent_req_create(memctx, &state, struct sdap_id_op_connect_state); - if (!req) { - ret = ENOMEM; - goto done; - } - - talloc_set_destructor((void*)state, sdap_id_op_connect_state_destroy); - - state->id_conn = op->conn_cache->id_conn; - state->ev = state->id_conn->id_ctx->be->ev; - state->op = op; - op->connect_req = req; - - if (op->conn_data) { - /* If the operation is already connected, - * reuse existing connection regardless of its status */ - DEBUG(SSSDBG_TRACE_ALL, "reusing operation connection\n"); - ret = EOK; - goto done; - } - - ret = sdap_id_op_connect_step(req); - if (ret != EOK) { - goto done; - } - -done: - if (ret != EOK) { - talloc_zfree(req); - } else if (op->conn_data && !op->conn_data->connect_req) { - /* Connection is already established */ - tevent_req_done(req); - tevent_req_post(req, state->ev); - } - - if (ret_out) { - *ret_out = ret; - } - - return req; -} - -/* Begin a connection retry to LDAP server */ -static int sdap_id_op_connect_step(struct tevent_req *req) -{ - struct sdap_id_op_connect_state *state = - tevent_req_data(req, struct sdap_id_op_connect_state); - struct sdap_id_op *op = state->op; - struct sdap_id_conn_cache *conn_cache = op->conn_cache; - - int ret = EOK; - struct sdap_id_conn_data *conn_data; - struct tevent_req *subreq = NULL; - - /* Try to reuse context cached connection */ - conn_data = conn_cache->cached_connection; - if (conn_data) { - if (conn_data->connect_req) { - DEBUG(SSSDBG_TRACE_ALL, "waiting for connection to complete\n"); - sdap_id_op_hook_conn_data(op, conn_data); - goto done; - } - - if (sdap_can_reuse_connection(conn_data)) { - DEBUG(SSSDBG_TRACE_ALL, "reusing cached connection\n"); - sdap_id_op_hook_conn_data(op, conn_data); - goto done; - } - - DEBUG(SSSDBG_TRACE_ALL, "releasing expired cached connection\n"); - conn_cache->cached_connection = NULL; - sdap_id_release_conn_data(conn_data); - } - - DEBUG(SSSDBG_TRACE_ALL, "beginning to connect\n"); - - conn_data = talloc_zero(conn_cache, struct sdap_id_conn_data); - if (!conn_data) { - ret = ENOMEM; - goto done; - } - - talloc_set_destructor(conn_data, sdap_id_conn_data_destroy); - - conn_data->conn_cache = conn_cache; - subreq = sdap_cli_resolve_and_connect_send(conn_data, state->ev, - state->id_conn->id_ctx->opts, - state->id_conn->id_ctx->be, - state->id_conn->service, false, - CON_TLS_DFL, false); - - if (!subreq) { - ret = ENOMEM; - goto done; - } - - tevent_req_set_callback(subreq, sdap_id_op_connect_done, conn_data); - conn_data->connect_req = subreq; - - DLIST_ADD(conn_cache->connections, conn_data); - conn_cache->cached_connection = conn_data; - - sdap_id_op_hook_conn_data(op, conn_data); - -done: - if (ret != EOK && conn_data) { - sdap_id_release_conn_data(conn_data); - } - - if (ret != EOK) { - talloc_zfree(subreq); - } - - return ret; -} - -static void sdap_id_op_connect_reinit_done(struct tevent_req *req); - -/* Subrequest callback for connection completion */ -static void sdap_id_op_connect_done(struct tevent_req *subreq) -{ - struct sdap_id_conn_data *conn_data = - tevent_req_callback_data(subreq, struct sdap_id_conn_data); - struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache; - struct sdap_server_opts *srv_opts = NULL; - struct sdap_server_opts *current_srv_opts = NULL; - bool can_retry = false; - bool is_offline = false; - struct tevent_req *reinit_req = NULL; - bool reinit = false; - int ret; - int ret_nonfatal; - - ret = sdap_cli_resolve_and_connect_recv(subreq, conn_data, &can_retry, - &conn_data->sh, &srv_opts); - conn_data->connect_req = NULL; - talloc_zfree(subreq); - - conn_data->notify_lock++; - - if (ret == ENOTSUP) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Authentication mechanism not Supported by server\n"); - } - - if (ret == EOK && (!conn_data->sh || !conn_data->sh->connected)) { - DEBUG(SSSDBG_FATAL_FAILURE, - "sdap_cli_resolve_and_connect_recv returned bogus connection\n"); - ret = EFAULT; - } - - if (ret != EOK && !can_retry) { - if (conn_cache->id_conn->ignore_mark_offline) { - DEBUG(SSSDBG_TRACE_FUNC, - "Failed to connect to server, but ignore mark offline " - "is enabled.\n"); - } else { - /* be is going offline as there is no more servers to try */ - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect, going offline (%d [%s])\n", - ret, strerror(ret)); - is_offline = true; - be_mark_offline(conn_cache->id_conn->id_ctx->be); - } - } - - if (ret == EOK) { - current_srv_opts = conn_cache->id_conn->id_ctx->srv_opts; - if (current_srv_opts) { - DEBUG(SSSDBG_TRACE_INTERNAL, - "Old USN: %lu, New USN: %lu\n", current_srv_opts->last_usn, srv_opts->last_usn); - - if (strcmp(srv_opts->server_id, current_srv_opts->server_id) == 0 - && srv_opts->supports_usn - && current_srv_opts->last_usn > srv_opts->last_usn) { - DEBUG(SSSDBG_FUNC_DATA, "Server was probably re-initialized\n"); - - current_srv_opts->max_user_value = 0; - current_srv_opts->max_group_value = 0; - current_srv_opts->max_service_value = 0; - current_srv_opts->max_sudo_value = 0; - current_srv_opts->max_iphost_value = 0; - current_srv_opts->max_ipnetwork_value = 0; - current_srv_opts->last_usn = srv_opts->last_usn; - - reinit = true; - } - } - ret_nonfatal = sdap_id_conn_data_set_expire_timer(conn_data); - if (ret_nonfatal != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "sdap_id_conn_data_set_expire_timer() failed [%d]: %s", - ret_nonfatal, sss_strerror(ret_nonfatal)); - } - ret_nonfatal = sdap_id_conn_data_start_idle_timer(conn_data); - if (ret_nonfatal != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "sdap_id_conn_data_start_idle_timer() failed [%d]: %s", - ret_nonfatal, sss_strerror(ret_nonfatal)); - } - sdap_steal_server_opts(conn_cache->id_conn->id_ctx, &srv_opts); - } - - if (can_retry) { - switch (ret) { - case EOK: - case ENOTSUP: - case EACCES: - case EIO: - case EFAULT: - case ETIMEDOUT: - case ERR_AUTH_FAILED: - break; - - default: - /* do not attempt to retry on errors like ENOMEM */ - DEBUG(SSSDBG_TRACE_FUNC, - "Marking the backend \"%s\" offline [%d]: %s\n", - conn_cache->id_conn->id_ctx->be->domain->name, - ret, sss_strerror(ret)); - can_retry = false; - is_offline = true; - be_mark_offline(conn_cache->id_conn->id_ctx->be); - break; - } - } - - int notify_count = 0; - - /* Notify about connection */ - for(;;) { - struct sdap_id_op *op; - - if (ret == EOK && !conn_data->sh->connected) { - DEBUG(SSSDBG_TRACE_ALL, - "connection was broken after %d notifies\n", notify_count); - } - - DLIST_FOR_EACH(op, conn_data->ops) { - if (op->connect_req) { - break; - } - } - - if (!op) { - break; - } - - /* another operation to notify */ - notify_count++; - - if (ret != EOK || !conn_data->sh->connected) { - /* failed to connect or connection got broken during notify */ - bool retry = false; - - /* drop connection from cache now */ - if (conn_cache->cached_connection == conn_data) { - conn_cache->cached_connection = NULL; - } - - if (can_retry) { - /* determining whether retry is possible */ - if (be_is_offline(conn_cache->id_conn->id_ctx->be)) { - /* be is offline, no retry possible */ - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_ALL, - "skipping automatic retry on op #%d as be is offline\n", notify_count); - ret = EIO; - } - - can_retry = false; - is_offline = true; - } else { - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_ALL, - "attempting automatic retry on op #%d\n", notify_count); - retry = true; - } else if (sdap_id_op_can_reconnect(op)) { - DEBUG(SSSDBG_TRACE_ALL, - "attempting failover retry on op #%d\n", notify_count); - op->reconnect_retry_count++; - retry = true; - } - } - } - - if (retry && op->connect_req) { - int retry_ret = sdap_id_op_connect_step(op->connect_req); - if (retry_ret != EOK) { - can_retry = false; - sdap_id_op_connect_req_complete(op, retry_ret); - } - - continue; - } - } - - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_ALL, - "notify connected to op #%d\n", notify_count); - sdap_id_op_connect_req_complete(op, ret); - } else if (is_offline) { - DEBUG(SSSDBG_TRACE_ALL, "notify offline to op #%d\n", notify_count); - sdap_id_op_connect_req_complete(op, EAGAIN); - } else { - DEBUG(SSSDBG_TRACE_ALL, - "notify error to op #%d: %d [%s]\n", notify_count, ret, strerror(ret)); - sdap_id_op_connect_req_complete(op, ret); - } - } - - /* all operations notified */ - if (conn_data->notify_lock > 0) { - conn_data->notify_lock--; - } - - if ((ret == EOK) - && conn_data->sh->connected - && !be_is_offline(conn_cache->id_conn->id_ctx->be)) { - DEBUG(SSSDBG_TRACE_ALL, - "caching successful connection after %d notifies\n", notify_count); - conn_cache->cached_connection = conn_data; - - /* Run any post-connection routines */ - be_run_unconditional_online_cb(conn_cache->id_conn->id_ctx->be); - be_run_online_cb(conn_cache->id_conn->id_ctx->be); - - } else { - if (conn_cache->cached_connection == conn_data) { - conn_cache->cached_connection = NULL; - } - - sdap_id_release_conn_data(conn_data); - } - - if (reinit) { - DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. " - "Cleaning cache.\n"); - reinit_req = sdap_reinit_cleanup_send(conn_cache->id_conn->id_ctx->be, - conn_cache->id_conn->id_ctx->be, - conn_cache->id_conn->id_ctx); - if (reinit_req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization " - "clean up.\n"); - return; - } - - tevent_req_set_callback(reinit_req, sdap_id_op_connect_reinit_done, - NULL); - } -} - -static void sdap_id_op_connect_reinit_done(struct tevent_req *req) -{ - errno_t ret; - - ret = sdap_reinit_cleanup_recv(req); - talloc_zfree(req); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization " - "clean up [%d]: %s\n", ret, strerror(ret)); - /* not fatal */ - return; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n"); -} - -/* Mark operation connection request as complete */ -static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret) -{ - struct tevent_req *req = op->connect_req; - struct sdap_id_op_connect_state *state; - uint64_t old_chain_id; - - if (!req) { - return; - } - - op->connect_req = NULL; - - state = tevent_req_data(req, struct sdap_id_op_connect_state); - state->result = ret; - - /* Set the chain id to the one associated with this request. */ - old_chain_id = sss_chain_id_set(op->chain_id); - if (ret == EOK) { - tevent_req_done(req); - } else { - sdap_id_op_hook_conn_data(op, NULL); - tevent_req_error(req, ret); - } - sss_chain_id_set(old_chain_id); -} - -/* Get the result of an asynchronous connect operation on sdap_id_op - * - * In data provider error code is returned: - * ERR_OK - connection established - * ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * ERR_FATAL - operation failed - */ -int sdap_id_op_connect_recv(struct tevent_req *req) -{ - struct sdap_id_op_connect_state *state = tevent_req_data(req, - struct sdap_id_op_connect_state); - - return state->result; -} - -/* Report completion of LDAP operation and release associated connection. - * Returns operation result (possible updated) passed in ret parameter. - * - * In data provider error code is returned: - * ERR_OK (operation result = EOK) - operation completed - * ERR_OK (operation result != EOK) - operation can be retried - * ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * ERR_FATAL - operation failed */ -int sdap_id_op_done(struct sdap_id_op *op, int retval) -{ - bool communication_error; - struct sdap_id_conn_data *current_conn = op->conn_data; - switch (retval) { - case EIO: - case ETIMEDOUT: - /* this currently the only possible communication error after connection is established */ - communication_error = true; - break; - - default: - communication_error = false; - break; - } - - if (communication_error && current_conn != 0 - && current_conn == op->conn_cache->cached_connection) { - /* do not reuse failed connection */ - op->conn_cache->cached_connection = NULL; - - DEBUG(SSSDBG_FUNC_DATA, - "communication error on cached connection, moving to next server\n"); - be_fo_try_next_server(op->conn_cache->id_conn->id_ctx->be, - op->conn_cache->id_conn->service->name); - } - - if (retval == EOK) { - /* operation completed successfully */ - op->reconnect_retry_count = 0; - } else if (be_is_offline(op->conn_cache->id_conn->id_ctx->be)) { - /* if backend is already offline, just report offline, do not duplicate errors */ - retval = EAGAIN; - op->reconnect_retry_count = 0; - DEBUG(SSSDBG_TRACE_ALL, "falling back to offline data...\n"); - } else if (communication_error) { - /* communication error, can try to reconnect */ - - if (!sdap_id_op_can_reconnect(op)) { - DEBUG(SSSDBG_TRACE_ALL, - "too many communication failures, giving up...\n"); - op->reconnect_retry_count = 0; - } else { - retval = EAGAIN; - op->reconnect_retry_count++; - DEBUG(SSSDBG_TRACE_ALL, - "advising for connection retry #%i\n", op->reconnect_retry_count); - } - } else { - /* fatal error, cannot retry */ - op->reconnect_retry_count = 0; - } - - if (current_conn) { - DEBUG(SSSDBG_TRACE_ALL, "releasing operation connection\n"); - sdap_id_op_hook_conn_data(op, NULL); - } - - return retval; -} - -/* Get SDAP handle associated with operation by sdap_id_op_connect */ -struct sdap_handle *sdap_id_op_handle(struct sdap_id_op *op) -{ - return op && op->conn_data ? op->conn_data->sh : NULL; -} diff --git a/src/providers/ldap/sdap_id_op.h b/src/providers/ldap/sdap_id_op.h deleted file mode 100644 index 1e0f9d8ce97..00000000000 --- a/src/providers/ldap/sdap_id_op.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - SSSD - - LDAP ID backend operation retry logic and connection cache - - Authors: - Eugene Indenbom - - Copyright (C) 2008-2010 Red Hat - - 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 . -*/ - -#ifndef _SDAP_ID_OP_H_ -#define _SDAP_ID_OP_H_ - -struct sdap_id_ctx; -struct sdap_id_conn_ctx; - -/* LDAP async connection cache */ -struct sdap_id_conn_cache; - -/* LDAP async operation tracker: - * - keeps track of connection usage - * - keeps track of operation retries */ -struct sdap_id_op; - -/* Create a connection cache */ -int sdap_id_conn_cache_create(TALLOC_CTX *memctx, - struct sdap_id_conn_ctx *id_conn, - struct sdap_id_conn_cache** conn_cache_out); - -/* Create an operation object */ -struct sdap_id_op *sdap_id_op_create(TALLOC_CTX *memctx, struct sdap_id_conn_cache *cache); - -/* Begin to connect to LDAP server. */ -struct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op, - TALLOC_CTX *memctx, - int *ret_out); - -/* Get the result of an asynchronous connect operation on sdap_id_op - * - * In dp_error data provider error code is returned: - * ERR_OK - connection established - * ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * ERR_FATAL - operation failed - */ -int sdap_id_op_connect_recv(struct tevent_req *req); - -/* Report completion of LDAP operation and release associated connection. - * Returns operation result (possible updated) passed in ret parameter. - * - * In dp_error data provider error code is returned: - * ERR_OK (operation result = EOK) - operation completed - * ERR_OK (operation result != EOK) - operation can be retried - * ERR_OFFLINE - backend is offline, operation result is set EAGAIN - * ERR_FATAL - operation failed */ -int sdap_id_op_done(struct sdap_id_op*, int ret); - -/* Get SDAP handle associated with operation by sdap_id_op_connect */ -struct sdap_handle *sdap_id_op_handle(struct sdap_id_op *op); -/* Get root DSE entry of connected LDAP server */ -const struct sysdb_attrs *sdap_id_op_rootDSE(struct sdap_id_op *op); - -#endif /* _SDAP_ID_OP_H_ */ From b651bf998edd9f4828e76aa13abfcede1225a418 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 1 Apr 2026 14:12:44 -0400 Subject: [PATCH 25/39] AD: Initialize new failover --- Makefile.am | 1 + src/providers/ad/ad_access.h | 2 + src/providers/ad/ad_common.c | 95 ++++++++++++++++++++++++++++--- src/providers/ad/ad_common.h | 11 +++- src/providers/ad/ad_init.c | 35 ++++++++++++ src/providers/ldap/ldap_common.h | 1 + src/tests/cmocka/test_ad_common.c | 13 ----- 7 files changed, 136 insertions(+), 22 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4546497a3c7..ecdf8eda6f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4693,6 +4693,7 @@ libsss_ad_la_SOURCES = \ src/providers/ad/ad_refresh.c \ src/providers/ad/ad_resolver.c \ src/providers/ad/ad_cldap_ping.c \ + $(SSSD_NEW_FAILOVER_OBJ) \ $(NULL) diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h index c54b53eed01..97ec6ef5855 100644 --- a/src/providers/ad/ad_access.h +++ b/src/providers/ad/ad_access.h @@ -29,6 +29,8 @@ struct ad_access_ctx { struct dp_option *ad_options; struct sdap_access_ctx *sdap_access_ctx; struct ad_id_ctx *ad_id_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ctx *gc_fctx; /* supported GPO access control modes */ enum gpo_access_control_mode { GPO_ACCESS_CONTROL_DISABLED, diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c index 390b4f3e7c6..7fa97ebc2f0 100644 --- a/src/providers/ad/ad_common.c +++ b/src/providers/ad/ad_common.c @@ -25,6 +25,7 @@ #include "providers/ad/ad_opts.h" #include "providers/be_dyndns.h" #include "providers/fail_over.h" +#include "providers/failover/ldap/failover_ldap.h" struct ad_server_data { bool gc; @@ -795,6 +796,93 @@ static void ad_online_cb(void *pvt) DEBUG(SSSDBG_TRACE_FUNC, "The AD provider is online\n"); } +struct sss_failover_ctx * +ad_init_failover(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts, + const char *service, + uint16_t port) +{ + struct sss_failover_ctx *fctx; + struct sss_failover_group *group; + struct sss_failover_server *server; + errno_t ret; + + /* Setup new failover. */ + fctx = sss_failover_init(mem_ctx, be_ctx->ev, service, + be_ctx->be_res->resolv, + be_ctx->be_res->family_order); + if (fctx == NULL) { + return NULL; + } + + /* Add primary servers */ + group = sss_failover_group_new(fctx, "primary"); + if (group == NULL) { + ret = ENOMEM; + goto done; + } + + server = sss_failover_server_new(fctx, "fake_1.samba.test", + "ldap://fake_1.samba.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_2.samba.test", + "ldap://fake_2.samba.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "dc.samba.test", + "ldap://dc.samba.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + /* kinit ctx needs to be set to call kinit vtable functions */ + fctx->kinit_ctx = fctx; + + sss_failover_vtable_set_kinit(fctx, + sss_failover_ldap_kinit_send, + sss_failover_ldap_kinit_recv, + opts); + + sss_failover_vtable_set_connect(fctx, + sss_failover_ldap_connect_send, + sss_failover_ldap_connect_recv, + opts); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(fctx); + return NULL; + } + + return fctx; +} + errno_t ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx, const char *primary_servers, @@ -1498,13 +1586,6 @@ ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx) return NULL; } ad_ctx->sdap_id_ctx = sdap_ctx; - ad_ctx->ldap_ctx = sdap_ctx->conn; - - ad_ctx->gc_ctx = sdap_id_ctx_conn_add(sdap_ctx, ad_opts->service->gc); - if (ad_ctx->gc_ctx == NULL) { - talloc_free(ad_ctx); - return NULL; - } return ad_ctx; } diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h index c32431add1a..9535fefc989 100644 --- a/src/providers/ad/ad_common.h +++ b/src/providers/ad/ad_common.h @@ -76,9 +76,9 @@ enum ad_basic_opt { struct ad_id_ctx { struct sdap_id_ctx *sdap_id_ctx; - struct sdap_id_conn_ctx *ldap_ctx; - struct sdap_id_conn_ctx *gc_ctx; struct ad_options *ad_options; + struct sss_failover_ctx *fctx; + struct sss_failover_ctx *gc_fctx; }; struct ad_resolver_ctx { @@ -145,6 +145,13 @@ struct ad_options *ad_create_trust_options(TALLOC_CTX *mem_ctx, errno_t ad_set_search_bases(struct sdap_options *id_opts, struct sdap_domain *sdap); +struct sss_failover_ctx * +ad_init_failover(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts, + const char *service, + uint16_t port); + errno_t ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, const char *primary_servers, diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index a6938d69f82..cab0d2f3a9b 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -42,12 +42,17 @@ #include "providers/be_dyndns.h" #include "providers/ad/ad_subdomains.h" #include "providers/ad/ad_domain_info.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_vtable.h" +#include "providers/failover/ldap/failover_ldap.h" struct ad_init_ctx { struct ad_options *options; struct ad_id_ctx *id_ctx; struct krb5_ctx *auth_ctx; struct ad_resolver_ctx *resolver_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ctx *gc_fctx; }; #define AD_COMPAT_ON "1" @@ -493,6 +498,31 @@ errno_t sssm_ad_init(TALLOC_CTX *mem_ctx, } } + /* Setup new failover. */ + init_ctx->fctx = ad_init_failover(init_ctx, be_ctx, + init_ctx->id_ctx->sdap_id_ctx->opts, + "AD", 389); + if (init_ctx->fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + ret = ENOMEM; + goto done; + } + + /* Global catalog */ + init_ctx->gc_fctx = ad_init_failover(init_ctx, be_ctx, + init_ctx->id_ctx->sdap_id_ctx->opts, + "AD_GC", 3268); + if (init_ctx->gc_fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + ret = ENOMEM; + goto done; + } + + init_ctx->id_ctx->fctx = init_ctx->fctx; + init_ctx->id_ctx->sdap_id_ctx->fctx = init_ctx->fctx; + init_ctx->id_ctx->sdap_id_ctx->gc_fctx = init_ctx->gc_fctx; + init_ctx->id_ctx->gc_fctx = init_ctx->gc_fctx; + *_module_data = init_ctx; ret = EOK; @@ -590,6 +620,11 @@ errno_t sssm_ad_access_init(TALLOC_CTX *mem_ctx, goto done; } + /* Failover */ + access_ctx->fctx = init_ctx->fctx; + access_ctx->gc_fctx = init_ctx->gc_fctx; + access_ctx->sdap_access_ctx->id_ctx->gc_fctx = init_ctx->gc_fctx; + ret = ad_init_gpo(access_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not initialize GPO " diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 1277fc61403..3ae0673539a 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -64,6 +64,7 @@ struct sdap_id_ctx { /* New failover context */ struct sss_failover_ctx *fctx; + struct sss_failover_ctx *gc_fctx; /* Enumeration/cleanup periodic task. Only the enumeration or the cleanup * task is started depending on the value of the domain's enumeration diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c index ae82b8c46d4..5e6fe224fda 100644 --- a/src/tests/cmocka/test_ad_common.c +++ b/src/tests/cmocka/test_ad_common.c @@ -879,7 +879,6 @@ test_ldap_conn_setup(void **state) struct sdap_domain *sdom; struct ad_id_ctx *ad_ctx; struct ad_id_ctx *subdom_ad_ctx; - struct sdap_id_conn_ctx *subdom_ldap_ctx; ret = test_ad_common_setup((void **) &test_ctx); assert_int_equal(ret, EOK); @@ -901,12 +900,6 @@ test_ldap_conn_setup(void **state) assert_non_null(ad_ctx->ad_options); - ad_ctx->gc_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx); - assert_non_null(ad_ctx->gc_ctx); - - ad_ctx->ldap_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx); - assert_non_null(ad_ctx->ldap_ctx); - ad_ctx->sdap_id_ctx = talloc_zero(ad_ctx, struct sdap_id_ctx); assert_non_null(ad_ctx->sdap_id_ctx); @@ -921,10 +914,6 @@ test_ldap_conn_setup(void **state) subdom_ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx); assert_non_null(subdom_ad_ctx); - subdom_ldap_ctx = talloc_zero(subdom_ad_ctx, struct sdap_id_conn_ctx); - assert_non_null(subdom_ldap_ctx); - subdom_ad_ctx->ldap_ctx = subdom_ldap_ctx; - ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->subdom, &sdom); assert_int_equal(ret, EOK); sdom->pvt = subdom_ad_ctx; @@ -946,8 +935,6 @@ test_ldap_conn_teardown(void **state) talloc_free(test_ctx->subdom_ad_ctx); talloc_free(test_ctx->ad_ctx->ad_options); - talloc_free(test_ctx->ad_ctx->gc_ctx); - talloc_free(test_ctx->ad_ctx->ldap_ctx); talloc_free(test_ctx->ad_ctx->sdap_id_ctx); test_ad_common_teardown((void **) &test_ctx); From b1c5d703984cc0978d5dd308de4c684c5cbe64c3 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 7 Apr 2026 10:40:03 -0400 Subject: [PATCH 26/39] ad: remove no longer needed connection logic --- src/providers/ad/ad_access.c | 33 +-- src/providers/ad/ad_common.c | 99 --------- src/providers/ad/ad_common.h | 17 -- src/providers/ad/ad_id.c | 70 +----- src/providers/ad/ad_id.h | 3 +- src/providers/ad/ad_pac.c | 2 - src/providers/ad/ad_pac.h | 1 - src/providers/ad/ad_subdomains.c | 1 - src/providers/ldap/ldap_id.c | 7 - src/providers/ldap/sdap_async_groups.c | 54 ----- src/providers/ldap/sdap_async_initgroups_ad.c | 18 -- src/tests/cmocka/test_ad_common.c | 207 ------------------ 12 files changed, 8 insertions(+), 504 deletions(-) diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c index 2ef88b7694c..0e72c048f06 100644 --- a/src/providers/ad/ad_access.c +++ b/src/providers/ad/ad_access.c @@ -238,12 +238,11 @@ struct ad_access_state { struct sss_domain_info *domain; char *filter; - struct sdap_id_conn_ctx **clist; int cindex; }; static errno_t -ad_sdap_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn); +ad_sdap_access_step(struct tevent_req *req); static void ad_sdap_access_done(struct tevent_req *req); @@ -278,13 +277,7 @@ ad_access_send(TALLOC_CTX *mem_ctx, goto done; } - state->clist = ad_gc_conn_list(state, ctx->ad_id_ctx, domain); - if (state->clist == NULL) { - ret = ENOMEM; - goto done; - } - - ret = ad_sdap_access_step(req, state->clist[state->cindex]); + ret = ad_sdap_access_step(req); if (ret != EOK) { goto done; } @@ -300,7 +293,7 @@ ad_access_send(TALLOC_CTX *mem_ctx, } static errno_t -ad_sdap_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn) +ad_sdap_access_step(struct tevent_req *req) { struct tevent_req *subreq; struct ad_access_state *state; @@ -320,7 +313,7 @@ ad_sdap_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn) subreq = sdap_access_send(state, state->ev, state->be_ctx, state->domain, req_ctx, - conn, state->pd); + state->pd); if (subreq == NULL) { talloc_free(req_ctx); return ENOMEM; @@ -363,24 +356,6 @@ ad_sdap_access_done(struct tevent_req *subreq) break; } - /* If possible, retry with LDAP */ - state->cindex++; - if (state->clist[state->cindex] == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "Error retrieving access check result: %s\n", - sss_strerror(ret)); - tevent_req_error(req, ret); - return; - } - - ret = ad_sdap_access_step(req, state->clist[state->cindex]); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* Another check in progress */ - return; } diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c index 7fa97ebc2f0..fd53f593d25 100644 --- a/src/providers/ad/ad_common.c +++ b/src/providers/ad/ad_common.c @@ -1617,105 +1617,6 @@ ad_resolver_ctx_init(TALLOC_CTX *mem_ctx, return EOK; } -struct sdap_id_conn_ctx * -ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom) -{ - struct sdap_id_conn_ctx *conn; - struct sdap_domain *sdom; - struct ad_id_ctx *subdom_id_ctx; - - sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom); - if (sdom == NULL || sdom->pvt == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n", - dom->name); - return NULL; - } - subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - conn = subdom_id_ctx->ldap_ctx; - - if (IS_SUBDOMAIN(sdom->dom) == true && conn != NULL) { - /* Regardless of connection types, a subdomain error must not be - * allowed to set the whole back end offline, rather report an error - * and let the caller deal with it (normally disable the subdomain - */ - conn->ignore_mark_offline = true; - } - - return conn; -} - -struct sdap_id_conn_ctx ** -ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom) -{ - struct sdap_id_conn_ctx **clist; - int cindex = 0; - - clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3); - if (clist == NULL) return NULL; - - /* Always try GC first */ - if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { - clist[cindex] = ad_ctx->gc_ctx; - clist[cindex]->ignore_mark_offline = true; - clist[cindex]->no_mpg_user_fallback = true; - cindex++; - } - - clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); - - return clist; -} - -struct sdap_id_conn_ctx ** -ad_ldap_conn_list(TALLOC_CTX *mem_ctx, - struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom) -{ - struct sdap_id_conn_ctx **clist; - - clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 2); - if (clist == NULL) { - return NULL; - } - - clist[0] = ad_get_dom_ldap_conn(ad_ctx, dom); - - clist[1] = NULL; - return clist; -} - -struct sdap_id_conn_ctx ** -ad_user_conn_list(TALLOC_CTX *mem_ctx, - struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom) -{ - struct sdap_id_conn_ctx **clist; - int cindex = 0; - - clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3); - if (clist == NULL) { - return NULL; - } - - /* Try GC first for users from trusted domains, but go to LDAP - * for users from non-trusted domains to get all POSIX attrs - */ - if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC) - && IS_SUBDOMAIN(dom)) { - clist[cindex] = ad_ctx->gc_ctx; - clist[cindex]->ignore_mark_offline = true; - cindex++; - } - - /* Users from primary domain can be just downloaded from LDAP. - * The domain's LDAP connection also works as a fallback - */ - clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); - - return clist; -} - errno_t subdom_inherit_opts_if_needed(struct dp_option *parent_opts, struct dp_option *subdom_opts, struct confdb_ctx *cdb, diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h index 9535fefc989..099c2b0714d 100644 --- a/src/providers/ad/ad_common.h +++ b/src/providers/ad/ad_common.h @@ -200,23 +200,6 @@ ad_resolver_ctx_init(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_id_ctx, struct ad_resolver_ctx **out_ctx); -struct sdap_id_conn_ctx ** -ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom); - -struct sdap_id_conn_ctx ** -ad_ldap_conn_list(TALLOC_CTX *mem_ctx, - struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom); - -struct sdap_id_conn_ctx ** -ad_user_conn_list(TALLOC_CTX *mem_ctx, - struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom); - -struct sdap_id_conn_ctx * -ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom); - /* AD dynamic DNS updates */ errno_t ad_dyndns_init(struct be_ctx *be_ctx, struct ad_options *ctx); diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index f20a8af9a62..d5f7d24f1b5 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -105,9 +105,7 @@ static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx, struct ad_handle_acct_info_state { struct dp_id_data *ar; struct sdap_id_ctx *ctx; - struct sdap_id_conn_ctx **conn; struct sdap_domain *sdom; - size_t cindex; struct ad_options *ad_options; bool using_pac; @@ -122,8 +120,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *ctx, struct ad_options *ad_options, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx **conn) + struct sdap_domain *sdom) { struct tevent_req *req; struct ad_handle_acct_info_state *state; @@ -138,9 +135,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, state->ar = ar; state->ctx = ctx; state->sdom = sdom; - state->conn = conn; state->ad_options = ad_options; - state->cindex = 0; /* Try to shortcut if this is ID or SID search and it belongs to * other domain range than is in ar->domain. */ @@ -187,15 +182,6 @@ ad_handle_acct_info_step(struct tevent_req *req) struct ldb_message *msg; int ret; - if (state->conn[state->cindex] == NULL) { - return EOK; - } - - if (state->conn[state->cindex+1] == NULL) { - noexist_delete = true; - } - - state->using_pac = false; if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_INITGROUPS) { ret = check_if_pac_is_available(state, state->sdom->dom, @@ -207,7 +193,6 @@ ad_handle_acct_info_step(struct tevent_req *req) subreq = ad_handle_pac_initgr_send(state, state->ctx->be, state->ar, state->ctx, state->sdom, - state->conn[state->cindex], noexist_delete, msg); if (subreq == NULL) { @@ -224,7 +209,6 @@ ad_handle_acct_info_step(struct tevent_req *req) subreq = sdap_handle_acct_req_send(state, state->ctx->be, state->ar, state->ctx, state->sdom, - state->conn[state->cindex], noexist_delete); if (subreq == NULL) { return ENOMEM; @@ -250,9 +234,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq) } else { ret = sdap_handle_acct_req_recv(subreq, &err); } - if (ret == ERR_OFFLINE - && state->conn[state->cindex+1] != NULL - && state->conn[state->cindex]->ignore_mark_offline) { + if (ret == ERR_OFFLINE) { /* This is a special case: GC does not work. * We need to Fall back to ldap */ @@ -275,7 +257,6 @@ ad_handle_acct_info_done(struct tevent_req *subreq) } /* Ret is only ENOENT now. Try the next connection */ - state->cindex++; ret = ad_handle_acct_info_step(req); if (ret != EAGAIN) { /* No additional search in progress. Save the last @@ -325,31 +306,6 @@ ad_handle_acct_info_recv(struct tevent_req *req, return EOK; } -struct sdap_id_conn_ctx ** -get_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom, struct dp_id_data *ar) -{ - struct sdap_id_conn_ctx **clist; - - switch (ar->entry_type & BE_REQ_TYPE_MASK) { - case BE_REQ_USER: /* user */ - clist = ad_user_conn_list(mem_ctx, ad_ctx, dom); - break; - case BE_REQ_BY_SECID: /* by SID */ - case BE_REQ_USER_AND_GROUP: /* get SID */ - case BE_REQ_GROUP: /* group */ - case BE_REQ_INITGROUPS: /* init groups for user */ - clist = ad_gc_conn_list(mem_ctx, ad_ctx, dom); - break; - default: - /* Requests for other object should only contact LDAP by default */ - clist = ad_ldap_conn_list(mem_ctx, ad_ctx, dom); - break; - } - - return clist; -} - struct ad_account_info_state { const char *err_msg; }; @@ -366,7 +322,6 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, struct ad_account_info_state *state = NULL; struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; - struct sdap_id_conn_ctx **clist = NULL; struct sdap_id_ctx *sdap_id_ctx = NULL; struct sdap_domain *sdom; errno_t ret; @@ -392,14 +347,6 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, goto immediately; } - /* Determine whether to connect to GC, LDAP or try both. */ - clist = get_conn_list(state, id_ctx, domain, data); - if (clist == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create conn list\n"); - ret = EIO; - goto immediately; - } - sdom = sdap_domain_get(sdap_id_ctx->opts, domain); if (sdom == NULL) { ret = EIO; @@ -407,7 +354,7 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, } subreq = ad_handle_acct_info_send(state, data, sdap_id_ctx, - id_ctx->ad_options, sdom, clist); + id_ctx->ad_options, sdom); if (subreq == NULL) { ret = ENOMEM; goto immediately; @@ -674,17 +621,6 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx, goto immediately; } - /* FIXME - should gc_ctx always default to ignore_offline on creation - * time rather than setting the flag on first use? - */ - id_ctx->gc_ctx->ignore_mark_offline = true; - state->op = sdap_id_op_create(state, id_ctx->gc_ctx->conn_cache); - if (state->op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto immediately; - } - ret = ad_get_account_domain_connect_retry(req); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Connection error"); diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h index dede0eddfc2..f906f33a16f 100644 --- a/src/providers/ad/ad_id.h +++ b/src/providers/ad/ad_id.h @@ -47,8 +47,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *ctx, struct ad_options *ad_options, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx **conn); + struct sdap_domain *sdom); errno_t ad_handle_acct_info_recv(struct tevent_req *req, const char **_err); diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c index 41d5d0145b7..bd255c3b8a1 100644 --- a/src/providers/ad/ad_pac.c +++ b/src/providers/ad/ad_pac.c @@ -247,7 +247,6 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, bool noexist_delete, struct ldb_message *msg) { @@ -341,7 +340,6 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, /* download missing SIDs */ subreq = sdap_ad_resolve_sids_send(state, be_ctx->ev, id_ctx, - conn, id_ctx->opts, sdom->dom, state->missing_sids); if (subreq == NULL) { diff --git a/src/providers/ad/ad_pac.h b/src/providers/ad/ad_pac.h index e7657b0219e..1188fb3f3cc 100644 --- a/src/providers/ad/ad_pac.h +++ b/src/providers/ad/ad_pac.h @@ -72,7 +72,6 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, struct sdap_domain *sdom, - struct sdap_id_conn_ctx *conn, bool noexist_delete, struct ldb_message *msg); diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index 2c255bb6671..1042dc55352 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -1341,7 +1341,6 @@ ads_get_dom_id_ctx(struct be_ctx *be_ctx, dom_id_ctx = sdom->pvt; } - dom_id_ctx->ldap_ctx->ignore_mark_offline = true; return dom_id_ctx; } diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index 8731aa47e2e..250395e47f1 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -1623,7 +1623,6 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) struct get_user_and_group_state *state = tevent_req_data(req, struct get_user_and_group_state); int ret; - struct sdap_id_conn_ctx *user_conn; ret = groups_get_recv(subreq); talloc_zfree(subreq); @@ -1644,12 +1643,6 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) /* Now the search finished fine but did not find an entry. * Retry with users. */ - /* Prefer LDAP over GC for users */ - user_conn = get_ldap_conn_from_sdom_pvt(state->id_ctx->opts, state->sdom); - if (user_conn == NULL) { - user_conn = state->conn; - } - subreq = users_get_send(req, state->ev, state->id_ctx, state->sdom, state->fctx, state->filter_val, state->filter_type, NULL, diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 5ece72f9988..4af046d26eb 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -1727,7 +1727,6 @@ struct sdap_get_groups_state { }; static errno_t sdap_get_groups_next_base(struct tevent_req *req); -static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq); static void sdap_get_groups_process(struct tevent_req *subreq); static void sdap_get_groups_done(struct tevent_req *subreq); @@ -1744,9 +1743,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, { errno_t ret; struct tevent_req *req; - struct tevent_req *subreq; struct sdap_get_groups_state *state; - struct sdap_id_conn_ctx *ldap_conn = NULL; req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); if (!req) return NULL; @@ -1775,30 +1772,6 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, goto done; } - /* With AD by default the Global Catalog is used for lookup. But the GC - * group object might not have full group membership data. To make sure we - * connect to an LDAP server of the group's domain. */ - ldap_conn = get_ldap_conn_from_sdom_pvt(state->opts, sdom); - if (ldap_conn != NULL) { - state->op = sdap_id_op_create(state, ldap_conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - ret = ENOMEM; - goto done; - } - - tevent_req_set_callback(subreq, - sdap_get_groups_ldap_connect_done, - req); - return req; - } - ret = sdap_get_groups_next_base(req); done: @@ -1810,33 +1783,6 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, return req; } -static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_get_groups_state *state; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_get_groups_state); - - ret = sdap_id_op_connect_recv(subreq); - talloc_zfree(subreq); - - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - state->ldap_sh = sdap_id_op_handle(state->op); - - ret = sdap_get_groups_next_base(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - - return; -} - static errno_t sdap_get_groups_next_base(struct tevent_req *req) { struct tevent_req *subreq; diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index 1cc7bca06d7..c7f1970ef64 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -1715,21 +1715,3 @@ static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx, done: return ret; } - -struct sdap_id_conn_ctx *get_ldap_conn_from_sdom_pvt(struct sdap_options *opts, - struct sdap_domain *sdom) -{ - struct ad_id_ctx *ad_id_ctx; - struct sdap_id_conn_ctx *user_conn = NULL; - - if (opts->schema_type == SDAP_SCHEMA_AD && sdom->pvt != NULL) { - ad_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - if (ad_id_ctx != NULL && ad_id_ctx->ldap_ctx != NULL) { - DEBUG(SSSDBG_TRACE_ALL, - "Returning LDAP connection for user lookup.\n"); - user_conn = ad_id_ctx->ldap_ctx; - } - } - - return user_conn; -} diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c index 5e6fe224fda..95083739557 100644 --- a/src/tests/cmocka/test_ad_common.c +++ b/src/tests/cmocka/test_ad_common.c @@ -871,76 +871,6 @@ static void test_ad_create_2way_trust_options(void **state) unlink(KEYTAB_PATH); } -static int -test_ldap_conn_setup(void **state) -{ - struct ad_common_test_ctx *test_ctx; - errno_t ret; - struct sdap_domain *sdom; - struct ad_id_ctx *ad_ctx; - struct ad_id_ctx *subdom_ad_ctx; - - ret = test_ad_common_setup((void **) &test_ctx); - assert_int_equal(ret, EOK); - - mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC); - - ad_ctx = test_ctx->ad_ctx; - - test_ctx->ad_ctx->ad_options = ad_create_trust_options( - ad_ctx, - NULL, - NULL, - NULL, - test_ctx->subdom, - REALMNAME, - HOST_NAME, - NULL, - NULL); - - assert_non_null(ad_ctx->ad_options); - - ad_ctx->sdap_id_ctx = talloc_zero(ad_ctx, struct sdap_id_ctx); - assert_non_null(ad_ctx->sdap_id_ctx); - - ad_ctx->sdap_id_ctx->opts = talloc_zero(ad_ctx->sdap_id_ctx, - struct sdap_options); - assert_non_null(ad_ctx->sdap_id_ctx->opts); - - ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->dom, &sdom); - assert_int_equal(ret, EOK); - sdom->pvt = ad_ctx; - - subdom_ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx); - assert_non_null(subdom_ad_ctx); - - ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->subdom, &sdom); - assert_int_equal(ret, EOK); - sdom->pvt = subdom_ad_ctx; - - test_ctx->subdom_ad_ctx = subdom_ad_ctx; - - *state = test_ctx; - return 0; -} - -static int -test_ldap_conn_teardown(void **state) -{ - struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, - struct ad_common_test_ctx); - assert_non_null(test_ctx); - - unlink(KEYTAB_PATH); - - talloc_free(test_ctx->subdom_ad_ctx); - talloc_free(test_ctx->ad_ctx->ad_options); - talloc_free(test_ctx->ad_ctx->sdap_id_ctx); - - test_ad_common_teardown((void **) &test_ctx); - return 0; -} - errno_t __wrap_sdap_select_principal_from_keytab_sync(TALLOC_CTX *mem_ctx, const char *princ_str, const char *realm_str, @@ -979,131 +909,6 @@ __wrap_sdap_set_sasl_options(struct sdap_options *id_opts, return EOK; } -void test_ad_get_dom_ldap_conn(void **state) -{ - struct sdap_id_conn_ctx *conn; - - struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, - struct ad_common_test_ctx); - assert_non_null(test_ctx); - - conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->dom); - assert_true(conn == test_ctx->ad_ctx->ldap_ctx); - - conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->subdom); - assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx); -} - -void test_gc_conn_list(void **state) -{ - struct sdap_id_conn_ctx **conn_list; - - struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, - struct ad_common_test_ctx); - assert_non_null(test_ctx); - - assert_true(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic, - AD_ENABLE_GC)); - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); - /* If there is a fallback, we should ignore the offline mode */ - assert_true(conn_list[0]->ignore_mark_offline); - assert_true(conn_list[1] == test_ctx->ad_ctx->ldap_ctx); - assert_false(conn_list[1]->ignore_mark_offline); - assert_null(conn_list[2]); - talloc_free(conn_list); - - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); - assert_true(conn_list[0]->ignore_mark_offline); - assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx); - /* Subdomain error should not set the backend offline! */ - assert_true(conn_list[1]->ignore_mark_offline); - talloc_free(conn_list); - - dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false); - assert_false(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic, - AD_ENABLE_GC)); - - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx); - assert_false(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); - - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx); - assert_true(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); -} - -void test_ldap_conn_list(void **state) -{ - struct sdap_id_conn_ctx **conn_list; - - struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, - struct ad_common_test_ctx); - assert_non_null(test_ctx); - - conn_list = ad_ldap_conn_list(test_ctx, - test_ctx->ad_ctx, - test_ctx->dom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx); - assert_false(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); - - conn_list = ad_ldap_conn_list(test_ctx, - test_ctx->ad_ctx, - test_ctx->subdom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx); - assert_true(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); -} - -void test_user_conn_list(void **state) -{ - struct sdap_id_conn_ctx **conn_list; - - struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, - struct ad_common_test_ctx); - assert_non_null(test_ctx); - - conn_list = ad_user_conn_list(test_ctx, test_ctx->ad_ctx, - test_ctx->dom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx); - assert_false(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); - - conn_list = ad_user_conn_list(test_ctx, test_ctx->ad_ctx, - test_ctx->subdom); - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); - assert_true(conn_list[0]->ignore_mark_offline); - assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx); - /* Subdomain error should not set the backend offline! */ - assert_true(conn_list[1]->ignore_mark_offline); - talloc_free(conn_list); -} - void test_netlogon_get_domain_info(void **state) { int ret; @@ -1200,18 +1005,6 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(test_ad_create_2way_trust_options, test_ad_common_setup, test_ad_common_teardown), - cmocka_unit_test_setup_teardown(test_ad_get_dom_ldap_conn, - test_ldap_conn_setup, - test_ldap_conn_teardown), - cmocka_unit_test_setup_teardown(test_gc_conn_list, - test_ldap_conn_setup, - test_ldap_conn_teardown), - cmocka_unit_test_setup_teardown(test_ldap_conn_list, - test_ldap_conn_setup, - test_ldap_conn_teardown), - cmocka_unit_test_setup_teardown(test_user_conn_list, - test_ldap_conn_setup, - test_ldap_conn_teardown), cmocka_unit_test_setup_teardown(test_check_if_pac_is_available, test_ad_sysdb_setup, test_ad_sysdb_teardown), From 08d660361a1b8777f7f4a1a2c256fcfb782cc3cf Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 7 Apr 2026 12:10:01 -0400 Subject: [PATCH 27/39] AD: Port provider to new failover --- src/providers/ad/ad_access.c | 44 ++-- src/providers/ad/ad_domain_info.c | 19 +- src/providers/ad/ad_domain_info.h | 10 +- src/providers/ad/ad_dyndns.c | 47 ++-- src/providers/ad/ad_gpo.c | 186 ++++++---------- src/providers/ad/ad_gpo.h | 1 + src/providers/ad/ad_id.c | 115 ++++------ src/providers/ad/ad_id.h | 3 +- src/providers/ad/ad_pac.c | 4 + src/providers/ad/ad_pac.h | 1 + src/providers/ad/ad_resolver.c | 45 ++-- src/providers/ad/ad_subdomains.c | 184 ++++------------ src/providers/ldap/ldap_access.c | 3 +- src/providers/ldap/sdap_access.c | 10 +- src/providers/ldap/sdap_access.h | 1 + src/providers/ldap/sdap_async.h | 2 +- src/providers/ldap/sdap_async_initgroups.c | 2 + src/providers/ldap/sdap_async_initgroups_ad.c | 207 ++++-------------- src/providers/ldap/sdap_async_private.h | 2 + 19 files changed, 304 insertions(+), 582 deletions(-) diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c index 0e72c048f06..ddb161df633 100644 --- a/src/providers/ad/ad_access.c +++ b/src/providers/ad/ad_access.c @@ -236,9 +236,11 @@ struct ad_access_state { struct pam_data *pd; struct be_ctx *be_ctx; struct sss_domain_info *domain; + struct sss_failover_ctx *fctx; char *filter; int cindex; + bool retried; }; static errno_t @@ -252,6 +254,7 @@ ad_access_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct ad_access_ctx *ctx, + struct sss_failover_ctx *fctx, struct pam_data *pd) { struct tevent_req *req; @@ -267,7 +270,9 @@ ad_access_send(TALLOC_CTX *mem_ctx, state->ctx = ctx; state->pd = pd; state->be_ctx = be_ctx; + state->fctx = fctx; state->domain = domain; + state->retried = false; ret = ad_parse_access_filter(state, domain, ctx->sdap_access_ctx->filter, &state->filter); @@ -313,7 +318,7 @@ ad_sdap_access_step(struct tevent_req *req) subreq = sdap_access_send(state, state->ev, state->be_ctx, state->domain, req_ctx, - state->pd); + state->fctx, state->pd); if (subreq == NULL) { talloc_free(req_ctx); return ENOMEM; @@ -339,24 +344,26 @@ ad_sdap_access_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - switch (ret) { - case ERR_ACCOUNT_EXPIRED: + if (ret == ERR_ACCOUNT_EXPIRED || ret == ERR_NO_MORE_SERVERS) { tevent_req_error(req, ret); return; - - case ERR_ACCESS_DENIED: - /* Retry on ACCESS_DENIED, too, to make sure that we don't - * miss out any attributes not present in GC - * FIXME - this is slow. We should retry only if GC failed - * and LDAP succeeded after the first ACCESS_DENIED - */ - break; - - default: - break; + } else { + if (state->retried) { + tevent_req_error(req, ret); + return; + /* Even with access denied, retry with LDAP to make sure that we don't + * miss out any attributes not present in GC */ + } else { + state->retried = true; + state->fctx = state->ctx->fctx; + + ret = ad_sdap_access_step(req); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + } } - - return; } switch (state->ctx->gpo_access_control_mode) { @@ -377,6 +384,7 @@ ad_sdap_access_done(struct tevent_req *subreq) state->be_ctx->ev, state->domain, state->ctx, + state->fctx, state->pd->user, state->pd->service); @@ -458,7 +466,9 @@ ad_pam_access_handler_send(TALLOC_CTX *mem_ctx, state->pd = pd; subreq = ad_access_send(state, params->ev, params->be_ctx, - params->domain, access_ctx, pd); + params->domain, access_ctx, + access_ctx->gc_fctx, + pd); if (subreq == NULL) { pd->pam_status = PAM_SYSTEM_ERR; goto immediately; diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c index 6338d412d5b..7f7f96eaf48 100644 --- a/src/providers/ad/ad_domain_info.c +++ b/src/providers/ad/ad_domain_info.c @@ -177,9 +177,8 @@ errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, struct ad_domain_info_state { struct tevent_context *ev; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *id_op; - struct sdap_id_ctx *id_ctx; struct sdap_options *opts; struct sdap_domain *sdom; @@ -199,8 +198,8 @@ static void ad_domain_info_netlogon_done(struct tevent_req *req); struct tevent_req * ad_domain_info_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_id_conn_ctx *conn, - struct sdap_id_op *op, + struct sdap_options *opts, + struct sss_failover_ldap_connection *conn, const char *dom_name) { errno_t ret; @@ -211,10 +210,8 @@ ad_domain_info_send(TALLOC_CTX *mem_ctx, if (!req) return NULL; state->ev = ev; - state->id_op = op; state->conn = conn; - state->id_ctx = conn->id_ctx; - state->opts = conn->id_ctx->opts; + state->opts = opts; state->dom_name = dom_name; state->sdom = sdap_domain_get_by_name(state->opts, state->dom_name); /* The first domain in the list is the domain configured in sssd.conf and @@ -272,8 +269,8 @@ ad_domain_info_next(struct tevent_req *req) } subreq = sdap_get_generic_send(state, state->ev, - state->id_ctx->opts, - sdap_id_op_handle(state->id_op), + state->opts, + state->conn->sh, base->basedn, LDAP_SCOPE_BASE, MASTER_DOMAIN_SID_FILTER, master_sid_attrs, NULL, 0, @@ -373,8 +370,8 @@ ad_domain_info_next_done(struct tevent_req *subreq) } subreq = sdap_get_generic_send(state, state->ev, - state->id_ctx->opts, - sdap_id_op_handle(state->id_op), + state->opts, + state->conn->sh, "", LDAP_SCOPE_BASE, filter, attrs, NULL, 0, dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), diff --git a/src/providers/ad/ad_domain_info.h b/src/providers/ad/ad_domain_info.h index cf601cff65c..cf136640e2f 100644 --- a/src/providers/ad/ad_domain_info.h +++ b/src/providers/ad/ad_domain_info.h @@ -25,12 +25,14 @@ #ifndef _AD_DOMAIN_INFO_H_ #define _AD_DOMAIN_INFO_H_ +#include "providers/failover/ldap/failover_ldap.h" + struct tevent_req * ad_domain_info_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_conn_ctx *conn, - struct sdap_id_op *op, - const char *dom_name); + struct tevent_context *ev, + struct sdap_options *opts, + struct sss_failover_ldap_connection *conn, + const char *dom_name); errno_t ad_domain_info_recv(struct tevent_req *req, diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c index 2c0653fd737..74adc1d3ef1 100644 --- a/src/providers/ad/ad_dyndns.c +++ b/src/providers/ad/ad_dyndns.c @@ -28,10 +28,13 @@ #include "providers/data_provider.h" #include "providers/be_dyndns.h" #include "providers/ad/ad_common.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" struct ad_dyndns_update_state { struct ad_options *ad_ctx; struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; }; static void @@ -129,7 +132,7 @@ ad_dyndns_update_send(TALLOC_CTX *mem_ctx, int ret; struct ad_options *ctx; struct ad_dyndns_update_state *state; - struct tevent_req *req, *subreq; + struct tevent_req *req; struct sdap_id_ctx *sdap_ctx; DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); @@ -154,21 +157,12 @@ ad_dyndns_update_send(TALLOC_CTX *mem_ctx, state->ad_ctx->dyndns_ctx->last_refresh = time(NULL); /* Make sure to have a valid LDAP connection */ - state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, sdap_ctx->fctx, req, + ad_dyndns_update_connect_done); + if (ret != EOK) { goto done; } - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret)); - ret = ENOMEM; - goto done; - } - tevent_req_set_callback(subreq, ad_dyndns_update_connect_done, req); ret = EOK; done: if (ret != EOK) { @@ -190,27 +184,26 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_dyndns_update_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + ctx = state->ad_ctx; sdap_ctx = ctx->id_ctx->sdap_id_ctx; - if (ret != EOK) { - if (be_is_offline(sdap_ctx->be)) { - DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " - "dynamic DNS update is skipped in offline mode.\n"); - tevent_req_error(req, ERR_DYNDNS_OFFLINE); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to LDAP server: [%d](%s)\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ERR_NETWORK_IO); - } - return; + if (be_is_offline(sdap_ctx->be)) { + DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " + "dynamic DNS update is skipped in offline mode.\n"); + tevent_req_error(req, ERR_DYNDNS_OFFLINE); } - ret = ldap_url_parse(ctx->service->sdap->uri, &lud); + ret = ldap_url_parse(state->conn->uri, &lud); if (ret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse ldap URI '%s': %d\n", ctx->service->sdap->uri, ret); diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index 20052c2f356..fa0caf886f7 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -148,9 +148,8 @@ enum ace_eval_agp_status { struct tevent_req *ad_gpo_process_som_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ldap_connection *conn, struct ldb_context *ldb_ctx, - struct sdap_id_op *sdap_op, struct sdap_options *opts, struct dp_option *ad_options, int timeout, @@ -163,8 +162,8 @@ int ad_gpo_process_som_recv(struct tevent_req *req, struct tevent_req * ad_gpo_process_gpo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_id_op *sdap_op, struct sdap_options *opts, + struct sss_failover_ldap_connection *conn, char *server_hostname, struct sss_domain_info *host_domain, struct ad_access_ctx *access_ctx, @@ -1913,12 +1912,13 @@ struct ad_gpo_access_state { struct tevent_context *ev; struct ldb_context *ldb_ctx; struct ad_access_ctx *access_ctx; + struct sss_failover_ctx *fctx; enum gpo_access_control_mode gpo_mode; bool gpo_implicit_deny; enum gpo_map_type gpo_map_type; - struct sdap_id_conn_ctx *conn; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; char *server_hostname; + const char *service; struct sdap_options *opts; int timeout; struct sss_domain_info *user_domain; @@ -1953,11 +1953,11 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sss_domain_info *domain, struct ad_access_ctx *ctx, + struct sss_failover_ctx *fctx, const char *user, const char *service) { struct tevent_req *req; - struct tevent_req *subreq; struct ad_gpo_access_state *state; errno_t ret; int hret; @@ -2049,15 +2049,10 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, state->gpo_implicit_deny = dp_opt_get_bool(ctx->ad_options, AD_GPO_IMPLICIT_DENY); state->access_ctx = ctx; + state->fctx = fctx; + state->service = service; state->opts = ctx->sdap_access_ctx->id_ctx->opts; state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT); - state->conn = ad_get_dom_ldap_conn(ctx->ad_id_ctx, state->host_domain); - state->sdap_op = sdap_id_op_create(state, state->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n"); - ret = ENOMEM; - goto immediately; - } ret = sss_hash_create(state, 0, &state->allow_maps); if (ret != EOK) { @@ -2073,14 +2068,11 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, goto immediately; } - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret)); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + ad_gpo_connect_done); + if (ret != EOK) { goto immediately; } - tevent_req_set_callback(subreq, ad_gpo_connect_done, req); return req; @@ -2144,41 +2136,41 @@ ad_gpo_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (!be_is_offline(state->conn->id_ctx->be)) { + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + + if (be_is_offline(state->access_ctx->sdap_access_ctx->id_ctx->be)) { + DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); + ret = process_offline_gpos(state, + state->user, + state->gpo_implicit_deny, + state->gpo_mode, + state->user_domain, + state->host_domain, + state->opts->idmap_ctx->map, + state->gpo_map_type); + + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "process_offline_gpos succeeded\n"); + tevent_req_done(req); + goto done; + } else { DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to AD server: [%d](%s)\n", + "process_offline_gpos failed [%d](%s)\n", ret, sss_strerror(ret)); goto done; - } else { - DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); - ret = process_offline_gpos(state, - state->user, - state->gpo_implicit_deny, - state->gpo_mode, - state->user_domain, - state->host_domain, - state->opts->idmap_ctx->map, - state->gpo_map_type); - - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_FUNC, "process_offline_gpos succeeded\n"); - tevent_req_done(req); - goto done; - } else { - DEBUG(SSSDBG_OP_FAILURE, - "process_offline_gpos failed [%d](%s)\n", - ret, sss_strerror(ret)); - goto done; - } } } /* extract server_hostname from server_uri */ - server_uri = state->conn->service->uri; + server_uri = state->conn->uri; ret = ldap_url_parse(server_uri, &lud); if (ret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -2255,7 +2247,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) subreq = groups_by_user_send(state, state->ev, state->access_ctx->ad_id_ctx->sdap_id_ctx, - sdom, + sdom, state->fctx, search_bases, state->host_fqdn, BE_FILTER_NAME, @@ -2392,7 +2384,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) state->ev, state->conn, state->ldb_ctx, - state->sdap_op, state->opts, state->access_ctx->ad_options, state->timeout, @@ -2438,8 +2429,8 @@ ad_gpo_process_som_done(struct tevent_req *subreq) subreq = ad_gpo_process_gpo_send(state, state->ev, - state->sdap_op, state->opts, + state->conn, state->server_hostname, state->host_domain, state->access_ctx, @@ -2490,14 +2481,7 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); - - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, - "Unable to get GPO list from server %s: [%d](%s)\n", - state->ad_hostname ? state->ad_hostname : "NULL", ret, sss_strerror(ret)); - goto done; - } else if (ret == ENOENT) { + if (ret == ENOENT) { DEBUG(SSSDBG_TRACE_FUNC, "No GPOs found that apply to this system.\n"); /* @@ -2528,6 +2512,11 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) } goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Unable to get GPO list from server %s: [%d](%s)\n", + state->ad_hostname ? state->ad_hostname : "NULL", ret, sss_strerror(ret)); + goto done; } ret = ad_gpo_filter_gpos_by_dacl(state, state->user, state->host_fqdn, @@ -3182,8 +3171,8 @@ ad_gpo_populate_gplink_list(TALLOC_CTX *mem_ctx, struct ad_gpo_process_som_state { struct tevent_context *ev; - struct sdap_id_op *sdap_op; struct sdap_options *opts; + struct sss_failover_ldap_connection *conn; struct dp_option *ad_options; int timeout; bool allow_enforced_only; @@ -3214,9 +3203,8 @@ static void ad_gpo_get_som_attrs_done(struct tevent_req *subreq); struct tevent_req * ad_gpo_process_som_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ldap_connection *conn, struct ldb_context *ldb_ctx, - struct sdap_id_op *sdap_op, struct sdap_options *opts, struct dp_option *ad_options, int timeout, @@ -3235,8 +3223,8 @@ ad_gpo_process_som_send(TALLOC_CTX *mem_ctx, } state->ev = ev; - state->sdap_op = sdap_op; state->opts = opts; + state->conn = conn; state->ad_options = ad_options; state->timeout = timeout; state->som_index = 0; @@ -3258,8 +3246,7 @@ ad_gpo_process_som_send(TALLOC_CTX *mem_ctx, goto immediately; } - subreq = ad_domain_info_send(state, state->ev, conn, - state->sdap_op, domain_name); + subreq = ad_domain_info_send(state, state->ev, state->opts, state->conn, domain_name); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "ad_domain_info_send failed.\n"); @@ -3343,7 +3330,7 @@ ad_gpo_site_name_retrieval_done(struct tevent_req *subreq) * retrieved at that point (see https://fedorahosted.org/sssd/ticket/2276) */ subreq = sdap_get_generic_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, NULL, 0, state->timeout, @@ -3376,8 +3363,6 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq) &reply_count, &reply); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret); - DEBUG(SSSDBG_OP_FAILURE, "Unable to get configNC: [%d](%s)\n", ret, sss_strerror(ret)); ret = ENOENT; @@ -3468,7 +3453,7 @@ ad_gpo_get_som_attrs_step(struct tevent_req *req) const char *som_dn = gp_som->som_dn; subreq = sdap_get_generic_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, som_dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, NULL, 0, state->timeout, @@ -3504,8 +3489,6 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret); - DEBUG(SSSDBG_OP_FAILURE, "Unable to get SOM attributes: [%d](%s)\n", ret, sss_strerror(ret)); @@ -4066,9 +4049,9 @@ static errno_t ad_gpo_parse_sd(TALLOC_CTX *mem_ctx, struct ad_gpo_process_gpo_state { struct ad_access_ctx *access_ctx; struct tevent_context *ev; - struct sdap_id_op *sdap_op; struct dp_option *ad_options; struct sdap_options *opts; + struct sss_failover_ldap_connection *conn; char *server_hostname; struct sss_domain_info *host_domain; int timeout; @@ -4092,8 +4075,8 @@ static void ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq); struct tevent_req * ad_gpo_process_gpo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_id_op *sdap_op, struct sdap_options *opts, + struct sss_failover_ldap_connection *conn, char *server_hostname, struct sss_domain_info *host_domain, struct ad_access_ctx *access_ctx, @@ -4111,9 +4094,9 @@ ad_gpo_process_gpo_send(TALLOC_CTX *mem_ctx, } state->ev = ev; - state->sdap_op = sdap_op; state->ad_options = access_ctx->ad_options; state->opts = opts; + state->conn = conn; state->server_hostname = server_hostname; state->host_domain = host_domain; state->access_ctx = access_ctx; @@ -4172,7 +4155,7 @@ ad_gpo_get_gpo_attrs_step(struct tevent_req *req) const char *gpo_dn = gp_gpo->gpo_dn; subreq = sdap_sd_search_send(state, state->ev, - state->opts, sdap_id_op_handle(state->sdap_op), + state->opts, state->conn->sh, gpo_dn, SECINFO_DACL, attrs, state->timeout); if (subreq == NULL) { @@ -4224,8 +4207,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->sdap_op, ret); - DEBUG(SSSDBG_OP_FAILURE, "Unable to get GPO attributes: [%d](%s)\n", ret, sss_strerror(ret)); @@ -4296,8 +4277,6 @@ ad_gpo_get_sd_referral_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { /* Terminate the sdap_id_op */ - ret = sdap_id_op_done(state->sdap_op, ret); - DEBUG(SSSDBG_OP_FAILURE, "Unable to get referred GPO attributes: [%d](%s)\n", ret, sss_strerror(ret)); @@ -4902,7 +4881,7 @@ struct ad_gpo_get_sd_referral_state { struct sdap_options *opts; struct sss_domain_info *host_domain; struct sss_domain_info *ref_domain; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sdap_id_op *ref_op; int timeout; char *gpo_dn; @@ -4927,7 +4906,6 @@ ad_gpo_get_sd_referral_send(TALLOC_CTX *mem_ctx, errno_t ret; struct tevent_req *req; struct ad_gpo_get_sd_referral_state *state; - struct tevent_req *subreq; LDAPURLDesc *lud = NULL; req = tevent_req_create(mem_ctx, &state, @@ -4976,31 +4954,12 @@ ad_gpo_get_sd_referral_send(TALLOC_CTX *mem_ctx, ldap_free_urldesc(lud); lud = NULL; - state->conn = ad_get_dom_ldap_conn(state->access_ctx->ad_id_ctx, - state->ref_domain); - if (!state->conn) { - DEBUG(SSSDBG_OP_FAILURE, - "No connection for %s\n", state->ref_domain->name); - ret = EINVAL; - goto done; - } - /* Start an ID operation for the referral */ - state->ref_op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->ref_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n"); - ret = ENOMEM; - goto done; - } - - /* Establish the sdap_id_op connection */ - subreq = sdap_id_op_connect_send(state->ref_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, sss_strerror(ret)); + ret = sss_failover_transaction_send(state, ev, access_ctx->fctx, req, + ad_gpo_get_sd_referral_conn_done); + if (ret != EOK) { goto done; } - tevent_req_set_callback(subreq, ad_gpo_get_sd_referral_conn_done, req); done: @@ -5026,20 +4985,13 @@ ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq) struct ad_gpo_get_sd_referral_state *state = tevent_req_data(req, struct ad_gpo_get_sd_referral_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (be_is_offline(state->conn->id_ctx->be)) { - DEBUG(SSSDBG_TRACE_FUNC, - "Backend is marked offline, retry later!\n"); - tevent_req_done(req); - } else { - DEBUG(SSSDBG_MINOR_FAILURE, - "Cross-realm GPO processing failed to connect to " \ - "referred LDAP server: (%d)[%s]\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); - } + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -5048,10 +5000,10 @@ ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq) * performing the smb connection. The GPO referral URL can't be directly used * because the user might have forced the DC to use (ad_server option) */ - ret = ldap_url_parse(state->conn->service->uri, &lud); + ret = ldap_url_parse(state->conn->uri, &lud); if (ret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse service URI (%s)!\n", - state->conn->service->uri); + state->conn->uri); tevent_req_error(req, EINVAL); return; } @@ -5065,7 +5017,7 @@ ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq) /* Request the referred GPO data */ subreq = sdap_sd_search_send(state, state->ev, state->opts, - sdap_id_op_handle(state->ref_op), + state->conn->sh, state->gpo_dn, SECINFO_DACL, attrs, @@ -5096,8 +5048,6 @@ ad_gpo_get_sd_referral_search_done(struct tevent_req *subreq) &num_refs, &refs); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->ref_op, ret); - DEBUG(SSSDBG_OP_FAILURE, "Unable to get GPO attributes: [%d](%s)\n", ret, sss_strerror(ret)); diff --git a/src/providers/ad/ad_gpo.h b/src/providers/ad/ad_gpo.h index 80237e5f3f9..76f1ee5446d 100644 --- a/src/providers/ad/ad_gpo.h +++ b/src/providers/ad/ad_gpo.h @@ -58,6 +58,7 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sss_domain_info *domain, struct ad_access_ctx *ctx, + struct sss_failover_ctx *fctx, const char *user, const char *service); diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index d5f7d24f1b5..49866f30da6 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -105,9 +105,11 @@ static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx, struct ad_handle_acct_info_state { struct dp_id_data *ar; struct sdap_id_ctx *ctx; + struct sss_failover_ctx *fctx; struct sdap_domain *sdom; struct ad_options *ad_options; bool using_pac; + bool retried; const char *err; }; @@ -120,7 +122,8 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *ctx, struct ad_options *ad_options, - struct sdap_domain *sdom) + struct sdap_domain *sdom, + struct sss_failover_ctx *fctx) { struct tevent_req *req; struct ad_handle_acct_info_state *state; @@ -136,6 +139,8 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, state->ctx = ctx; state->sdom = sdom; state->ad_options = ad_options; + state->fctx = fctx; + state->retried = false; /* Try to shortcut if this is ID or SID search and it belongs to * other domain range than is in ar->domain. */ @@ -192,6 +197,7 @@ ad_handle_acct_info_step(struct tevent_req *req) state->using_pac = true; subreq = ad_handle_pac_initgr_send(state, state->ctx->be, state->ar, state->ctx, + state->fctx, state->sdom, noexist_delete, msg); @@ -208,6 +214,7 @@ ad_handle_acct_info_step(struct tevent_req *req) if (subreq == NULL) { subreq = sdap_handle_acct_req_send(state, state->ctx->be, state->ar, state->ctx, + state->fctx, state->sdom, noexist_delete); if (subreq == NULL) { @@ -234,60 +241,36 @@ ad_handle_acct_info_done(struct tevent_req *subreq) } else { ret = sdap_handle_acct_req_recv(subreq, &err); } - if (ret == ERR_OFFLINE) { + talloc_zfree(subreq); + + if (ret != EOK && !state->retried) { /* This is a special case: GC does not work. * We need to Fall back to ldap */ - ret = ENOENT; - } - talloc_zfree(subreq); - if (ret != EOK) { - /* if GC was not used error should be set */ - state->err = err; - - goto fail; + state->retried = true; + state->fctx = state->ctx->fctx; + ret = ad_handle_acct_info_step(req); + if (ret != EAGAIN) { + goto done; + } } + done: if (ret == EOK) { tevent_req_done(req); - return; - } else if (ret != ENOENT) { - ret = EIO; - goto fail; - } - - /* Ret is only ENOENT now. Try the next connection */ - ret = ad_handle_acct_info_step(req); - if (ret != EAGAIN) { - /* No additional search in progress. Save the last - * error status, we'll be returning it. - */ - state->err = err; - - if (ret == EOK) { - /* No more connections */ - tevent_req_done(req); - } else { - goto fail; + } else { + if (IS_SUBDOMAIN(state->sdom->dom)) { + /* Deactivate subdomain on lookup errors instead of going + * offline completely. + * This is a stopgap, until our failover is per-domain, + * not per-backend. Unfortunately, we can't rewrite the error + * code on some reported codes only, because sdap_id_op code + * encapsulated the failover as well.. + */ + ret = ERR_SUBDOM_INACTIVE; } - return; - } - - /* Another lookup in progress */ - return; - -fail: - if (IS_SUBDOMAIN(state->sdom->dom)) { - /* Deactivate subdomain on lookup errors instead of going - * offline completely. - * This is a stopgap, until our failover is per-domain, - * not per-backend. Unfortunately, we can't rewrite the error - * code on some reported codes only, because sdap_id_op code - * encapsulated the failover as well.. - */ - ret = ERR_SUBDOM_INACTIVE; + tevent_req_error(req, ret); } - tevent_req_error(req, ret); return; } @@ -323,6 +306,7 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct sdap_id_ctx *sdap_id_ctx = NULL; + struct sss_failover_ctx *fctx = NULL; struct sdap_domain *sdom; errno_t ret; @@ -354,7 +338,8 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, } subreq = ad_handle_acct_info_send(state, data, sdap_id_ctx, - id_ctx->ad_options, sdom); + id_ctx->ad_options, sdom, + fctx); if (subreq == NULL) { ret = ENOMEM; goto immediately; @@ -490,7 +475,6 @@ errno_t ad_account_info_handler_recv(TALLOC_CTX *mem_ctx, } static errno_t ad_get_account_domain_prepare_search(struct tevent_req *req); -static errno_t ad_get_account_domain_connect_retry(struct tevent_req *req); static void ad_get_account_domain_connect_done(struct tevent_req *subreq); static void ad_get_account_domain_search(struct tevent_req *req); static void ad_get_account_domain_search_done(struct tevent_req *subreq); @@ -513,7 +497,7 @@ struct ad_get_account_domain_state { char *filter; const char **attrs; struct dp_reply_std reply; - struct sdap_id_op *op; + struct sss_failover_ldap_connection *conn; struct sysdb_attrs **objects; size_t count; @@ -621,9 +605,9 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx, goto immediately; } - ret = ad_get_account_domain_connect_retry(req); + ret = sss_failover_transaction_send(state, params->ev, id_ctx->gc_fctx, req, + ad_get_account_domain_connect_done); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Connection error"); goto immediately; } @@ -692,33 +676,20 @@ static errno_t ad_get_account_domain_prepare_search(struct tevent_req *req) return EOK; } -static errno_t ad_get_account_domain_connect_retry(struct tevent_req *req) -{ - struct ad_get_account_domain_state *state = tevent_req_data(req, - struct ad_get_account_domain_state); - struct tevent_req *subreq; - errno_t ret; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - return ENOMEM; - } - - tevent_req_set_callback(subreq, ad_get_account_domain_connect_done, req); - return ret; -} - static void ad_get_account_domain_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - errno_t ret; + struct ad_get_account_domain_state *state = tevent_req_data(subreq, + struct ad_get_account_domain_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -740,7 +711,7 @@ static void ad_get_account_domain_search(struct tevent_req *req) } subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts, - sdap_id_op_handle(state->op), + state->conn->sh, "", LDAP_SCOPE_SUBTREE, state->filter, diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h index f906f33a16f..6221e0149ac 100644 --- a/src/providers/ad/ad_id.h +++ b/src/providers/ad/ad_id.h @@ -47,7 +47,8 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, struct dp_id_data *ar, struct sdap_id_ctx *ctx, struct ad_options *ad_options, - struct sdap_domain *sdom); + struct sdap_domain *sdom, + struct sss_failover_ctx *fctx); errno_t ad_handle_acct_info_recv(struct tevent_req *req, const char **_err); diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c index bd255c3b8a1..922f8c97b41 100644 --- a/src/providers/ad/ad_pac.c +++ b/src/providers/ad/ad_pac.c @@ -228,6 +228,7 @@ errno_t ad_get_pac_data_from_user_entry(TALLOC_CTX *mem_ctx, struct ad_handle_pac_initgr_state { struct dp_id_data *ar; + struct sss_failover_ctx *fctx; const char *err; int dp_error; struct sdap_options *opts; @@ -246,6 +247,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, + struct sss_failover_ctx *fctx, struct sdap_domain *sdom, bool noexist_delete, struct ldb_message *msg) @@ -268,6 +270,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, } state->user_dom = sdom->dom; state->opts = id_ctx->opts; + state->fctx = fctx; /* The following variables are currently unused because no sub-request * returns any of them. But they are needed to allow the same signature as @@ -340,6 +343,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, /* download missing SIDs */ subreq = sdap_ad_resolve_sids_send(state, be_ctx->ev, id_ctx, + state->fctx, id_ctx->opts, sdom->dom, state->missing_sids); if (subreq == NULL) { diff --git a/src/providers/ad/ad_pac.h b/src/providers/ad/ad_pac.h index 1188fb3f3cc..5a57d5bee02 100644 --- a/src/providers/ad/ad_pac.h +++ b/src/providers/ad/ad_pac.h @@ -71,6 +71,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_id_data *ar, struct sdap_id_ctx *id_ctx, + struct sss_failover_ctx *fctx, struct sdap_domain *sdom, bool noexist_delete, struct ldb_message *msg); diff --git a/src/providers/ad/ad_resolver.c b/src/providers/ad/ad_resolver.c index 342837a3b7f..c5178bf08d2 100644 --- a/src/providers/ad/ad_resolver.c +++ b/src/providers/ad/ad_resolver.c @@ -25,6 +25,8 @@ #include "providers/ad/ad_resolver.h" #include "providers/ldap/sdap_async_resolver_enum.h" #include "providers/ldap/ldap_resolver_enum.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" static errno_t ad_resolver_setup_enumeration(struct be_ctx *be_ctx, @@ -220,7 +222,7 @@ ad_resolver_setup_tasks(struct be_ctx *be_ctx, struct ad_resolver_enum_state { struct ad_resolver_ctx *resolver_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct tevent_context *ev; const char *realm; @@ -240,7 +242,6 @@ ad_resolver_enumeration_send(TALLOC_CTX *mem_ctx, struct ad_resolver_enum_state *state; struct ad_resolver_ctx *ctx; struct tevent_req *req; - struct tevent_req *subreq; errno_t ret; struct sdap_id_ctx *sdap_id_ctx; @@ -270,20 +271,11 @@ ad_resolver_enumeration_send(TALLOC_CTX *mem_ctx, goto fail; } - state->sdap_op = sdap_id_op_create(state, sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n"); - ret = ENOMEM; - goto fail; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, strerror(ret)); + ret = sss_failover_transaction_send(state, ev, ctx->ad_id_ctx->fctx, req, + ad_resolver_enumeration_conn_done); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, ad_resolver_enumeration_conn_done, req); return req; @@ -303,29 +295,22 @@ ad_resolver_enumeration_conn_done(struct tevent_req *subreq) struct ad_resolver_enum_state *state = tevent_req_data(req, struct ad_resolver_enum_state); struct sdap_id_ctx *id_ctx = state->resolver_ctx->ad_id_ctx->sdap_id_ctx; - int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (be_is_offline(id_ctx->be)) { - DEBUG(SSSDBG_TRACE_FUNC, - "Backend is marked offline, retry later!\n"); - tevent_req_done(req); - } else { - DEBUG(SSSDBG_MINOR_FAILURE, - "Domain enumeration failed to connect to " \ - "LDAP server: (%d)[%s]\n", ret, strerror(ret)); - tevent_req_error(req, ret); - } + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - subreq = ad_domain_info_send(state, state->ev, id_ctx->conn, - state->sdap_op, state->sdom->dom->name); + subreq = ad_domain_info_send(state, state->ev, id_ctx->opts, state->conn, + state->sdom->dom->name); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "ad_domain_info_send failed.\n"); - tevent_req_error(req, ret); + tevent_req_error(req, ENOMEM); return; } tevent_req_set_callback(subreq, ad_resolver_enumeration_master_done, req); diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index 1042dc55352..da1d340c108 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -1104,10 +1104,9 @@ struct ad_get_slave_domain_state { struct sdap_idmap_ctx *idmap_ctx; struct sysdb_attrs *root_attrs; struct sdap_domain *root_sdom; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; }; -static errno_t ad_get_slave_domain_retry(struct tevent_req *req); static void ad_get_slave_domain_connect_done(struct tevent_req *subreq); static void ad_get_slave_domain_done(struct tevent_req *subreq); @@ -1143,19 +1142,12 @@ ad_get_slave_domain_send(TALLOC_CTX *mem_ctx, goto immediately; } - state->sdap_op = sdap_id_op_create(state, root_id_ctx->ldap_ctx->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, root_id_ctx->fctx, req, + ad_get_slave_domain_connect_done); + if (ret != EOK) { goto immediately; } - ret = ad_get_slave_domain_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } - immediately: if (ret == EOK) { tevent_req_done(req); @@ -1167,26 +1159,6 @@ ad_get_slave_domain_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t ad_get_slave_domain_retry(struct tevent_req *req) -{ - struct ad_get_slave_domain_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct ad_get_slave_domain_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed " - "[%d]: %s\n", ret, sss_strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, ad_get_slave_domain_connect_done, req); - - return EAGAIN; -} - static void ad_get_slave_domain_connect_done(struct tevent_req *subreq) { struct ad_get_slave_domain_state *state; @@ -1199,18 +1171,18 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_get_slave_domain_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " - "[%d]: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_search_bases_send(state, state->ev, state->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->root_sdom->search_bases, NULL, false, 0, SLAVE_DOMAIN_FILTER, attrs, NULL); @@ -1239,21 +1211,14 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq) ret = sdap_search_bases_recv(subreq, state, &reply_count, &reply); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup slave domain data " - "[%d]: %s\n", ret, sss_strerror(ret)); - /* We continue to finish sdap_id_op. */ - } - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { - /* retry */ - ret = ad_get_slave_domain_retry(req); - if (ret != EOK) { - goto done; - } - return; + if (ret == ERR_NO_MORE_SERVERS) { + ret = ERR_OFFLINE; + goto done; } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup slave domain data " + "[%d]: %s\n", ret, sss_strerror(ret)); + ret = ERR_SERVER_FAILURE; goto done; } @@ -1732,6 +1697,7 @@ static void ad_check_gc_usability_search_done(struct tevent_req *subreq); struct ad_check_gc_usability_state { struct sdap_options *sdap_opts; + struct sss_failover_ldap_connection *conn; const char *attrs[3]; @@ -1743,7 +1709,7 @@ ad_check_gc_usability_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct ad_options *ad_options, struct sdap_options *sdap_opts, - struct sdap_id_op *op, + struct sss_failover_ldap_connection *conn, const char *domain_name, const char *domain_sid) { @@ -1760,6 +1726,7 @@ ad_check_gc_usability_send(TALLOC_CTX *mem_ctx, return NULL; } state->sdap_opts = sdap_opts; + state->conn = conn; state->is_gc_usable = false; if (dp_opt_get_bool(ad_options->basic, AD_ENABLE_GC) == false) { @@ -1816,7 +1783,7 @@ ad_check_gc_usability_send(TALLOC_CTX *mem_ctx, subreq = sdap_get_generic_send(state, ev, state->sdap_opts, - sdap_id_op_handle(op), + state->conn->sh, state->sdap_opts->schema_basedn, LDAP_SCOPE_SUBTREE, filter, @@ -1938,14 +1905,13 @@ struct ad_subdomains_refresh_state { struct tevent_context *ev; struct be_ctx *be_ctx; struct ad_subdomains_ctx *sd_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct sdap_id_ctx *id_ctx; struct ad_options *ad_options; char *forest; }; -static errno_t ad_subdomains_refresh_retry(struct tevent_req *req); static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq); static void ad_subdomains_refresh_master_done(struct tevent_req *subreq); static void ad_subdomains_refresh_gc_check_done(struct tevent_req *subreq); @@ -1974,73 +1940,44 @@ ad_subdomains_refresh_send(TALLOC_CTX *mem_ctx, state->id_ctx = sd_ctx->sdap_id_ctx; state->ad_options = sd_ctx->ad_id_ctx->ad_options; - state->sdap_op = sdap_id_op_create(state, - sd_ctx->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, state->id_ctx->fctx, req, + ad_subdomains_refresh_connect_done); + if (ret != EOK) { goto immediately; } - ret = ad_subdomains_refresh_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } - immediately: if (ret == EOK) { tevent_req_done(req); } else { tevent_req_error(req, ret); } - tevent_req_post(req, ev); return req; } -static errno_t ad_subdomains_refresh_retry(struct tevent_req *req) -{ - struct ad_subdomains_refresh_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct ad_subdomains_refresh_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed " - "[%d]: %s\n", ret, sss_strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, ad_subdomains_refresh_connect_done, req); - - return EAGAIN; -} - static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq) { struct ad_subdomains_refresh_state *state; struct tevent_req *req; - errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_subdomains_refresh_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " - "[%d]: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } /* connect to the DC we are a member of */ - subreq = ad_domain_info_send(state, state->ev, state->id_ctx->conn, - state->sdap_op, state->sd_ctx->domain_name); + subreq = ad_domain_info_send(state, state->ev, + state->sd_ctx->ad_id_ctx->sdap_id_ctx->opts, + state->conn, state->sd_ctx->domain_name); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -2149,7 +2086,7 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq) state->ev, state->ad_options, state->id_ctx->opts, - state->sdap_op, + state->conn, state->be_ctx->domain->name, master_sid); if (subreq == NULL) { @@ -2228,7 +2165,7 @@ static void ad_subdomains_refresh_gc_check_done(struct tevent_req *subreq) } subreq = ad_get_root_domain_send(state, state->ev, ad_domain, state->forest, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sd_ctx); if (subreq == NULL) { tevent_req_error(req, ENOMEM); @@ -2260,20 +2197,6 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq) ret, sss_strerror(ret)); root_attrs = NULL; root_id_ctx = NULL; - /* We continue to finish sdap_id_op. */ - } - - /* We finish sdap_id_op here since we connect - * to forest root for slave domains. */ - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { - /* retry */ - ret = ad_subdomains_refresh_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { tevent_req_error(req, ret); return; } @@ -2493,7 +2416,7 @@ errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx, struct ad_check_domain_state { struct tevent_context *ev; struct be_ctx *be_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ldap_connection *conn; struct ad_id_ctx *dom_id_ctx; struct sdap_options *opts; @@ -2546,7 +2469,6 @@ ad_check_domain_send(TALLOC_CTX *mem_ctx, errno_t ret; uint32_t trust_type; struct tevent_req *req; - struct tevent_req *subreq; struct ad_check_domain_state *state; req = tevent_req_create(mem_ctx, &state, struct ad_check_domain_state); @@ -2614,24 +2536,12 @@ ad_check_domain_send(TALLOC_CTX *mem_ctx, ret = EINVAL; goto immediately; } - - state->sdap_op = sdap_id_op_create(state, - state->dom_id_ctx->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto immediately; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed " - "[%d]: %s\n", ret, sss_strerror(ret)); - goto immediately; + ret = sss_failover_transaction_send(state, ev, ad_id_ctx->fctx, req, + ad_check_domain_connect_done); + if (ret != EOK) { + goto immediately; } - tevent_req_set_callback(subreq, ad_check_domain_connect_done, req); - return req; immediately: @@ -2649,24 +2559,22 @@ static void ad_check_domain_connect_done(struct tevent_req *subreq) { struct tevent_req *req; struct ad_check_domain_state *state; - int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_check_domain_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " - "[%d]: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - subreq = ad_domain_info_send(state, state->ev, - state->dom_id_ctx->sdap_id_ctx->conn, - state->sdap_op, state->dom_name); + subreq = ad_domain_info_send(state, state->ev, state->opts, + state->conn, state->dom_name); tevent_req_set_callback(subreq, ad_check_domain_done, req); diff --git a/src/providers/ldap/ldap_access.c b/src/providers/ldap/ldap_access.c index b25d27a52c7..e833052a1e9 100644 --- a/src/providers/ldap/ldap_access.c +++ b/src/providers/ldap/ldap_access.c @@ -55,7 +55,8 @@ sdap_pam_access_handler_send(TALLOC_CTX *mem_ctx, state->pd = pd; subreq = sdap_access_send(state, params->ev, params->be_ctx, - params->domain, access_ctx, pd); + params->domain, access_ctx, + access_ctx->id_ctx->fctx, pd); if (subreq == NULL) { pd->pam_status = PAM_SYSTEM_ERR; goto immediately; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 933c1f838a6..6d2201dc937 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -81,6 +81,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, + struct sss_failover_ctx *fctx, const char *username, struct ldb_message *user_entry); @@ -109,6 +110,7 @@ struct sdap_access_req_ctx { struct tevent_context *ev; struct sdap_access_ctx *access_ctx; struct be_ctx *be_ctx; + struct sss_failover_ctx *fctx; struct sss_domain_info *domain; struct ldb_message *user_entry; size_t current_rule; @@ -125,6 +127,7 @@ sdap_access_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, + struct sss_failover_ctx *fctx, struct pam_data *pd) { errno_t ret; @@ -144,6 +147,7 @@ sdap_access_send(TALLOC_CTX *mem_ctx, state->pd = pd; state->ev = ev; state->access_ctx = access_ctx; + state->fctx = fctx; state->current_rule = 0; DEBUG(SSSDBG_TRACE_FUNC, @@ -256,6 +260,7 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state, subreq = sdap_access_filter_send(state, state->ev, state->be_ctx, state->domain, state->access_ctx, + state->fctx, state->pd->user, state->user_entry); if (subreq == NULL) { @@ -820,6 +825,7 @@ struct sdap_access_filter_req_ctx { struct sss_failover_ldap_connection *conn; struct sysdb_handle *handle; struct sss_domain_info *domain; + struct sss_failover_ctx *fctx; /* cached result of access control checks */ bool cached_access; const char *basedn; @@ -835,6 +841,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, + struct sss_failover_ctx *fctx, const char *username, struct ldb_message *user_entry) { @@ -861,6 +868,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, state->opts = access_ctx->id_ctx->opts; state->ev = ev; state->access_ctx = access_ctx; + state->fctx = fctx; state->domain = domain; DEBUG(SSSDBG_TRACE_FUNC, @@ -913,7 +921,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Checking filter against LDAP\n"); - ret = sss_failover_transaction_send(state, ev, access_ctx->id_ctx->fctx, req, + ret = sss_failover_transaction_send(state, ev, state->fctx, req, sdap_access_filter_connect_done); if (ret != EOK) { goto done; diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h index 0a57ebbc63a..ed59de67c02 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -100,6 +100,7 @@ sdap_access_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sss_domain_info *domain, struct sdap_access_ctx *access_ctx, + struct sss_failover_ctx *fctx, struct pam_data *pd); errno_t sdap_access_recv(struct tevent_req *req); diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 3f0b8f77984..ad1a701d1f8 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -164,7 +164,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct sdap_id_ctx *id_ctx, struct sdap_attr_map *user_map, size_t user_map_cnt, - struct sss_failover_ldap_connection *conn, + struct sss_failover_ctx *fctx, struct sdap_search_base **search_bases, const char *name, int filter_type, diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 23f5e65cc99..5facf7a6a00 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -3207,6 +3207,8 @@ errno_t sdap_ad_check_domain_local_groups(struct tevent_req *req) subreq = sdap_ad_get_domain_local_groups_send(state, state->ev, local_sdom, state->opts, state->sysdb, state->dom->parent, + state->id_ctx->fctx, + state->id_ctx->opts->sdom->group_search_bases, groups, res->count); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_get_domain_local_groups_send failed.\n"); diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index c7f1970ef64..3db5e5f9e9c 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -409,29 +409,18 @@ errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req) struct sdap_ad_tokengroups_initgr_mapping_state { struct tevent_context *ev; struct sdap_options *opts; - struct sdap_handle *sh; + struct sss_failover_ldap_connection *conn; struct sdap_idmap_ctx *idmap_ctx; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; const char *orig_dn; int timeout; const char *username; - - struct sdap_id_op *op; }; static void sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq); static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq); -static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_options *opts, - const char *orig_dn, - int timeout, - const char *username, - struct sdap_handle *sh, - struct tevent_req *req, - tevent_req_fn callback); static struct tevent_req * sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, @@ -439,16 +428,13 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, - struct sdap_handle *sh, + struct sss_failover_ctx *fctx, const char *name, const char *orig_dn, int timeout) { struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct sdap_domain *sdom; - struct ad_id_ctx *subdom_id_ctx; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -460,7 +446,6 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->opts = opts; - state->sh = sh; state->idmap_ctx = opts->idmap_ctx; state->sysdb = sysdb; state->domain = domain; @@ -472,38 +457,12 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, goto immediately; } - sdom = sdap_domain_get(opts, domain); - if (sdom == NULL || sdom->pvt == NULL) { - ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout, - state->username, sh, req, - sdap_ad_tokengroups_initgr_mapping_done); - if (ret == EOK) { - return req; - } else { - DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n", - domain->name); - goto immediately; - } - } - - subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto immediately; - } - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, fctx, req, + sdap_ad_tokengroups_initgr_mapping_connect_done); + if (ret != EOK) { goto immediately; } - tevent_req_set_callback(subreq, - sdap_ad_tokengroups_initgr_mapping_connect_done, - req); - return req; immediately: @@ -522,23 +481,23 @@ sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq) { struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; struct tevent_req *req = NULL; - int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state); - - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, - sdap_id_op_handle(state->op), + state->conn->sh, state->username, state->orig_dn, state->timeout); if (subreq == NULL) { @@ -753,16 +712,15 @@ static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req) struct sdap_ad_tokengroups_initgr_posix_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; - struct sdap_id_conn_ctx *conn; struct sdap_options *opts; - struct sdap_handle *sh; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; const char *orig_dn; int timeout; const char *username; - struct sdap_id_op *op; char **missing_sids; size_t num_missing_sids; char **cached_groups; @@ -781,20 +739,16 @@ static struct tevent_req * sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, - struct sdap_handle *sh, const char *name, const char *orig_dn, int timeout) { struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct sdap_domain *sdom; - struct ad_id_ctx *subdom_id_ctx; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -806,9 +760,8 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; - state->conn = conn; + state->fctx = fctx; state->opts = opts; - state->sh = sh; state->sysdb = sysdb; state->domain = domain; state->orig_dn = orig_dn; @@ -819,37 +772,12 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, goto immediately; } - sdom = sdap_domain_get(opts, domain); - if (sdom == NULL || sdom->pvt == NULL) { - ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout, - state->username, sh, req, - sdap_ad_tokengroups_initgr_posix_tg_done); - if (ret == EOK) { - return req; - } else { - DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n", - domain->name); - goto immediately; - } - } - subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto immediately; - } - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req, + sdap_ad_tokengroups_initgr_posix_sids_connect_done); + if (ret != EOK) { goto immediately; } - tevent_req_set_callback(subreq, - sdap_ad_tokengroups_initgr_posix_sids_connect_done, - req); - return req; immediately: @@ -868,23 +796,24 @@ sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq) { struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; struct tevent_req *req = NULL; - int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, - sdap_id_op_handle(state->op), + state->conn->sh, state->username, state->orig_dn, state->timeout); if (subreq == NULL) { @@ -1060,7 +989,7 @@ sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq) /* download missing SIDs */ subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx, - state->conn, + state->fctx, state->opts, state->domain, state->missing_sids); if (subreq == NULL) { @@ -1153,9 +1082,8 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req) struct sdap_ad_get_domain_local_groups_state { struct tevent_context *ev; - struct sdap_id_conn_ctx *conn; + struct sss_failover_ldap_connection *conn; struct sdap_options *opts; - struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *dom; @@ -1176,13 +1104,13 @@ sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *dom, + struct sss_failover_ctx *fctx, + struct sdap_search_base **search_bases, struct sysdb_attrs **groups, size_t num_groups) { struct sdap_ad_get_domain_local_groups_state *state; struct tevent_req *req; - struct tevent_req *subreq; - struct ad_id_ctx *ad_id_ctx; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -1193,12 +1121,10 @@ sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, } state->ev = ev; - ad_id_ctx = talloc_get_type(local_sdom->pvt, struct ad_id_ctx); - state->conn = ad_id_ctx->ldap_ctx; state->opts = opts; state->sysdb = sysdb; state->dom = dom; - state->search_bases = state->conn->id_ctx->opts->sdom->group_search_bases; + state->search_bases = search_bases; state->groups = groups; state->num_groups = num_groups; @@ -1208,22 +1134,12 @@ sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, goto fail; } - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (state->op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); + ret = sss_failover_transaction_send(state, ev, fctx, req, + sdap_ad_get_domain_local_groups_connect_done); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, - sdap_ad_get_domain_local_groups_connect_done, req); - return req; fail: @@ -1240,18 +1156,20 @@ sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq) struct tevent_req); struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, struct sdap_ad_get_domain_local_groups_state); - int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } + subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts, state->sysdb, state->dom, - sdap_id_op_handle(state->op), + state->conn->sh, state->search_bases, state->groups, state->num_groups, state->group_hash, 0); @@ -1565,6 +1483,7 @@ struct sdap_ad_tokengroups_initgroups_state { bool use_id_mapping; bool use_shortcut; struct sss_domain_info *domain; + struct sss_failover_ctx *fctx; }; static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq); @@ -1573,7 +1492,7 @@ struct tevent_req * sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, - struct sdap_id_conn_ctx *conn, + struct sss_failover_ctx *fctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, @@ -1598,6 +1517,7 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, state->use_id_mapping = use_id_mapping; state->domain = domain; + state->fctx = fctx; /* We can compute the gidNumber attribute from SIDs obtained from * the tokenGroups lookup in case ID mapping is used for a user from the @@ -1625,12 +1545,13 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, } if (state->use_shortcut) { subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts, - sysdb, domain, sh, + sysdb, domain, state->fctx, name, orig_dn, timeout); } else { - subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn, - opts, sysdb, domain, sh, + subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, + state->fctx, + opts, sysdb, domain, name, orig_dn, timeout); } @@ -1679,39 +1600,3 @@ errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req) return EOK; } - -static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_options *opts, - const char *orig_dn, - int timeout, - const char *username, - struct sdap_handle *sh, - struct tevent_req *req, - tevent_req_fn callback) -{ - struct tevent_req *subreq = NULL; - errno_t ret; - - if (sh != NULL) { - /* plain LDAP provider already has a sdap_handle */ - subreq = sdap_get_ad_tokengroups_send(mem_ctx, ev, opts, sh, username, - orig_dn, timeout); - if (subreq == NULL) { - ret = ENOMEM; - tevent_req_error(req, ret); - goto done; - } - - tevent_req_set_callback(subreq, callback, req); - ret = EOK; - goto done; - - } else { - ret = EINVAL; - goto done; - } - -done: - return ret; -} diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h index a02a133a89a..21d62366b58 100644 --- a/src/providers/ldap/sdap_async_private.h +++ b/src/providers/ldap/sdap_async_private.h @@ -199,6 +199,8 @@ sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *dom, + struct sss_failover_ctx *fctx, + struct sdap_search_base **search_bases, struct sysdb_attrs **groups, size_t num_groups); errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req); From b8b2c9a5eaacb18019c42943fc92c84d065fae32 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 8 Apr 2026 16:18:13 -0400 Subject: [PATCH 28/39] ad: Unset DPM_CHECK_ONLINE handler --- src/providers/ad/ad_init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index cab0d2f3a9b..11e737c94da 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -550,10 +550,6 @@ errno_t sssm_ad_id_init(TALLOC_CTX *mem_ctx, ad_account_info_handler_send, ad_account_info_handler_recv, id_ctx, struct ad_id_ctx, struct dp_id_data, struct dp_reply_std); - dp_set_method(dp_methods, DPM_CHECK_ONLINE, - sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx->sdap_id_ctx, - struct sdap_id_ctx, void, struct dp_reply_std); - dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, ad_get_account_domain_send, ad_get_account_domain_recv, id_ctx, struct ad_id_ctx, struct dp_get_acct_domain_data, struct dp_reply_std); From 1fcbfaf746cc7525d397b089c38681f22f12437f Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Fri, 24 Apr 2026 13:49:14 -0400 Subject: [PATCH 29/39] AD: Add GC usage logic function --- src/providers/ad/ad_id.c | 42 +++++++++++++++++++++++++++++++ src/providers/failover/failover.h | 2 ++ 2 files changed, 44 insertions(+) diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 49866f30da6..054ba612124 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -274,6 +274,42 @@ ad_handle_acct_info_done(struct tevent_req *subreq) return; } +struct sss_failover_ctx * +get_fctx_conn_method(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, + struct sss_domain_info *dom, struct dp_id_data *ar) +{ + + bool use_gc = false; + + switch (ar->entry_type & BE_REQ_TYPE_MASK) { + case BE_REQ_USER: /* user */ + /* Try GC first for users from trusted domains, but go to LDAP + * for users from non-trusted domains to get all POSIX attrs */ + if (IS_SUBDOMAIN(dom)) { + use_gc = true; + } + break; + case BE_REQ_BY_SECID: /* by SID */ + case BE_REQ_USER_AND_GROUP: /* get SID */ + case BE_REQ_GROUP: /* group */ + case BE_REQ_INITGROUPS: /* init groups for user */ + use_gc = true; + break; + default: + /* Requests for other object should only contact LDAP by default */ + break; + } + + if (!dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { + use_gc = false; + } + + ad_ctx->sdap_id_ctx->gc_fctx->no_mpg_user_fallback = use_gc; + ad_ctx->sdap_id_ctx->fctx->no_mpg_user_fallback = use_gc; + + return use_gc ? ad_ctx->sdap_id_ctx->gc_fctx : ad_ctx->sdap_id_ctx->fctx; +} + errno_t ad_handle_acct_info_recv(struct tevent_req *req, const char **_err) @@ -331,6 +367,12 @@ ad_account_info_send(TALLOC_CTX *mem_ctx, goto immediately; } + fctx = get_fctx_conn_method(state, id_ctx, domain, data); + if (fctx == NULL) { + ret = EIO; + goto immediately; + } + sdom = sdap_domain_get(sdap_id_ctx->opts, domain); if (sdom == NULL) { ret = EIO; diff --git a/src/providers/failover/failover.h b/src/providers/failover/failover.h index 91d34b2610b..4c1071d8f16 100644 --- a/src/providers/failover/failover.h +++ b/src/providers/failover/failover.h @@ -101,6 +101,8 @@ struct sss_failover_ctx { * connect to the server and the queue serializes the requests to ensure * that we establish only one connection that is then reused. */ struct tevent_queue *vtable_op_queue; + + bool no_mpg_user_fallback; }; /** From 90149eb6d19ffd5ad81f75f9f99be4267456b5ff Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Mon, 27 Apr 2026 10:03:39 -0400 Subject: [PATCH 30/39] AD: Switch to LDAP connection for groups membership data --- src/providers/ldap/ldap_id.c | 1 + src/providers/ldap/sdap_async.h | 1 + src/providers/ldap/sdap_async_enum.c | 1 + src/providers/ldap/sdap_async_groups.c | 47 ++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index 250395e47f1..e280ebde525 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -872,6 +872,7 @@ static void groups_get_search(struct tevent_req *req) subreq = sdap_get_groups_send(state, state->ev, state->sdom, state->ctx->opts, + state->ctx->fctx, state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index ad1a701d1f8..d7f78a7d7e9 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -103,6 +103,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_domain *sdom, struct sdap_options *opts, + struct sss_failover_ctx *fctx, struct sdap_handle *sh, const char **attrs, const char *filter, diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c index 4292f5ee43a..5f2da5422a7 100644 --- a/src/providers/ldap/sdap_async_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -608,6 +608,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, subreq = sdap_get_groups_send(state, state->ev, state->sdom, state->ctx->opts, + state->ctx->fctx, state->conn->sh, state->attrs, state->filter, dp_opt_get_int(state->ctx->opts->basic, diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 4af046d26eb..9c8092dc3c0 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -1699,6 +1699,8 @@ static int sdap_process_group_recv(struct tevent_req *req) struct sdap_get_groups_state { struct tevent_context *ev; struct sdap_options *opts; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sdap_handle *sh; struct sss_domain_info *dom; struct sdap_domain *sdom; @@ -1727,6 +1729,7 @@ struct sdap_get_groups_state { }; static errno_t sdap_get_groups_next_base(struct tevent_req *req); +static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq); static void sdap_get_groups_process(struct tevent_req *subreq); static void sdap_get_groups_done(struct tevent_req *subreq); @@ -1734,6 +1737,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_domain *sdom, struct sdap_options *opts, + struct sss_failover_ctx *fctx, struct sdap_handle *sh, const char **attrs, const char *filter, @@ -1750,6 +1754,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, state->ev = ev; state->opts = opts; + state->fctx = fctx; state->sdom = sdom; state->dom = sdom->dom; state->sh = sh; @@ -1772,6 +1777,19 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, goto done; } + /* With AD by default the Global Catalog is used for lookup. But the GC + * group object might not have full group membership data. To make sure we + * connect to an LDAP server of the group's domain. */ + if (state->opts->schema_type == SDAP_SCHEMA_AD) { + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + sdap_get_groups_ldap_connect_done); + if (ret != EOK) { + goto done; + } + + return req; + } + ret = sdap_get_groups_next_base(req); done: @@ -1783,6 +1801,35 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, return req; } +static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_get_groups_state *state; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_get_groups_state); + + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + + state->ldap_sh = state->conn->sh; + + ret = sdap_get_groups_next_base(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } + + return; +} + static errno_t sdap_get_groups_next_base(struct tevent_req *req) { struct tevent_req *subreq; From ecb0c6c75163199bb8d8c3f4e13ec206e212cb01 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Tue, 28 Apr 2026 11:33:05 -0400 Subject: [PATCH 31/39] gpo: move offline processing for new failover After switching to new failover code, processing offline gpos function was no longer reached if backend is offline during AD access checks. --- src/providers/ad/ad_access.c | 25 ++++++++++++++++++++++++- src/providers/ad/ad_gpo.c | 25 +------------------------ src/providers/ad/ad_gpo.h | 11 +++++++++++ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c index ddb161df633..72a79911d93 100644 --- a/src/providers/ad/ad_access.c +++ b/src/providers/ad/ad_access.c @@ -30,6 +30,7 @@ #include "providers/ad/ad_gpo.h" #include "src/providers/ad/ad_common.h" #include "src/providers/ldap/sdap_access.h" +#include "providers/ldap/sdap_idmap.h" /* * More advanced format can be used to restrict the filter to a specific @@ -418,7 +419,29 @@ ad_gpo_access_done(struct tevent_req *subreq) } else { DEBUG(SSSDBG_OP_FAILURE, "GPO-based access control failed.\n"); if (mode == GPO_ACCESS_CONTROL_ENFORCING) { - tevent_req_error(req, ret); + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); + ret = process_offline_gpos(state, + state->pd->user, + dp_opt_get_bool(state->ctx->ad_options, AD_GPO_IMPLICIT_DENY), + mode, + state->domain, + get_domains_head(state->domain), + state->ctx->sdap_access_ctx->id_ctx->opts->idmap_ctx->map, + GPO_MAP_INTERACTIVE); + + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "process_offline_gpos succeeded.\n"); + tevent_req_done(req); + } else { + DEBUG(SSSDBG_OP_FAILURE, + "process_offline_gpos failed [%d](%s).\n", + ret, sss_strerror(ret)); + tevent_req_error(req, ret); + } + } else { + tevent_req_error(req, ret); + } } else { DEBUG(SSSDBG_OP_FAILURE, "Ignoring error: [%d](%s); GPO-based access control failed, " diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index fa0caf886f7..4dac2c206c1 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -2088,7 +2088,7 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t +errno_t process_offline_gpos(TALLOC_CTX *mem_ctx, const char *user, bool gpo_implicit_deny, @@ -2146,29 +2146,6 @@ ad_gpo_connect_done(struct tevent_req *subreq) return; } - if (be_is_offline(state->access_ctx->sdap_access_ctx->id_ctx->be)) { - DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); - ret = process_offline_gpos(state, - state->user, - state->gpo_implicit_deny, - state->gpo_mode, - state->user_domain, - state->host_domain, - state->opts->idmap_ctx->map, - state->gpo_map_type); - - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_FUNC, "process_offline_gpos succeeded\n"); - tevent_req_done(req); - goto done; - } else { - DEBUG(SSSDBG_OP_FAILURE, - "process_offline_gpos failed [%d](%s)\n", - ret, sss_strerror(ret)); - goto done; - } - } - /* extract server_hostname from server_uri */ server_uri = state->conn->uri; ret = ldap_url_parse(server_uri, &lud); diff --git a/src/providers/ad/ad_gpo.h b/src/providers/ad/ad_gpo.h index 76f1ee5446d..4ec2b87560f 100644 --- a/src/providers/ad/ad_gpo.h +++ b/src/providers/ad/ad_gpo.h @@ -24,6 +24,7 @@ #define AD_GPO_H_ #include "providers/ad/ad_access.h" +#include "lib/idmap/sss_idmap.h" #define AD_GPO_CHILD_OUT_FILENO 3 @@ -64,4 +65,14 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, errno_t ad_gpo_access_recv(struct tevent_req *req); +errno_t +process_offline_gpos(TALLOC_CTX *mem_ctx, + const char *user, + bool gpo_implicit_deny, + enum gpo_access_control_mode gpo_mode, + struct sss_domain_info *user_domain, + struct sss_domain_info *host_domain, + struct sss_idmap_ctx *idmap_ctx, + enum gpo_map_type gpo_map_type); + #endif /* AD_GPO_H_ */ From 0bd9ae624f981b0a91dc20e7e50ffc8e57da220e Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 6 May 2026 14:33:25 -0400 Subject: [PATCH 32/39] ipa: remove no longer needed connection logic --- src/providers/ipa/ipa_subdomains_id.c | 43 --------------------------- 1 file changed, 43 deletions(-) diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index 8f373f19cef..574062bb929 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -708,49 +708,6 @@ int ipa_get_subdom_acct_recv(struct tevent_req *req) static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, struct sss_domain_info *dom); -static struct sdap_id_conn_ctx ** -ipa_ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *ipa_ctx, - struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom) -{ - struct ad_id_ctx *forest_root_ad_id_ctx; - struct sdap_id_conn_ctx **clist; - int cindex = 0; - - /* While creating the domains and sub-domains each domain gets a global - * catalog services assigned but only one should be used because the - * global catalog is by definition responsible for the whole forest so it - * does not make sense to use a global catalog service for each domain and - * in the worst case connect to the same GC multiple times. - * - * In the AD provider this is simple because the GC service of the - * configured domain AD_GC_SERVICE_NAME ("AD_GC") can be used. In the IPA - * case all domains from the trusted forest are on the level of - * sub-domains so we have to pick one. Since the forest root is linked - * from all domain of the same forest it will be the most straight forward - * choice. */ - forest_root_ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, dom->forest_root); - if (forest_root_ad_id_ctx == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "Missing ad_id_ctx for forest root.\n"); - return NULL; - } - - clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3); - if (clist == NULL) return NULL; - - /* Always try GC first */ - if (dp_opt_get_bool(forest_root_ad_id_ctx->ad_options->basic, - AD_ENABLE_GC)) { - clist[cindex] = forest_root_ad_id_ctx->gc_ctx; - clist[cindex]->ignore_mark_offline = true; - clist[cindex]->no_mpg_user_fallback = true; - cindex++; - } - - clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); - - return clist; -} - /* IPA lookup for server mode. AD or IPA subdomain */ struct ipa_get_acct_state { struct tevent_context *ev; From 480118220bfbb75152c0b5ca9011418b258b7577 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 6 May 2026 14:43:01 -0400 Subject: [PATCH 33/39] ipa: Add ipa subdomain GC usage logic function --- src/providers/ipa/ipa_subdomains_id.c | 52 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index 574062bb929..f5134602f4d 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -705,6 +705,35 @@ int ipa_get_subdom_acct_recv(struct tevent_req *req) return EOK; } +struct sss_failover_ctx * +get_ad_fctx_conn_method(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, + struct dp_id_data *ar) +{ + + bool use_gc = false; + + /* We read users and groups from GC. From groups, we may switch to + * using LDAP connection in the group request itself, but in order + * to resolve Universal group memberships, we also need the GC + * connection + */ + switch (ar->entry_type & BE_REQ_TYPE_MASK) { + case BE_REQ_INITGROUPS: + case BE_REQ_BY_SECID: + case BE_REQ_GROUP: + use_gc = true; + break; + default: + break; + } + + if (!dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { + use_gc = false; + } + + return use_gc ? ad_ctx->sdap_id_ctx->gc_fctx : ad_ctx->sdap_id_ctx->fctx; +} + static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, struct sss_domain_info *dom); @@ -743,6 +772,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, struct tevent_req *subreq; struct ipa_get_acct_state *state; struct sdap_domain *sdom; + struct sss_failover_ctx *fctx; struct sdap_id_conn_ctx **clist; struct sdap_id_ctx *sdap_id_ctx; struct ad_id_ctx *ad_id_ctx; @@ -773,25 +803,9 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, } sdap_id_ctx = ad_id_ctx->sdap_id_ctx; - /* We read users and groups from GC. From groups, we may switch to - * using LDAP connection in the group request itself, but in order - * to resolve Universal group memberships, we also need the GC - * connection - */ - switch (state->ar->entry_type & BE_REQ_TYPE_MASK) { - case BE_REQ_INITGROUPS: - case BE_REQ_BY_SECID: - case BE_REQ_GROUP: - clist = ipa_ad_gc_conn_list(req, ipa_ctx, ad_id_ctx, state->obj_dom); - break; - default: - clist = ad_ldap_conn_list(req, ad_id_ctx, state->obj_dom); - break; - } - - if (clist == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "Cannot generate AD connection list!\n"); - ret = ENOMEM; + fctx = get_ad_fctx_conn_method(req, ad_id_ctx, state->ar); + if (fctx == NULL) { + ret = EIO; goto fail; } From cd418add0ffe2b91359cc9221eb627d93951291e Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Fri, 8 May 2026 16:04:44 -0400 Subject: [PATCH 34/39] ipa: Initialize new failover --- Makefile.am | 1 + src/providers/ipa/ipa_access.h | 1 + src/providers/ipa/ipa_common.h | 1 + src/providers/ipa/ipa_init.c | 117 ++++++++++++++++++++-- src/providers/ipa/ipa_subdomains_server.c | 26 +++++ 5 files changed, 139 insertions(+), 7 deletions(-) diff --git a/Makefile.am b/Makefile.am index ecdf8eda6f1..3445f28ec2b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4628,6 +4628,7 @@ libsss_ipa_la_SOURCES = \ src/providers/ad/ad_srv.c \ src/providers/ad/ad_domain_info.c \ src/providers/ad/ad_cldap_ping.c \ + $(SSSD_NEW_FAILOVER_OBJ) \ $(NULL) libsss_ipa_la_CFLAGS = \ $(AM_CFLAGS) \ diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h index 9cec0d1063f..2deccdffbea 100644 --- a/src/providers/ipa/ipa_access.h +++ b/src/providers/ipa/ipa_access.h @@ -35,6 +35,7 @@ enum ipa_access_mode { struct ipa_access_ctx { struct sdap_id_ctx *sdap_ctx; struct dp_option *ipa_options; + struct sss_failover_ctx *fctx; time_t last_update; struct sdap_access_ctx *sdap_access_ctx; diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 2a8259828ea..c5fa3825842 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -205,6 +205,7 @@ struct ipa_auth_ctx { struct ipa_id_ctx { struct sdap_id_ctx *sdap_id_ctx; struct ipa_options *ipa_options; + struct sss_failover_ctx *fctx; char *view_name; /* Only used with server mode */ diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index 9a58a96d0b6..829ac9b5db6 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -42,6 +42,9 @@ #include "providers/be_dyndns.h" #include "providers/ipa/ipa_session.h" #include "providers/ipa/ipa_opts.h" +#include "providers/failover/failover.h" +#include "providers/failover/failover_vtable.h" +#include "providers/failover/ldap/failover_ldap.h" #define DNS_SRV_MISCONFIGURATION "SRV discovery is enabled on the IPA " \ "server while using custom dns_discovery_domain. DNS discovery of " \ @@ -56,6 +59,7 @@ struct ipa_init_ctx { struct ipa_options *options; struct ipa_id_ctx *id_ctx; struct ipa_auth_ctx *auth_ctx; + struct sss_failover_ctx *fctx; }; @@ -104,6 +108,93 @@ static bool srv_in_server_list(const char *servers) return has_srv; } +static struct sss_failover_ctx * +sssm_ipa_init_failover(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + struct sdap_options *opts, + const char *service, + uint16_t port) +{ + struct sss_failover_ctx *fctx; + struct sss_failover_group *group; + struct sss_failover_server *server; + errno_t ret; + + /* Setup new failover. */ + fctx = sss_failover_init(mem_ctx, be_ctx->ev, service, + be_ctx->be_res->resolv, + be_ctx->be_res->family_order); + if (fctx == NULL) { + return NULL; + } + + /* Add primary servers */ + group = sss_failover_group_new(fctx, "primary"); + if (group == NULL) { + ret = ENOMEM; + goto done; + } + + server = sss_failover_server_new(fctx, "fake_1.ipa.test", + "ldap://fake_1.ipa.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "fake_2.ipa.test", + "ldap://fake_2.ipa.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + server = sss_failover_server_new(fctx, "master.ipa.test", + "ldap://master.ipa.test", port, 1, 1); + if (server == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_failover_group_add_server(group, server); + if (ret != EOK) { + goto done; + } + + /* kinit ctx needs to be set to call kinit vtable functions */ + fctx->kinit_ctx = fctx; + + sss_failover_vtable_set_kinit(fctx, + sss_failover_ldap_kinit_send, + sss_failover_ldap_kinit_recv, + opts); + + sss_failover_vtable_set_connect(fctx, + sss_failover_ldap_connect_send, + sss_failover_ldap_connect_recv, + opts); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(fctx); + return NULL; + } + + return fctx; +} + static errno_t ipa_init_options(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options **_ipa_options) @@ -215,7 +306,9 @@ static errno_t ipa_init_id_ctx(TALLOC_CTX *mem_ctx, static errno_t ipa_init_dyndns(struct be_ctx *be_ctx, - struct ipa_options *ipa_options) + struct ipa_options *ipa_options, + struct sdap_id_ctx *sdap_id_ctx) + { bool enabled; errno_t ret; @@ -253,7 +346,7 @@ static errno_t ipa_init_dyndns(struct be_ctx *be_ctx, DEBUG(SSSDBG_CONF_SETTINGS, "nsupdate is available\n"); - ret = ipa_dyndns_init(be_ctx, ipa_options); + ret = ipa_dyndns_init(be_ctx, ipa_options, sdap_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Failure setting up automatic DNS update\n"); @@ -552,7 +645,7 @@ static errno_t ipa_init_misc(struct be_ctx *be_ctx, "ipa_hostname is not Fully Qualified Domain Name.\n"); } - ret = ipa_init_dyndns(be_ctx, ipa_options); + ret = ipa_init_dyndns(be_ctx, ipa_options, sdap_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init dyndns [%d]: %s\n", ret, sss_strerror(ret)); @@ -679,6 +772,19 @@ errno_t sssm_ipa_init(TALLOC_CTX *mem_ctx, } } + /* Setup new failover. */ + init_ctx->fctx = sssm_ipa_init_failover(init_ctx, be_ctx, + init_ctx->id_ctx->sdap_id_ctx->opts, + "IPA", 389); + if (init_ctx->fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + ret = ENOMEM; + goto done; + } + + init_ctx->id_ctx->fctx = init_ctx->fctx; + init_ctx->id_ctx->sdap_id_ctx->fctx = init_ctx->fctx; + *_module_data = init_ctx; ret = EOK; @@ -706,10 +812,6 @@ errno_t sssm_ipa_id_init(TALLOC_CTX *mem_ctx, ipa_account_info_handler_send, ipa_account_info_handler_recv, id_ctx, struct ipa_id_ctx, struct dp_id_data, struct dp_reply_std); - dp_set_method(dp_methods, DPM_CHECK_ONLINE, - sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx->sdap_id_ctx, - struct sdap_id_ctx, void, struct dp_reply_std); - dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, default_account_domain_send, default_account_domain_recv, NULL, void, struct dp_get_acct_domain_data, struct dp_reply_std); @@ -763,6 +865,7 @@ errno_t sssm_ipa_access_init(TALLOC_CTX *mem_ctx, } access_ctx->sdap_ctx = id_ctx->sdap_id_ctx; + access_ctx->fctx = init_ctx->fctx; access_ctx->host_map = id_ctx->ipa_options->id->host_map; access_ctx->hostgroup_map = id_ctx->ipa_options->hostgroup_map; access_ctx->host_search_bases = id_ctx->ipa_options->id->sdom->host_search_bases; diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c index 2d846240bbb..f8e0c027b34 100644 --- a/src/providers/ipa/ipa_subdomains_server.c +++ b/src/providers/ipa/ipa_subdomains_server.c @@ -431,6 +431,8 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, const char *gc_service_name; const char *service_name; struct ad_srv_plugin_ctx *srv_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ctx *gc_fctx; const char *ad_domain; const char *ad_site_override; const char *ad_servers; @@ -585,6 +587,30 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, ad_id_ctx->sdap_id_ctx->opts->sdap_certmap_ctx = id_ctx->sdap_id_ctx->opts->sdap_certmap_ctx; + /* Setup new failover. */ + fctx = ad_init_failover(be_ctx, be_ctx, + ad_id_ctx->sdap_id_ctx->opts, + "AD", 389); + if (fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + talloc_free(ad_options); + return ENOMEM; + } + + gc_fctx = ad_init_failover(be_ctx, be_ctx, + ad_id_ctx->sdap_id_ctx->opts, + "AD_GC", 3268); + if (gc_fctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n"); + talloc_free(ad_options); + return ENOMEM; + } + + ad_id_ctx->sdap_id_ctx->fctx = fctx; + ad_id_ctx->sdap_id_ctx->gc_fctx = gc_fctx; + ad_id_ctx->fctx = fctx; + ad_id_ctx->gc_fctx = gc_fctx; + *_ad_id_ctx = ad_id_ctx; return EOK; } From 12612894d8574f0611740a4d2fed9583c01fef62 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Fri, 8 May 2026 16:04:56 -0400 Subject: [PATCH 35/39] ipa: Port to new failover --- src/providers/ipa/ipa_access.c | 95 +++++---------- src/providers/ipa/ipa_auth.c | 66 +++++----- src/providers/ipa/ipa_common.c | 10 +- src/providers/ipa/ipa_common.h | 2 +- src/providers/ipa/ipa_dyndns.c | 57 ++++----- src/providers/ipa/ipa_dyndns.h | 3 +- src/providers/ipa/ipa_id.c | 96 +++++---------- src/providers/ipa/ipa_init.c | 2 +- src/providers/ipa/ipa_selinux.c | 59 ++++----- src/providers/ipa/ipa_session.c | 67 +++------- src/providers/ipa/ipa_subdomains.c | 91 +++++--------- src/providers/ipa/ipa_subdomains_ext_groups.c | 89 ++++++-------- src/providers/ipa/ipa_subdomains_id.c | 114 ++++++------------ src/providers/ipa/ipa_sudo_async.c | 77 ++++-------- src/providers/ipa/ipa_views.c | 52 +++----- 15 files changed, 312 insertions(+), 568 deletions(-) diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index a9855113af4..c09cb6266e2 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -86,7 +86,8 @@ struct ipa_fetch_hbac_state { struct be_ctx *be_ctx; struct sdap_id_ctx *sdap_ctx; struct ipa_access_ctx *access_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct dp_option *ipa_options; struct sdap_search_base **search_bases; @@ -102,7 +103,6 @@ struct ipa_fetch_hbac_state { struct ipa_common_entries *services; }; -static errno_t ipa_fetch_hbac_retry(struct tevent_req *req); static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq); static errno_t ipa_fetch_hbac_hostinfo(struct tevent_req *req); static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq); @@ -118,7 +118,7 @@ ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx, struct ipa_fetch_hbac_state *state; struct tevent_req *req; time_t now, refresh_interval; - bool offline; + bool offline = false; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -132,6 +132,7 @@ ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx, state->be_ctx = be_ctx; state->access_ctx = access_ctx; state->sdap_ctx = access_ctx->sdap_ctx; + state->fctx = access_ctx->fctx; state->ipa_options = access_ctx->ipa_options; state->search_bases = access_ctx->hbac_search_bases; state->hosts = talloc_zero(state, struct ipa_common_entries); @@ -156,14 +157,16 @@ ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx, goto immediately; } - state->sdap_op = sdap_id_op_create(state, state->sdap_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; + ret = sss_failover_transaction_send(state,state->ev, state->fctx, req, + ipa_fetch_hbac_connect_done); + if (ret != EOK) { goto immediately; } - offline = be_is_offline(be_ctx); + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + offline = true; + } + DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n", offline ? "offline" : "online"); @@ -176,11 +179,6 @@ ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx, goto immediately; } - ret = ipa_fetch_hbac_retry(req); - if (ret != EAGAIN) { - goto immediately; - } - return req; immediately: @@ -194,26 +192,6 @@ ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t ipa_fetch_hbac_retry(struct tevent_req *req) -{ - struct ipa_fetch_hbac_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct ipa_fetch_hbac_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: " - "%d(%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, ipa_fetch_hbac_connect_done, req); - - return EAGAIN; -} - static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; @@ -223,13 +201,18 @@ static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_fetch_hbac_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); + talloc_zfree(subreq); - if (ret != EOK) { - goto done; + + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; } - if (be_is_offline(state->be_ctx)) { + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { ret = EOK; goto done; } @@ -275,7 +258,7 @@ static errno_t ipa_fetch_hbac_hostinfo(struct tevent_req *req) } subreq = ipa_host_info_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, hostname, state->access_ctx->host_map, state->access_ctx->hostgroup_map, @@ -308,25 +291,12 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - /* Only call sdap_id_op_done in case of an error to trigger a - * failover. In general changing the tevent_req layout would be better - * so that all searches are in another sub-request so that we can - * error out at any step and the parent request can call - * sdap_id_op_done just once. */ - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { - /* retry */ - ret = ipa_fetch_hbac_retry(req); - if (ret != EAGAIN) { - goto done; - } - return; - } - goto done; + tevent_req_error(req, ERR_SERVER_FAILURE); + return; } subreq = ipa_hbac_service_info_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, state->search_bases); if (subreq == NULL) { @@ -379,7 +349,7 @@ static void ipa_fetch_hbac_services_done(struct tevent_req *subreq) } subreq = ipa_hbac_rule_info_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, state->search_bases, state->ipa_host); @@ -417,7 +387,6 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq) state->rules->entry_subdir = HBAC_RULES_SUBDIR; talloc_zfree(subreq); if (ret == ENOENT) { - /* Set ret to EOK so we can safely call sdap_id_op_done. */ found = false; ret = EOK; } else if (ret == EOK) { @@ -426,17 +395,9 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq) goto done; } - ret = sdap_id_op_done(state->sdap_op, ret); if (ret != EOK) { - /* retry */ - ret = ipa_fetch_hbac_retry(req); - if (ret != EAGAIN) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { - tevent_req_error(req, ret); - return; + ret = ERR_SERVER_FAILURE; + goto done; } if (found == false) { @@ -591,7 +552,7 @@ ipa_pam_access_handler_send(TALLOC_CTX *mem_ctx, subreq = sdap_access_send(state, params->ev, params->be_ctx, params->domain, access_ctx->sdap_access_ctx, - access_ctx->sdap_ctx->conn, pd); + access_ctx->fctx, pd); if (subreq == NULL) { state->pd->pam_status = PAM_SYSTEM_ERR; goto immediately; diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 3399d82d448..727c3d1b12f 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -34,8 +34,9 @@ struct get_password_migration_flag_state { struct tevent_context *ev; - struct sdap_id_op *sdap_op; struct sdap_id_ctx *sdap_id_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct fo_server *srv; char *ipa_realm; bool password_migration; @@ -50,7 +51,7 @@ static struct tevent_req *get_password_migration_flag_send(TALLOC_CTX *memctx, char *ipa_realm) { int ret; - struct tevent_req *req, *subreq; + struct tevent_req *req; struct get_password_migration_flag_state *state; if (sdap_id_ctx == NULL || ipa_realm == NULL) { @@ -67,26 +68,17 @@ static struct tevent_req *get_password_migration_flag_send(TALLOC_CTX *memctx, state->ev = ev; state->sdap_id_ctx = sdap_id_ctx; + state->fctx = sdap_id_ctx->fctx; state->srv = NULL; state->password_migration = false; state->ipa_realm = ipa_realm; - state->sdap_op = sdap_id_op_create(state, - state->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n"); - goto fail; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, strerror(ret)); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + get_password_migration_flag_auth_done); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, get_password_migration_flag_auth_done, req); - return req; fail: @@ -101,27 +93,28 @@ static void get_password_migration_flag_auth_done(struct tevent_req *subreq) struct get_password_migration_flag_state *state = tevent_req_data(req, struct get_password_migration_flag_state); static const char *attrs[] = {IPA_CONFIG_MIGRATION_ENABLED, NULL}; - int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret) { - if (be_is_offline(state->sdap_id_ctx->be)) { - DEBUG(SSSDBG_MINOR_FAILURE, - "No IPA server is available, cannot get the " - "migration flag while offline\n"); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to IPA server: [%d](%s)\n", - ret, strerror(ret)); - } - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, + "No IPA server is available, cannot get the " + "migration flag while offline\n"); + + tevent_req_error(req, ERR_SERVER_FAILURE); return; } subreq = ipa_get_config_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_id_ctx->opts, state->ipa_realm, attrs, NULL, NULL); @@ -181,6 +174,7 @@ struct ipa_pam_auth_handler_state { struct tevent_context *ev; struct ipa_auth_ctx *auth_ctx; struct be_ctx *be_ctx; + struct sss_failover_ctx *fctx; struct pam_data *pd; struct sss_domain_info *dom; }; @@ -212,6 +206,7 @@ ipa_pam_auth_handler_send(TALLOC_CTX *mem_ctx, state->ev = params->ev; state->auth_ctx = auth_ctx; state->be_ctx = params->be_ctx; + state->fctx = auth_ctx->sdap_id_ctx->fctx; state->dom = find_domain_by_name(state->be_ctx->domain, state->pd->domain, true); @@ -306,7 +301,6 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq) static void ipa_pam_auth_handler_flag_done(struct tevent_req *subreq) { struct ipa_pam_auth_handler_state *state; - struct sdap_auth_ctx *sdap_auth_ctx; bool password_migration = false; struct tevent_req *req; errno_t ret; @@ -324,18 +318,14 @@ static void ipa_pam_auth_handler_flag_done(struct tevent_req *subreq) } if (password_migration) { - sdap_auth_ctx = state->auth_ctx->sdap_auth_ctx; - subreq = sdap_cli_resolve_and_connect_send(state, state->ev, - sdap_auth_ctx->opts, - sdap_auth_ctx->be, - sdap_auth_ctx->service, - true, CON_TLS_ON, true); - if (subreq == NULL) { + ret = sss_failover_transaction_ex_send( + state, state->ev, state->fctx, req, ipa_pam_auth_handler_connect_done, true, + false, false, SSS_FAILOVER_TRANSACTION_TLS_ON); + if (ret != EOK) { state->pd->pam_status = PAM_SYSTEM_ERR; goto done; } - tevent_req_set_callback(subreq, ipa_pam_auth_handler_connect_done, req); return; } diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 632254802ef..f147012b261 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -899,16 +899,16 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, /* Set flag that controls whether we want to write the * kdcinfo files at all */ - ipa_opts->service->krb5_service->write_kdcinfo = \ + ipa_opts->krb5_service->write_kdcinfo = \ dp_opt_get_bool(ipa_opts->auth, KRB5_USE_KDCINFO); DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n", ipa_opts->auth[KRB5_USE_KDCINFO].opt_name, - ipa_opts->service->krb5_service->write_kdcinfo ? "true" : "false"); - if (ipa_opts->service->krb5_service->write_kdcinfo) { + ipa_opts->krb5_service->write_kdcinfo ? "true" : "false"); + if (ipa_opts->krb5_service->write_kdcinfo) { sss_krb5_parse_lookahead( dp_opt_get_string(ipa_opts->auth, KRB5_KDCINFO_LOOKAHEAD), - &ipa_opts->service->krb5_service->lookahead_primary, - &ipa_opts->service->krb5_service->lookahead_backup); + &ipa_opts->krb5_service->lookahead_primary, + &ipa_opts->krb5_service->lookahead_backup); } *_opts = ipa_opts->auth; diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index c5fa3825842..b2f5e9b343d 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -229,7 +229,7 @@ struct ipa_options { struct sdap_search_base **ranges_search_bases; struct sdap_search_base **views_search_bases; struct sdap_search_base **deskprofile_search_bases; - struct ipa_service *service; + struct krb5_service *krb5_service; /* id provider */ struct sdap_options *id; diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index f3b34754a5c..52cc9f0dd2b 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -29,10 +29,13 @@ #include "providers/ipa/ipa_dyndns.h" #include "providers/data_provider.h" #include "providers/be_dyndns.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" struct ipa_dyndns_update_state { struct ipa_options *ipa_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; }; static void @@ -53,7 +56,8 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq); errno_t ipa_dyndns_init(struct be_ctx *be_ctx, - struct ipa_options *ctx) + struct ipa_options *ctx, + struct sdap_id_ctx *sdap_id_ctx) { errno_t ret; const time_t ptask_first_delay = 10; @@ -61,6 +65,7 @@ errno_t ipa_dyndns_init(struct be_ctx *be_ctx, int offset; uint32_t extraflags = 0; + ctx->id_ctx->fctx = sdap_id_ctx->fctx; ctx->be_res = be_ctx->be_res; if (ctx->be_res == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Resolver must be initialized in order " @@ -102,8 +107,8 @@ ipa_dyndns_update_send(TALLOC_CTX *mem_ctx, { int ret; struct ipa_options *ctx; + struct tevent_req *req; struct ipa_dyndns_update_state *state; - struct tevent_req *req, *subreq; struct sdap_id_ctx *sdap_ctx; DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); @@ -127,22 +132,11 @@ ipa_dyndns_update_send(TALLOC_CTX *mem_ctx, } state->ipa_ctx->dyndns_ctx->last_refresh = time(NULL); - /* Make sure to have a valid LDAP connection */ - state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret)); - ret = ENOMEM; + ret = sss_failover_transaction_send(state, ev, sdap_ctx->fctx, req, + ipa_dyndns_update_connect_done); + if (ret != EOK) { goto done; } - tevent_req_set_callback(subreq, ipa_dyndns_update_connect_done, req); ret = EOK; done: if (ret != EOK) { @@ -164,23 +158,22 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_dyndns_update_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } ctx = state->ipa_ctx; sdap_ctx = ctx->id_ctx->sdap_id_ctx; - if (ret != EOK) { - if (be_is_offline(sdap_ctx->be)) { - DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " - "dynamic DNS update is skipped in offline mode.\n"); - tevent_req_error(req, ERR_DYNDNS_OFFLINE); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to LDAP server: [%d](%s)\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ERR_NETWORK_IO); - } + if (sdap_ctx->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " + "dynamic DNS update is skipped in offline mode.\n"); + tevent_req_error(req, ERR_DYNDNS_OFFLINE); return; } @@ -198,13 +191,13 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) goto done; } - if (ctx->service->sdap->uri == NULL) { + if (state->conn->uri == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "LDAP uri not set\n"); ret = EINVAL; goto done; } - if (strncmp(ctx->service->sdap->uri, + if (strncmp(state->conn->uri, "ldap://", 7) != 0) { DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected format of LDAP URI.\n"); ret = EIO; @@ -231,7 +224,7 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) if (!subreq) { ret = EIO; DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: [%d](%s)\n", + "sdap_dyndns_update_send failed: [%d](%s)\n", ret, sss_strerror(ret)); goto done; } diff --git a/src/providers/ipa/ipa_dyndns.h b/src/providers/ipa/ipa_dyndns.h index d6873b7b922..024e8cd49da 100644 --- a/src/providers/ipa/ipa_dyndns.h +++ b/src/providers/ipa/ipa_dyndns.h @@ -30,6 +30,7 @@ #include "providers/backend.h" errno_t ipa_dyndns_init(struct be_ctx *be_ctx, - struct ipa_options *ctx); + struct ipa_options *ctx, + struct sdap_id_ctx *sdap_id_ctx); #endif /* IPA_DYNDNS_H_ */ diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c index e0eb236290b..bb2ee639f93 100644 --- a/src/providers/ipa/ipa_id.c +++ b/src/providers/ipa/ipa_id.c @@ -477,7 +477,8 @@ struct ipa_id_get_account_info_state { struct tevent_context *ev; struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *ctx; - struct sdap_id_op *op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; struct dp_id_data *ar; @@ -511,7 +512,6 @@ ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev, { int ret; struct tevent_req *req; - struct tevent_req *subreq; struct ipa_id_get_account_info_state *state; req = tevent_req_create(memctx, &state, @@ -524,13 +524,7 @@ ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; - - state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); - if (state->op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n"); - ret = ENOMEM; - goto fail; - } + state->fctx = state->ctx->fctx; state->domain = find_domain_by_name(state->ctx->be->domain, ar->domain, true); @@ -568,12 +562,11 @@ ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev, goto fail; } } else { - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_id_get_account_info_connected); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, ipa_id_get_account_info_connected, req); } return req; @@ -590,15 +583,18 @@ static void ipa_id_get_account_info_connected(struct tevent_req *subreq) struct tevent_req); struct ipa_id_get_account_info_state *state = tevent_req_data(req, struct ipa_id_get_account_info_state); - int ret; - - ret = sdap_id_op_connect_recv(subreq); + errno_t ret; + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n"); - goto fail; + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; } + talloc_zfree(subreq); + subreq = ipa_get_trusted_override_send(state, state->ev, state->ctx, state->ipa_ctx->ipa_options, state->realm, state->ipa_ctx->view_name, state->ar); @@ -633,21 +629,7 @@ static void ipa_id_get_account_info_got_override(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->op, ret); - - if (ret == EAGAIN) { - /* retry */ - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); - goto fail; - } - tevent_req_set_callback(subreq, ipa_id_get_account_info_connected, - req); - return; - } - - DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); + ret = ERR_SERVER_FAILURE; goto fail; } @@ -720,8 +702,9 @@ static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req, subreq = sdap_handle_acct_req_send(state, state->ctx->be, ar, state->ipa_ctx->sdap_id_ctx, + state->ipa_ctx->sdap_id_ctx->fctx, state->ipa_ctx->sdap_id_ctx->opts->sdom, - state->ipa_ctx->sdap_id_ctx->conn, true); + true); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n"); return ENOMEM; @@ -1144,7 +1127,8 @@ int ipa_id_get_account_info_recv(struct tevent_req *req) struct ipa_id_get_netgroup_state { struct tevent_context *ev; struct ipa_id_ctx *ctx; - struct sdap_id_op *op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -1168,7 +1152,6 @@ static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx, { struct tevent_req *req; struct ipa_id_get_netgroup_state *state; - struct tevent_req *subreq; struct sdap_id_ctx *ctx; char *clean_name; int ret; @@ -1180,14 +1163,7 @@ static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ipa_ctx; - - state->op = sdap_id_op_create(state, ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - + state->fctx = state->ctx->sdap_id_ctx->fctx; state->sysdb = ctx->be->domain->sysdb; state->domain = ctx->be->domain; state->name = name; @@ -1214,11 +1190,11 @@ static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx, &state->attrs, NULL); if (ret != EOK) goto fail; - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_id_get_netgroup_connected); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, ipa_id_get_netgroup_connected, req); return req; @@ -1234,21 +1210,21 @@ static void ipa_id_get_netgroup_connected(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct ipa_id_get_netgroup_state *state = tevent_req_data(req, struct ipa_id_get_netgroup_state); - int ret; struct sdap_id_ctx *sdap_ctx = state->ctx->sdap_id_ctx; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } subreq = ipa_get_netgroups_send(state, state->ev, state->sysdb, state->domain, sdap_ctx->opts, state->ctx->ipa_options, - sdap_id_op_handle(state->op), + state->conn->sh, state->attrs, state->filter, state->timeout); if (!subreq) { @@ -1271,18 +1247,6 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq) ret = ipa_get_netgroups_recv(subreq, state, &state->count, &state->netgroups); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - - if (ret == EAGAIN) { - /* retry */ - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - tevent_req_error(req, ret); - return; - } - tevent_req_set_callback(subreq, ipa_id_get_netgroup_connected, req); - return; - } if (ret && ret != ENOENT) { tevent_req_error(req, ret); diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index 829ac9b5db6..e8342201dd6 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -497,7 +497,7 @@ static errno_t ipa_init_krb5_auth_ctx(TALLOC_CTX *mem_ctx, return ENOMEM; } - krb5_auth_ctx->service = ipa_options->service->krb5_service; + krb5_auth_ctx->service = ipa_options->krb5_service; server_mode = dp_opt_get_bool(ipa_options->basic, IPA_SERVER_MODE); krb5_auth_ctx->config_type = server_mode ? K5C_IPA_SERVER : K5C_IPA_CLIENT; diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c index 9d902c781c3..866099f7669 100644 --- a/src/providers/ipa/ipa_selinux.c +++ b/src/providers/ipa/ipa_selinux.c @@ -54,6 +54,7 @@ static struct tevent_req * ipa_get_selinux_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, struct be_ctx *be_ctx, struct sysdb_attrs *user, struct sysdb_attrs *host, @@ -709,7 +710,8 @@ static errno_t selinux_child_recv(struct tevent_req *req) struct ipa_get_selinux_state { struct be_ctx *be_ctx; struct ipa_selinux_ctx *selinux_ctx; - struct sdap_id_op *op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sysdb_attrs *host; struct sysdb_attrs *user; @@ -727,13 +729,13 @@ ipa_get_selinux_maps_offline(struct tevent_req *req); static struct tevent_req * ipa_get_selinux_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, struct be_ctx *be_ctx, struct sysdb_attrs *user, struct sysdb_attrs *host, struct ipa_selinux_ctx *selinux_ctx) { struct tevent_req *req; - struct tevent_req *subreq; struct ipa_get_selinux_state *state; bool offline; int ret = EOK; @@ -749,10 +751,12 @@ ipa_get_selinux_send(TALLOC_CTX *mem_ctx, state->be_ctx = be_ctx; state->selinux_ctx = selinux_ctx; + state->fctx = selinux_ctx->id_ctx->sdap_id_ctx->fctx; state->user = user; state->host = host; - offline = be_is_offline(be_ctx); + offline = state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE; + DEBUG(SSSDBG_TRACE_INTERNAL, "Connection status is [%s].\n", offline ? "offline" : "online"); @@ -769,23 +773,11 @@ ipa_get_selinux_send(TALLOC_CTX *mem_ctx, } if (!offline) { - state->op = sdap_id_op_create(state, - selinux_ctx->id_ctx->sdap_id_ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto immediate; - } - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send failed: " - "%d(%s).\n", ret, strerror(ret)); - talloc_zfree(state->op); + ret = sss_failover_transaction_send(state, ev, state->fctx, req, + ipa_get_selinux_connect_done); + if (ret != EOK) { goto immediate; } - - tevent_req_set_callback(subreq, ipa_get_selinux_connect_done, req); } else { ret = ipa_get_selinux_maps_offline(req); goto immediate; @@ -815,11 +807,16 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq) struct dp_module *selinux_mod; const char *hostname; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } - if (be_is_offline(state->be_ctx)) { - talloc_zfree(state->op); + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { ret = ipa_get_selinux_maps_offline(req); if (ret == EOK) { tevent_req_done(req); @@ -828,10 +825,6 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq) goto fail; } - if (ret != EOK) { - goto fail; - } - access_mod = dp_target_module(state->be_ctx->provider, DPT_ACCESS); selinux_mod = dp_target_module(state->be_ctx->provider, DPT_SELINUX); if (access_mod == selinux_mod && state->host != NULL) { @@ -849,7 +842,7 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq) } subreq = ipa_host_info_send(state, state->be_ctx->ev, - sdap_id_op_handle(state->op), + state->conn->sh, id_ctx->sdap_id_ctx->opts, hostname, id_ctx->ipa_options->id->host_map, @@ -1001,7 +994,7 @@ static void ipa_get_config_step(struct tevent_req *req) domain = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic, IPA_KRB5_REALM); subreq = ipa_get_config_send(state, state->be_ctx->ev, - sdap_id_op_handle(state->op), + state->conn->sh, id_ctx->sdap_id_ctx->opts, domain, attrs, NULL, NULL); if (subreq == NULL) { @@ -1028,10 +1021,10 @@ static void ipa_get_selinux_config_done(struct tevent_req *subreq) subreq = ipa_selinux_get_maps_send(state, state->be_ctx->ev, state->be_ctx->domain->sysdb, - sdap_id_op_handle(state->op), - id_ctx->opts, - state->selinux_ctx->id_ctx->ipa_options, - state->selinux_ctx->selinux_search_bases); + state->conn->sh, + id_ctx->opts, + state->selinux_ctx->id_ctx->ipa_options, + state->selinux_ctx->selinux_search_bases); if (!subreq) { ret = ENOMEM; goto done; @@ -1112,7 +1105,7 @@ static void ipa_get_selinux_maps_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "SELinux maps referenced an HBAC rule. " "Need to refresh HBAC rules\n"); subreq = ipa_hbac_rule_info_send(state, state->be_ctx->ev, - sdap_id_op_handle(state->op), + state->conn->sh, id_ctx->sdap_id_ctx->opts, state->selinux_ctx->hbac_search_bases, state->host); @@ -1451,7 +1444,7 @@ ipa_selinux_handler_send(TALLOC_CTX *mem_ctx, goto immediately; } - subreq = ipa_get_selinux_send(state, params->be_ctx, state->user, + subreq = ipa_get_selinux_send(state, params->ev, params->be_ctx, state->user, state->host, selinux_ctx); if (subreq == NULL) { goto immediately; diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c index 2fef7cb94f1..0e26b423dc7 100644 --- a/src/providers/ipa/ipa_session.c +++ b/src/providers/ipa/ipa_session.c @@ -49,8 +49,9 @@ struct ipa_fetch_deskprofile_state { struct tevent_context *ev; struct be_ctx *be_ctx; struct sdap_id_ctx *sdap_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct ipa_session_ctx *session_ctx; - struct sdap_id_op *sdap_op; struct dp_option *ipa_options; struct sdap_search_base **search_bases; const char *username; @@ -65,7 +66,6 @@ struct ipa_fetch_deskprofile_state { uint16_t priority; }; -static errno_t ipa_fetch_deskprofile_retry(struct tevent_req *req); static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq); static errno_t ipa_fetch_deskprofile_hostinfo(struct tevent_req *req); static void ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq); @@ -98,6 +98,7 @@ ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->be_ctx = be_ctx; state->session_ctx = session_ctx; + state->fctx = session_ctx->sdap_ctx->fctx; state->sdap_ctx = session_ctx->sdap_ctx; state->ipa_options = session_ctx->ipa_options; state->search_bases = session_ctx->deskprofile_search_bases; @@ -119,14 +120,6 @@ ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, goto immediately; } - state->sdap_op = sdap_id_op_create(state, - state->sdap_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto immediately; - } - now = time(NULL); request_interval = dp_opt_get_int(state->ipa_options, @@ -149,7 +142,7 @@ ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, state->session_ctx->no_rules_found = false; - offline = be_is_offline(be_ctx); + offline = state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE; DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n", offline ? "offline" : "online"); @@ -163,11 +156,11 @@ ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, goto immediately; } - ret = ipa_fetch_deskprofile_retry(req); - if (ret != EAGAIN) { + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_fetch_deskprofile_connect_done); + if (ret != EOK) { goto immediately; } - return req; immediately: @@ -181,29 +174,6 @@ ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t -ipa_fetch_deskprofile_retry(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct ipa_fetch_deskprofile_state *state; - int ret; - - state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_id_op_connect_send() failed: %d (%s)\n", - ret, strerror(ret)); - - return ret; - } - - tevent_req_set_callback(subreq, ipa_fetch_deskprofile_connect_done, req); - - return EAGAIN; -} - static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq) { @@ -211,10 +181,15 @@ ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq) errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); + struct ipa_fetch_deskprofile_state *state = tevent_req_data(req, + struct ipa_fetch_deskprofile_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + ret = EINVAL; goto done; } @@ -243,7 +218,7 @@ ipa_fetch_deskprofile_hostinfo(struct tevent_req *req) subreq = ipa_host_info_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, hostname, state->session_ctx->host_map, @@ -291,7 +266,7 @@ ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq) subreq = ipa_deskprofile_get_config_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, state->ipa_options); if (subreq == NULL) { @@ -331,7 +306,7 @@ ipa_fetch_deskprofile_config_done(struct tevent_req *subreq) subreq = ipa_deskprofile_rule_info_send(state, state->ev, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_ctx->opts, state->search_bases, state->ipa_host, @@ -367,8 +342,6 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq) state->rules->entry_subdir = DESKPROFILE_RULES_SUBDIR; talloc_zfree(subreq); if (ret == ENOENT) { - /* Set ret to EOK so we can safely call sdap_id_op_done. */ - ret = EOK; found = false; } else if (ret == EOK) { found = true; @@ -376,12 +349,6 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq) goto done; } - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - /* For now, let's completely purge the previous stored * rules before saving the new ones */ ret = ipa_common_purge_rules(state->be_ctx->domain, diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 0144b521e09..dbc6f5582ba 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -2873,10 +2873,10 @@ static errno_t ipa_subdomains_write_kdcinfo_recv(struct tevent_req *req) struct ipa_subdomains_refresh_state { struct tevent_context *ev; struct ipa_subdomains_ctx *sd_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; }; -static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req); static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); @@ -2907,20 +2907,15 @@ ipa_subdomains_refresh_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->sd_ctx = sd_ctx; + state->fctx = sd_ctx->ipa_id_ctx->fctx; - state->sdap_op = sdap_id_op_create(state, - sd_ctx->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_subdomains_refresh_connect_done); + if (ret != EOK) { goto immediately; } - ret = ipa_subdomains_refresh_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } + return req; immediately: if (ret == EOK) { @@ -2933,26 +2928,6 @@ ipa_subdomains_refresh_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req) -{ - struct ipa_subdomains_refresh_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct ipa_subdomains_refresh_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed " - "[%d]: %s\n", ret, sss_strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, ipa_subdomains_refresh_connect_done, req); - - return EAGAIN; -} - static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq) { struct ipa_subdomains_refresh_state *state; @@ -2962,23 +2937,25 @@ static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_subdomains_refresh_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP " - "[%d]: %s\n", ret, sss_strerror(ret)); - if (be_is_offline(state->sd_ctx->be_ctx)) { - DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, " - "cannot get the subdomain list while offline\n"); - ret = ERR_OFFLINE; - } + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server available, " + "cannot get the subdomain list while offline\n"); + ret = ERR_OFFLINE; tevent_req_error(req, ret); return; } subreq = ipa_subdomains_ranges_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3006,7 +2983,7 @@ static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq) } subreq = ipa_subdomains_certmap_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3034,7 +3011,7 @@ static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq) } subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3062,7 +3039,7 @@ static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq) } subreq = ipa_subdomains_slave_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3090,7 +3067,7 @@ static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq) } subreq = ipa_subdomains_view_name_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3120,7 +3097,7 @@ static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq) } subreq = ipa_subdomains_view_template_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3153,7 +3130,7 @@ static void ipa_subdomains_refresh_view_template_done(struct tevent_req *subreq) state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3184,7 +3161,7 @@ ipa_subdomains_refresh_view_domain_resolution_order_done(struct tevent_req *subr } subreq = ipa_domain_resolution_order_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); + state->conn->sh); if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; @@ -3207,18 +3184,16 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq) ret = ipa_domain_resolution_order_recv(subreq); talloc_zfree(subreq); - if (ret != EOK) { + + if (ret == ERR_NO_MORE_SERVERS) { + ret = ERR_OFFLINE; + tevent_req_error(req, ret); + return; + } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to get the domains order resolution [%d]: %s\n", ret, sss_strerror(ret)); - /* Not good, but let's try to continue with other server side options */ - } - - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); + tevent_req_error(req, ERR_SERVER_FAILURE); return; } diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c index 56298eb59be..db4e20b273b 100644 --- a/src/providers/ipa/ipa_subdomains_ext_groups.c +++ b/src/providers/ipa/ipa_subdomains_ext_groups.c @@ -519,8 +519,9 @@ static void ipa_add_trusted_memberships_done(struct tevent_req *subreq); struct get_trusted_membership_state { struct tevent_context *ev; struct ipa_server_mode_ctx *server_mode; - struct sdap_id_op *sdap_op; struct sdap_id_ctx *sdap_id_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct fo_server *srv; char *user_name; struct sss_domain_info *user_dom; @@ -545,7 +546,6 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, { int ret; struct tevent_req *req; - struct tevent_req *subreq; struct get_trusted_membership_state *state; req = tevent_req_create(mem_ctx, &state, struct get_trusted_membership_state); @@ -557,6 +557,7 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->user_dom = user_dom; state->sdap_id_ctx = sdap_id_ctx; + state->fctx = sdap_id_ctx->fctx; state->srv = NULL; state->domain = domain; @@ -575,14 +576,6 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, goto done; } - state->sdap_op = sdap_id_op_create(state, - state->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - state->server_mode = server_mode; if (server_mode->ext_groups == NULL) { server_mode->ext_groups = talloc_zero(server_mode, @@ -608,15 +601,12 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx, } - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, strerror(ret)); + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_get_trusted_memberships_connect_done); + if (ret != EOK) { goto done; } - tevent_req_set_callback(subreq, ipa_get_trusted_memberships_connect_done, req); - return req; done: @@ -638,23 +628,23 @@ static void ipa_get_trusted_memberships_connect_done(struct tevent_req *subreq) struct get_trusted_membership_state); int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (be_is_offline(state->sdap_id_ctx->be)) { - DEBUG(SSSDBG_MINOR_FAILURE, - "No IPA server is available, going offline\n"); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to IPA server: [%d](%s)\n", - ret, strerror(ret)); - } + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, + "IPA server is offline\n"); goto fail; } subreq = sdap_search_bases_send(state, state->ev, state->sdap_id_ctx->opts, - sdap_id_op_handle(state->sdap_op), + state->conn->sh, state->sdap_id_ctx->opts->sdom->group_search_bases, NULL, true, dp_opt_get_int(state->sdap_id_ctx->opts->basic, @@ -850,7 +840,8 @@ static errno_t filter_groups_by_attribute_name(char **groups, struct add_trusted_membership_state { struct tevent_context *ev; struct sdap_id_ctx *sdap_id_ctx; - struct sdap_id_op *sdap_op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct ldb_dn *user_dn; struct sss_domain_info *user_dom; struct sss_domain_info *group_dom; @@ -877,7 +868,6 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx, { int ret; struct tevent_req *req; - struct tevent_req *subreq; struct add_trusted_membership_state *state; req = tevent_req_create(mem_ctx, &state, struct add_trusted_membership_state); @@ -889,6 +879,7 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->user_dom = user_dom; state->sdap_id_ctx = sdap_id_ctx; + state->fctx = sdap_id_ctx->fctx; state->user_dn = user_dn; state->group_dom = group_dom; state->orig_groups = groups; @@ -932,23 +923,12 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx, goto done; } - state->sdap_op = sdap_id_op_create(state, - state->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, strerror(ret)); + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_add_trusted_memberships_connect_done); + if (ret != EOK) { goto done; } - tevent_req_set_callback(subreq, ipa_add_trusted_memberships_connect_done, req); - return req; done: @@ -970,17 +950,18 @@ static void ipa_add_trusted_memberships_connect_done(struct tevent_req *subreq) struct add_trusted_membership_state); int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (be_is_offline(state->sdap_id_ctx->be)) { - DEBUG(SSSDBG_MINOR_FAILURE, - "No IPA server is available, going offline\n"); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to IPA server: [%d](%s)\n", - ret, strerror(ret)); - } + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, + "No IPA server is available, going offline\n"); tevent_req_error(req, ret); return; @@ -1053,7 +1034,7 @@ static void ipa_add_trusted_memberships_get_next(struct tevent_req *req) * directly fetch the group with the corresponding DN. */ subreq = groups_get_send(state, state->ev, state->sdap_id_ctx, state->group_sdom, - NULL, + state->fctx, fq_name, BE_FILTER_NAME, false, false, false); diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index f5134602f4d..9e54257bda8 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -51,7 +51,8 @@ struct ipa_subdomain_account_state { struct tevent_context *ev; struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *ctx; - struct sdap_id_op *op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; struct dp_id_data *ar; @@ -79,7 +80,6 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, { struct tevent_req *req; struct ipa_subdomain_account_state *state; - struct tevent_req *subreq; int ret; req = tevent_req_create(memctx, &state, struct ipa_subdomain_account_state); @@ -91,13 +91,7 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; - - state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } + state->fctx = ipa_ctx->sdap_id_ctx->fctx; state->domain = find_domain_by_name(state->ctx->be->domain, ar->domain, true); @@ -138,11 +132,11 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, return req; } - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_subdomain_account_connected); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, ipa_subdomain_account_connected, req); return req; @@ -160,18 +154,20 @@ static void ipa_subdomain_account_connected(struct tevent_req *subreq) struct ipa_subdomain_account_state); int ret; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n"); - goto fail; + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; } subreq = ipa_get_trusted_override_send(state, state->ev, state->ctx, - state->ipa_ctx->ipa_options, - dp_opt_get_string(state->ipa_ctx->ipa_options->basic, - IPA_KRB5_REALM), - state->ipa_ctx->view_name, state->ar); + state->ipa_ctx->ipa_options, + dp_opt_get_string(state->ipa_ctx->ipa_options->basic, + IPA_KRB5_REALM), + state->ipa_ctx->view_name, state->ar); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "ipa_get_trusted_override_send failed.\n"); ret = ENOMEM; @@ -204,21 +200,7 @@ static void ipa_subdomain_account_got_override(struct tevent_req *subreq) &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { - ret = sdap_id_op_done(state->op, ret); - - if (ret == EAGAIN) { - /* retry */ - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); - goto fail; - } - tevent_req_set_callback(subreq, ipa_subdomain_account_connected, - req); - return; - } - - DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); + ret = ERR_SERVER_FAILURE; goto fail; } @@ -412,7 +394,8 @@ struct ipa_get_subdom_acct { struct tevent_context *ev; struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *ctx; - struct sdap_id_op *op; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; struct sysdb_attrs *override_attrs; @@ -436,7 +419,6 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, { struct tevent_req *req; struct ipa_get_subdom_acct *state; - struct tevent_req *subreq; int ret; req = tevent_req_create(memctx, &state, struct ipa_get_subdom_acct); @@ -445,16 +427,10 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, state->ev = ev; state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; + state->fctx = state->ctx->fctx; state->override_attrs = override_attrs; state->use_pac = false; - state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); - if (!state->op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - state->domain = find_domain_by_name(state->ctx->be->domain, ar->domain, true); if (state->domain == NULL) { @@ -498,11 +474,11 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, } if (ret != EOK) goto fail; - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_get_subdom_acct_connected); + if (ret != EOK) { goto fail; } - tevent_req_set_callback(subreq, ipa_get_subdom_acct_connected, req); return req; @@ -523,19 +499,21 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) struct req_input *req_input; char *shortname; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } if (state->entry_type == BE_REQ_INITGROUPS) { /* With V1/V2 of the extdom plugin a user lookup will resolve the full * group membership of the user. */ - if (sdap_is_extension_supported(sdap_id_op_handle(state->op), + if (sdap_is_extension_supported(state->conn->sh, EXOP_SID2NAME_V1_OID) || - sdap_is_extension_supported(sdap_id_op_handle(state->op), + sdap_is_extension_supported(state->conn->sh, EXOP_SID2NAME_V2_OID)) { state->entry_type = BE_REQ_USER; } else { @@ -545,7 +523,7 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) * and add the user to all groups. */ subreq = ipa_get_subdom_acct_process_pac_send(state, state->ev, - sdap_id_op_handle(state->op), + state->conn->sh, state->ipa_ctx, state->domain, state->user_msg); @@ -623,9 +601,9 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) } break; case BE_FILTER_CERT: - if (sdap_is_extension_supported(sdap_id_op_handle(state->op), + if (sdap_is_extension_supported(state->conn->sh, EXOP_SID2NAME_V1_OID) || - sdap_is_extension_supported(sdap_id_op_handle(state->op), + sdap_is_extension_supported(state->conn->sh, EXOP_SID2NAME_V2_OID)) { req_input->type = REQ_INP_CERT; req_input->inp.cert = talloc_strdup(req_input, state->filter); @@ -653,7 +631,7 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) state->ctx->opts, state->domain, state->override_attrs, - sdap_id_op_handle(state->op), + state->conn->sh, state->entry_type, req_input); if (!subreq) { @@ -669,32 +647,19 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct ipa_get_subdom_acct *state = tevent_req_data(req, - struct ipa_get_subdom_acct); int ret; ret = ipa_s2n_get_acct_info_recv(subreq); talloc_zfree(subreq); - ret = sdap_id_op_done(state->op, ret); - if (ret != EOK) { - /* retry */ - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - tevent_req_error(req, ret); - return; - } - tevent_req_set_callback(subreq, ipa_get_subdom_acct_connected, req); + if (ret == ENOMEM) { + tevent_req_error(req, ENOMEM); return; - } - - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); + } else if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ERR_SERVER_FAILURE); return; } - /* FIXME: do we need some special handling of ENOENT */ - tevent_req_done(req); } @@ -773,7 +738,6 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, struct ipa_get_acct_state *state; struct sdap_domain *sdom; struct sss_failover_ctx *fctx; - struct sdap_id_conn_ctx **clist; struct sdap_id_ctx *sdap_id_ctx; struct ad_id_ctx *ad_id_ctx; @@ -817,7 +781,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, } subreq = ad_handle_acct_info_send(req, ar, sdap_id_ctx, - ad_id_ctx->ad_options, sdom, clist); + ad_id_ctx->ad_options, sdom, fctx); if (subreq == NULL) { ret = ENOMEM; goto fail; diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c index a903422351f..3f0ac01432c 100644 --- a/src/providers/ipa/ipa_sudo_async.c +++ b/src/providers/ipa/ipa_sudo_async.c @@ -28,9 +28,12 @@ #include "providers/ipa/ipa_hosts.h" #include "providers/ipa/ipa_sudo.h" #include "providers/ipa/ipa_dn.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" #include "db/sysdb.h" #include "db/sysdb_sudo.h" + struct ipa_hostinfo { size_t num_hosts; size_t num_hostgroups; @@ -842,6 +845,8 @@ struct ipa_sudo_refresh_state { struct sysdb_ctx *sysdb; struct sss_domain_info *domain; struct ipa_sudo_ctx *sudo_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct ipa_options *ipa_opts; struct sdap_options *sdap_opts; const char *cmdgroups_filter; @@ -849,14 +854,12 @@ struct ipa_sudo_refresh_state { const char *delete_filter; bool update_usn; - struct sdap_id_op *sdap_op; struct sdap_handle *sh; struct sysdb_attrs **rules; size_t num_rules; }; -static errno_t ipa_sudo_refresh_retry(struct tevent_req *req); static void ipa_sudo_refresh_connect_done(struct tevent_req *subreq); static void ipa_sudo_refresh_host_done(struct tevent_req *subreq); static void ipa_sudo_refresh_done(struct tevent_req *subreq); @@ -884,18 +887,11 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx, state->sysdb = sudo_ctx->id_ctx->be->domain->sysdb; state->domain = sudo_ctx->id_ctx->be->domain; state->sudo_ctx = sudo_ctx; + state->fctx = sudo_ctx->id_ctx->fctx; state->ipa_opts = sudo_ctx->ipa_opts; state->sdap_opts = sudo_ctx->sdap_opts; state->update_usn = update_usn; - state->sdap_op = sdap_id_op_create(state, - sudo_ctx->id_ctx->conn->conn_cache); - if (!state->sdap_op) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto immediately; - } - state->cmdgroups_filter = talloc_strdup(state, cmdgroups_filter); if (cmdgroups_filter != NULL && state->cmdgroups_filter == NULL) { ret = ENOMEM; @@ -914,12 +910,14 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx, goto immediately; } - ret = ipa_sudo_refresh_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_sudo_refresh_connect_done); + if (ret != EOK) { + goto immediately; } + return req; + immediately: if (ret == EOK) { tevent_req_done(req); @@ -931,49 +929,26 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx, return req; } -static errno_t -ipa_sudo_refresh_retry(struct tevent_req *req) -{ - struct ipa_sudo_refresh_state *state; - struct tevent_req *subreq; - int ret; - - state = tevent_req_data(req, struct ipa_sudo_refresh_state); - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: " - "%d(%s)\n", ret, strerror(ret)); - return ret; - } - - tevent_req_set_callback(subreq, ipa_sudo_refresh_connect_done, req); - - return EAGAIN; -} - static void ipa_sudo_refresh_connect_done(struct tevent_req *subreq) { struct ipa_sudo_refresh_state *state; const char *hostname; struct tevent_req *req; - int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ipa_sudo_refresh_state); - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed " - "[%d]: %s\n", ret, strerror(ret)); - tevent_req_error(req, ret); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } - state->sh = sdap_id_op_handle(state->sdap_op); + state->sh = state->conn->sh; DEBUG(SSSDBG_TRACE_FUNC, "SUDO LDAP connection successful\n"); DEBUG(SSSDBG_TRACE_FUNC, "About to fetch host information\n"); @@ -1053,17 +1028,9 @@ ipa_sudo_refresh_done(struct tevent_req *subreq) &state->num_rules, &usn); talloc_zfree(subreq); - ret = sdap_id_op_done(state->sdap_op, ret); - if (ret == EAGAIN) { - /* retry */ - ret = ipa_sudo_refresh_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { - tevent_req_error(req, ret); - return; + if (ret != EOK) { + ret = ERR_SERVER_FAILURE; + goto done; } ret = sysdb_transaction_start(state->sysdb); @@ -1092,7 +1059,7 @@ ipa_sudo_refresh_done(struct tevent_req *subreq) in_transaction = false; if (usn != NULL && state->update_usn) { - sdap_sudo_set_usn(state->sudo_ctx->id_ctx->srv_opts, usn); + sdap_sudo_set_usn(state->conn->srv_opts, usn); } DEBUG(SSSDBG_TRACE_FUNC, "Sudo rules are successfully stored in cache\n"); diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c index e2fff877d9b..ba706f3d0d0 100644 --- a/src/providers/ipa/ipa_views.c +++ b/src/providers/ipa/ipa_views.c @@ -382,13 +382,14 @@ errno_t get_dp_id_data_for_user_name(TALLOC_CTX *mem_ctx, struct ipa_get_trusted_override_state { struct tevent_context *ev; struct sdap_id_ctx *sdap_id_ctx; + struct sss_failover_ctx *fctx; + struct sss_failover_ldap_connection *conn; struct ipa_options *ipa_options; const char *ipa_realm; const char *ipa_view_name; struct dp_id_data *ar; struct sss_domain_info *dom; - struct sdap_id_op *sdap_op; struct sysdb_attrs *override_attrs; char *filter; bool login_override_checked; @@ -409,7 +410,6 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, { int ret; struct tevent_req *req; - struct tevent_req *subreq; struct ipa_get_trusted_override_state *state; req = tevent_req_create(mem_ctx, &state, struct ipa_get_trusted_override_state); @@ -420,6 +420,7 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->sdap_id_ctx = sdap_id_ctx; + state->fctx = sdap_id_ctx->fctx; state->ipa_options = ipa_options; state->ipa_realm = ipa_realm; state->ar = ar; @@ -446,23 +447,12 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx, goto done; } - state->sdap_op = sdap_id_op_create(state, - state->sdap_id_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto done; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n", - ret, strerror(ret)); + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_get_trusted_override_connect_done); + if (ret != EOK) { goto done; } - tevent_req_set_callback(subreq, ipa_get_trusted_override_connect_done, req); - return req; done: @@ -487,18 +477,18 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq) char *search_base; struct ipa_options *ipa_opts = state->ipa_options; - ret = sdap_id_op_connect_recv(subreq); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); talloc_zfree(subreq); - if (ret != EOK) { - if (ret == ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, - "No IPA server is available, going offline\n"); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to IPA server: [%d](%s)\n", - ret, strerror(ret)); - } + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); + return; + } + if (state->fctx->active_server->state == SSS_FAILOVER_SERVER_STATE_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, + "No IPA server is available, going offline\n"); goto fail; } @@ -528,7 +518,7 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq) state->ipa_view_name, state->filter); subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts, - sdap_id_op_handle(state->sdap_op), search_base, + state->conn->sh, search_base, LDAP_SCOPE_SUBTREE, state->filter, NULL, state->ipa_options->override_map, @@ -583,14 +573,12 @@ static void ipa_get_trusted_override_done(struct tevent_req *subreq) state->login_override_checked = true; state->ar->entry_type = BE_REQ_USER; - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); + ret = sss_failover_transaction_send(state, state->ev, state->fctx, req, + ipa_get_trusted_override_connect_done); + if (ret != EOK) { state->ar->entry_type = BE_REQ_GROUP; goto fail; } - tevent_req_set_callback(subreq, ipa_get_trusted_override_connect_done, - req); return; /* If no user override was found when looking up the auto private group * switch back to BE_REQ_GROUP to continue processing */ From eaacd79e80f12cb38b06cbc5e9eb0fe5e66a8d50 Mon Sep 17 00:00:00 2001 From: Dan Lavu Date: Thu, 16 Apr 2026 09:19:34 -0400 Subject: [PATCH 36/39] refactoring ipa tests for hostname framework changes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Jakub Vávra Reviewed-by: Justin Stephenson Reviewed-by: Madhuri Upadhye (cherry picked from commit 8f170d08a0ca0a9573fc173ae5e7e6a1cd8ffc26) --- src/tests/system/tests/test_ipa.py | 41 +++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/tests/system/tests/test_ipa.py b/src/tests/system/tests/test_ipa.py index d55d0d529ec..adf489e2508 100644 --- a/src/tests/system/tests/test_ipa.py +++ b/src/tests/system/tests/test_ipa.py @@ -540,7 +540,7 @@ def test_ipa__idview_useroverride_attribute(client: Client, ipa: IPA, override_a :customerscenario: False """ ipa.idview("testview1").add(description="This is a new view") - ipa.idview("testview1").apply(hosts=[f"{client.host.hostname}"]) + ipa.idview("testview1").apply(hosts=[client.hostnameutils.name]) attr, expected_value = next(iter(override_attrs.items())) @@ -582,7 +582,7 @@ def test_ipa__idview_groupoverride_attribute(client: Client, ipa: IPA, override_ :customerscenario: False """ ipa.idview("testview1").add(description="This is a new view") - ipa.idview("testview1").apply(hosts=[f"{client.host.hostname}"]) + ipa.idview("testview1").apply(hosts=[client.hostnameutils.name]) attr, expected_value = next(iter(override_attrs.items())) ipa.group("group-1").add().idgroupoverride().add_override("testview1", **override_attrs) @@ -617,7 +617,7 @@ def test_ipa__idview_groupoverride_group_members(client: Client, ipa: IPA): :customerscenario: False """ ipa.idview("testview1").add(description="This is a new view") - ipa.idview("testview1").apply(hosts=[f"{client.host.hostname}"]) + ipa.idview("testview1").apply(hosts=[client.hostnameutils.name]) u1 = ipa.user("user-1").add() u2 = ipa.user("user-2").add() @@ -666,7 +666,7 @@ def test_ipa__idview_append_user_cert(client: Client, ipa: IPA, moduledatadir: s :customerscenario: False """ ipa.idview("testview1").add(description="This is a new view") - ipa.idview("testview1").apply(hosts=[f"{client.host.hostname}"]) + ipa.idview("testview1").apply(hosts=[client.hostnameutils.name]) with open(f"{moduledatadir}/certificate") as f: certificate_content = f.read().strip() @@ -697,7 +697,7 @@ def test_ipa__idview_fails_to_apply_on_ipa_master(ipa: IPA): :customerscenario: False """ ipa.idview("testview1").add(description="This is a new view") - result = ipa.idview("testview1").apply(hosts=f"{ipa.host.hostname}") + result = ipa.idview("testview1").apply(hosts=[ipa.server]) assert result.rc == 1, "An IPA ID view should not apply on server!" @@ -727,11 +727,9 @@ def test_ipa__idview_lookup_user_by_email_with_overrides(client: Client, ipa: IP :customerscenario: True """ ipa.idview("testview1").add(description="View for email lookup test") - - ipa.idview("testview1").apply(hosts=[f"{client.host.hostname}"]) + ipa.idview("testview1").apply(hosts=[client.hostnameutils.name]) user = ipa.user("user-1").add(email="user1@ipa.test") - user.iduseroverride().add_override("testview1", login="o-user1", uid=999999, gid=888888, home="/home/o-user1") client.sssd.restart() @@ -834,7 +832,7 @@ def test_ipa__hbac_permitted_users_can_login(client: Client, ipa: IPA): ipa.hbac("allow_all").disable() ssh_access_rule = ipa.hbac("ssh_access_user1").create( - description="SSH access rule for user1", users=["user1"], hosts=["client.test"], services=["sshd"] + description="SSH access rule for user1", users=["user1"], hosts=[client.hostnameutils.name], services=["sshd"] ) client.sssd.restart() @@ -879,7 +877,10 @@ def test_ipa__hbac_permitted_group_users_can_login(client: Client, ipa: IPA): ipa.hbac("allow_all").disable() ipa.hbac("allow_group_ssh_access").create( - description="SSH access for allow group", groups="allow_group", hosts="client.test", services="sshd" + description="SSH access for allow group", + groups="allow_group", + hosts=client.hostnameutils.name, + services="sshd", ) client.sssd.restart() @@ -926,9 +927,9 @@ def test_ipa__hbac_permitted_host_group_members_can_login(client: Client, ipa: I ipa.user(user).add() ipa_client = ipa.hostgroup("ipa-client").add(description="client host group") - ipa_client.add_member(host="client.test") + ipa_client.add_member(host=client.hostnameutils.name) ipa_master = ipa.hostgroup("ipa-master").add(description="IPA server host group") - ipa_master.add_member(host="master.ipa.test") + ipa_master.add_member(host=ipa.server) ipa.hbac("allow_all").disable() @@ -989,7 +990,7 @@ def test_ipa__hbac_users_can_auth_by_permitted_services(client: Client, ipa: IPA ipa.hbac("service_group").create( description="service group rule", users="user1", - hosts="client.test", + hosts=client.hostnameutils.name, servicegroups="service_group", ) client.sssd.restart() @@ -1025,7 +1026,7 @@ def test_ipa__hbac_users_and_groups_in_one_rule(client: Client, ipa: IPA): description="Access for mixed users and groups", users="allowed_user3", groups="group1", - hosts="client.test", + hosts=client.hostnameutils.name, services="sshd", ) client.sssd.restart() @@ -1072,7 +1073,7 @@ def test_ipa__hbac_permitted_nested_group_users_can_login(client: Client, ipa: I ipa.hbac("allow_parent_group").create( description="Allow parent group with nested children", groups="parent_group", - hosts="client.test", + hosts=client.hostnameutils.name, services="sshd", ) client.sssd.restart() @@ -1108,7 +1109,7 @@ def test_ipa__hbac_rule_enable_disable_affects_login(client: Client, ipa: IPA): ipa.hbac("allow_all").disable() rule1 = ipa.hbac("rule1").create( - description="Rule 1 allowing SSH access", users="user1", hosts="client.test", services="sshd" + description="Rule 1 allowing SSH access", users="user1", hosts=client.hostnameutils.name, services="sshd" ) client.sssd.restart() @@ -1149,11 +1150,15 @@ def test_ipa__hbac_user_host_service_category_equals_all(client: Client, ipa: IP ipa_rule = ipa.hbac(f"access_{hbac}_all") if hbac == "user": - ipa_rule.create(description="Access to all users", usercat="all", hosts="client.test", services="sshd") + ipa_rule.create( + description="Access to all users", usercat="all", hosts=client.hostnameutils.name, services="sshd" + ) elif hbac == "host": ipa_rule.create(description="Access to all hosts", hostcat="all", users="user1", services="sshd") elif hbac == "service": - ipa_rule.create(description="Access to all services", servicecat="all", hosts="client.test", users="user1") + ipa_rule.create( + description="Access to all services", servicecat="all", hosts=client.hostnameutils.name, users="user1" + ) client.sssd.restart() if hbac == "user": From 7cadeba1f57e146a30ea9bb50447e2ba61556418 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Thu, 19 Mar 2026 13:04:54 -0400 Subject: [PATCH 37/39] tests: Exclude certain tests temporarily test_logging__offline_errors_are_written_to_logs_and_syslog: asserted offline logs messages are only part of old failover test_autofs__propagate_offline_status_*: asserted offline log messages are only part of the old failover test_logging__dns_resolution_issue_in_logs: asserted log messages are part of the old failover code test_failover: Needs to be updated for new failover implementation test_ad__user_authentication_when_provider_is_set_to_ldap_with_gss_spnego: 'id_provider = ldap' is hardcoded to go to 'master.ldap.test' but AD server should be used here test_ipa__subids_configured[id_provider=ldap]: 'id_provider = ldap' is hardcoded to go to 'master.ldap.test' but IPA server should be used here test_multithreaded_pac_client: requires re-using cached connection, not yet implemented in new failover --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81c0c2ab753..69c8e9611d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -311,6 +311,7 @@ jobs: --polarion-config=../polarion.yaml \ --output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ + -k "not test_logging__offline_errors_are_written_to_logs_and_syslog and not test_failover and not test_logging__dns_resolution_issue_in_logs and not test_ad__user_authentication_when_provider_is_set_to_ldap_with_gss_spnego and not test_multithreaded_pac_client and not test_autofs__propagate_offline_status and not test_failover__ and not test_ipa__subids_configured" \ --collect-only . |& tee $GITHUB_WORKSPACE/pytest-collect.log - name: Run tests @@ -331,6 +332,7 @@ jobs: --output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \ --output-polarion-testrun=$GITHUB_WORKSPACE/artifacts/testrun.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ + -k "not test_logging__offline_errors_are_written_to_logs_and_syslog and not test_failover and not test_logging__dns_resolution_issue_in_logs and not test_ad__user_authentication_when_provider_is_set_to_ldap_with_gss_spnego and not test_multithreaded_pac_client and not test_autofs__propagate_offline_status and not test_failover__ and not test_ipa__subids_configured" \ -vvv . |& tee $GITHUB_WORKSPACE/pytest.log - name: Upload artifacts From 5eda297eb1f1300f1091acd92f6a39ca1d14d4bb Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Thu, 21 May 2026 13:07:17 -0400 Subject: [PATCH 38/39] WIP IPA: Remove sdap_service related code --- src/providers/ipa/ipa_common.c | 293 +-------------------------------- src/providers/ipa/ipa_common.h | 9 - src/providers/ipa/ipa_dyndns.c | 14 -- src/providers/ipa/ipa_init.c | 20 +-- 4 files changed, 2 insertions(+), 334 deletions(-) diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index f147012b261..fbdeed88aba 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -922,275 +922,6 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, return ret; } -static void ipa_resolve_callback(void *private_data, struct fo_server *server) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct ipa_service *service; - struct resolv_hostent *srvaddr; - struct sockaddr *sockaddr; - char *new_uri; - const char *srv_name; - socklen_t sockaddr_len; - int ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n"); - return; - } - - service = talloc_get_type(private_data, struct ipa_service); - if (!service) { - DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Bad private_data\n"); - talloc_free(tmp_ctx); - return; - } - - srvaddr = fo_get_server_hostent(server); - if (!srvaddr) { - DEBUG(SSSDBG_CRIT_FAILURE, - "No hostent available for server (%s)\n", - fo_get_server_str_name(server)); - talloc_free(tmp_ctx); - return; - } - - sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT, &sockaddr_len); - if (sockaddr == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n"); - talloc_free(tmp_ctx); - return; - } - - srv_name = fo_get_server_name(server); - if (srv_name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n"); - talloc_free(tmp_ctx); - return; - } - - new_uri = talloc_asprintf(service, "ldap://%s", srv_name); - if (!new_uri) { - DEBUG(SSSDBG_OP_FAILURE, "Failed to copy URI ...\n"); - talloc_free(tmp_ctx); - return; - } - DEBUG(SSSDBG_TRACE_FUNC, "Constructed uri '%s'\n", new_uri); - - /* free old one and replace with new one */ - talloc_zfree(service->sdap->uri); - service->sdap->uri = new_uri; - talloc_zfree(service->sdap->sockaddr); - service->sdap->sockaddr = talloc_steal(service, sockaddr); - service->sdap->sockaddr_len = sockaddr_len; - - if (service->krb5_service->write_kdcinfo) { - ret = write_krb5info_file_from_fo_server(service->krb5_service, - server, - true, - SSS_KRB5KDC_FO_SRV, - NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "write to %s/kdcinfo.%s failed, authentication might fail.\n", - PUBCONF_PATH, service->krb5_service->realm); - } - } - - talloc_free(tmp_ctx); -} - -static errno_t _ipa_servers_init(struct be_ctx *ctx, - const char *fo_service, - struct ipa_service *service, - struct ipa_options *options, - const char *servers, - bool primary) -{ - TALLOC_CTX *tmp_ctx; - char **list = NULL; - char *ipa_domain; - int ret = 0; - int i; - int j; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - /* split server param into a list */ - ret = split_on_separator(tmp_ctx, servers, ',', true, true, &list, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n"); - goto done; - } - - for (j = 0; list[j]; j++) { - if (resolv_is_address(list[j])) { - DEBUG(SSSDBG_IMPORTANT_INFO, - "ipa_server [%s] is detected as IP address, " - "this can cause GSSAPI problems\n", list[j]); - } - } - - /* now for each one add a new server to the failover service */ - for (i = 0; list[i]; i++) { - - talloc_steal(service, list[i]); - - if (be_fo_is_srv_identifier(list[i])) { - if (!primary) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to add server [%s] to failover service: " - "SRV resolution only allowed for primary servers!\n", - list[i]); - continue; - } - - ipa_domain = dp_opt_get_string(options->basic, IPA_DOMAIN); - ret = be_fo_add_srv_server(ctx, fo_service, "ldap", ipa_domain, - BE_FO_PROTO_TCP, false, NULL); - if (ret) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n"); - goto done; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Added service lookup for service [%s]\n", - fo_service); - continue; - } - - /* It could be ipv6 address in square brackets. Remove - * the brackets if needed. */ - ret = remove_ipv6_brackets(list[i]); - if (ret != EOK) { - goto done; - } - - ret = be_fo_add_server(ctx, fo_service, list[i], 0, NULL, primary); - if (ret && ret != EEXIST) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n"); - goto done; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Added Server %s\n", list[i]); - } - -done: - talloc_free(tmp_ctx); - return ret; -} - -static inline errno_t -ipa_primary_servers_init(struct be_ctx *ctx, const char *fo_service, - struct ipa_service *service, struct ipa_options *options, - const char *servers) -{ - return _ipa_servers_init(ctx, fo_service, service, options, servers, true); -} - -static inline errno_t -ipa_backup_servers_init(struct be_ctx *ctx, const char *fo_service, - struct ipa_service *service, struct ipa_options *options, - const char *servers) -{ - return _ipa_servers_init(ctx, fo_service, service, options, servers, false); -} - -static int ipa_user_data_cmp(void *ud1, void *ud2) -{ - return strcasecmp((char*) ud1, (char*) ud2); -} - -int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, - const char *primary_servers, - const char *backup_servers, - const char *realm, - const char *ipa_service, - struct ipa_options *options, - struct ipa_service **_service) -{ - TALLOC_CTX *tmp_ctx; - struct ipa_service *service; - int ret; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - service = talloc_zero(tmp_ctx, struct ipa_service); - if (!service) { - ret = ENOMEM; - goto done; - } - service->sdap = talloc_zero(service, struct sdap_service); - if (!service->sdap) { - ret = ENOMEM; - goto done; - } - - service->krb5_service = krb5_service_new(service, ctx, - ipa_service, realm, - true, /* The configured value */ - 0, /* will be set later when */ - 0); /* the auth provider is set up */ - - if (!service->krb5_service) { - ret = ENOMEM; - goto done; - } - - ret = be_fo_add_service(ctx, ipa_service, ipa_user_data_cmp); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n"); - goto done; - } - - service->sdap->name = talloc_strdup(service, ipa_service); - if (!service->sdap->name) { - ret = ENOMEM; - goto done; - } - - service->sdap->kinit_service_name = service->krb5_service->name; - - if (!primary_servers) { - DEBUG(SSSDBG_CONF_SETTINGS, - "No primary servers defined, using service discovery\n"); - primary_servers = BE_SRV_IDENTIFIER; - } - - ret = ipa_primary_servers_init(ctx, ipa_service, service, options, primary_servers); - if (ret != EOK) { - goto done; - } - - if (backup_servers) { - ret = ipa_backup_servers_init(ctx, ipa_service, service, options, backup_servers); - if (ret != EOK) { - goto done; - } - } - - ret = be_fo_service_add_callback(memctx, ctx, ipa_service, - ipa_resolve_callback, service); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add failover callback!\n"); - goto done; - } - - ret = EOK; - -done: - if (ret == EOK) { - *_service = talloc_steal(memctx, service); - } - talloc_zfree(tmp_ctx); - return ret; -} - int ipa_get_autofs_options(struct ipa_options *ipa_opts, struct ldb_context *ldb, struct confdb_ctx *cdb, @@ -1330,9 +1061,6 @@ ipa_create_trust_options(TALLOC_CTX *mem_ctx, struct ipa_options *ipa_options = NULL; struct ipa_id_ctx *ipa_id_ctx = NULL; struct sdap_id_ctx *sdap_id_ctx = NULL; - const char *ipa_servers; - const char *ipa_backup_servers; - const char *service_name; errno_t ret; DEBUG(SSSDBG_TRACE_FUNC, "Trust is defined to domain '%s'\n", @@ -1348,25 +1076,6 @@ ipa_create_trust_options(TALLOC_CTX *mem_ctx, goto done; } - ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); - ipa_backup_servers = dp_opt_get_string(ipa_options->basic, IPA_BACKUP_SERVER); - - service_name = talloc_asprintf(ipa_options, "sd_%s", subdom->name); - if (service_name == NULL) { - ret = ENOMEM; - goto done; - } - - ret = ipa_service_init(ipa_options, be_ctx, ipa_servers, - ipa_backup_servers, subdom->realm, - service_name, ipa_options, - &ipa_options->service); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init IPA service [%d]: %s\n", - ret, sss_strerror(ret)); - goto done; - } - /* Set IPA SDAP options */ ipa_id_ctx = talloc_zero(mem_ctx, struct ipa_id_ctx); if (ipa_id_ctx == NULL) { @@ -1374,7 +1083,7 @@ ipa_create_trust_options(TALLOC_CTX *mem_ctx, goto done; } - sdap_id_ctx = sdap_id_ctx_new(mem_ctx, be_ctx, ipa_options->service->sdap); + sdap_id_ctx = sdap_id_ctx_new(mem_ctx, be_ctx, NULL); if (sdap_id_ctx == NULL) { ret = ENOMEM; goto done; diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index b2f5e9b343d..24574aef41e 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -39,7 +39,6 @@ #define IPA_ID_RANGE_MPG "ipaAutoPrivateGroups" struct ipa_service { - struct sdap_service *sdap; struct krb5_service *krb5_service; }; @@ -290,14 +289,6 @@ errno_t ipa_autofs_init(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *id_ctx, struct dp_method *dp_methods); -int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, - const char *primary_servers, - const char *backup_servers, - const char *realm, - const char *ipa_service, - struct ipa_options *options, - struct ipa_service **_service); - int ipa_sudo_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index 52cc9f0dd2b..b91b3cd662f 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -177,20 +177,6 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq) return; } - /* The following three checks are here to prevent SEGFAULT - * from ticket #3076. */ - if (ctx->service == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "service structure not initialized\n"); - ret = EINVAL; - goto done; - } - - if (ctx->service->sdap == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "sdap structure not initialized\n"); - ret = EINVAL; - goto done; - } - if (state->conn->uri == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "LDAP uri not set\n"); ret = EINVAL; diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index e8342201dd6..3f74fa1a2da 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -200,9 +200,6 @@ static errno_t ipa_init_options(TALLOC_CTX *mem_ctx, struct ipa_options **_ipa_options) { struct ipa_options *ipa_options; - const char *ipa_servers; - const char *ipa_backup_servers; - const char *realm; errno_t ret; ret = ipa_get_options(mem_ctx, be_ctx->cdb, be_ctx->conf_path, @@ -211,20 +208,6 @@ static errno_t ipa_init_options(TALLOC_CTX *mem_ctx, return ret; } - ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); - ipa_backup_servers = dp_opt_get_string(ipa_options->basic, IPA_BACKUP_SERVER); - realm = dp_opt_get_string(ipa_options->basic, IPA_KRB5_REALM); - - ret = ipa_service_init(ipa_options, be_ctx, ipa_servers, - ipa_backup_servers, realm, "IPA", ipa_options, - &ipa_options->service); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init IPA service [%d]: %s\n", - ret, sss_strerror(ret)); - talloc_free(ipa_options); - return ret; - } - *_ipa_options = ipa_options; return EOK; } @@ -245,7 +228,7 @@ static errno_t ipa_init_id_ctx(TALLOC_CTX *mem_ctx, goto done; } - sdap_id_ctx = sdap_id_ctx_new(mem_ctx, be_ctx, ipa_options->service->sdap); + sdap_id_ctx = sdap_id_ctx_new(mem_ctx, be_ctx, NULL); if (sdap_id_ctx == NULL) { ret = ENOMEM; goto done; @@ -526,7 +509,6 @@ static errno_t ipa_init_sdap_auth_ctx(TALLOC_CTX *mem_ctx, } sdap_auth_ctx->be = be_ctx; - sdap_auth_ctx->service = ipa_options->service->sdap; if (ipa_options->id == NULL) { talloc_free(sdap_auth_ctx); From 65c17939fa74dd2e55a0550fcd2650a86e64e6aa Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Thu, 21 May 2026 13:11:39 -0400 Subject: [PATCH 39/39] ci: Set temp --mh-topology=ipa --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69c8e9611d7..9da1b90d267 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -312,6 +312,7 @@ jobs: --output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ -k "not test_logging__offline_errors_are_written_to_logs_and_syslog and not test_failover and not test_logging__dns_resolution_issue_in_logs and not test_ad__user_authentication_when_provider_is_set_to_ldap_with_gss_spnego and not test_multithreaded_pac_client and not test_autofs__propagate_offline_status and not test_failover__ and not test_ipa__subids_configured" \ + --mh-topology=ipa \ --collect-only . |& tee $GITHUB_WORKSPACE/pytest-collect.log - name: Run tests @@ -333,6 +334,7 @@ jobs: --output-polarion-testrun=$GITHUB_WORKSPACE/artifacts/testrun.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ -k "not test_logging__offline_errors_are_written_to_logs_and_syslog and not test_failover and not test_logging__dns_resolution_issue_in_logs and not test_ad__user_authentication_when_provider_is_set_to_ldap_with_gss_spnego and not test_multithreaded_pac_client and not test_autofs__propagate_offline_status and not test_failover__ and not test_ipa__subids_configured" \ + --mh-topology=ipa \ -vvv . |& tee $GITHUB_WORKSPACE/pytest.log - name: Upload artifacts