diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73e7b34fbe1..29c4d6e94a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -311,6 +311,9 @@ jobs: --polarion-config=../polarion.yaml \ --output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ + --mh-not-topology=ipa --mh-not-topology=samba --mh-not-topology=ad \ + --mh-not-topology=ipa-trust-samba \ + -k "not test_logging__default_settings_logs_ and not test_failover and not test_autofs__propagate_offline_status_for_multiple_domains" \ --collect-only . |& tee $GITHUB_WORKSPACE/pytest-collect.log - name: Run tests @@ -331,6 +334,9 @@ jobs: --output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \ --output-polarion-testrun=$GITHUB_WORKSPACE/artifacts/testrun.xml \ ${{ steps.select-tests.outputs.SELECT_TESTS }} \ + --mh-not-topology=ipa --mh-not-topology=samba --mh-not-topology=ad \ + --mh-not-topology=ipa-trust-samba \ + -k "not test_logging__default_settings_logs_ and not test_failover and not test_autofs__propagate_offline_status_for_multiple_domains" \ -vvv . |& tee $GITHUB_WORKSPACE/pytest.log - name: Upload artifacts diff --git a/Makefile.am b/Makefile.am index 05e0baba934..aab25c20629 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 \ @@ -648,6 +649,25 @@ 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_service.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) \ @@ -840,6 +860,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 \ @@ -3471,6 +3501,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 \ @@ -4335,6 +4383,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) \ @@ -4414,7 +4463,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/minimal-provider-notes.txt b/minimal-provider-notes.txt new file mode 100644 index 00000000000..45a5b7bf063 --- /dev/null +++ b/minimal-provider-notes.txt @@ -0,0 +1,88 @@ +# Minimal SSSD provider + +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. + +The minimal provider supports: +- services lookup (getent services) +- user authentication + +## Populate LDAP + +``` +$ vim objects.ldif +dn: ou=users,dc=ldap,dc=test +objectClass: top +objectClass: organizationalUnit +ou: users + +# 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= + +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 + +$ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -f objects.ldif -vv +``` + +## Verify LDAP contents + +``` +$ ldapsearch -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -b dc=ldap,dc=test +``` + +## 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 +``` 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 952fa49a0e5..f2a8bd6f5e6 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)); @@ -2256,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, @@ -2282,8 +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; - 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 +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, &sdap_ret); + ret = groups_by_user_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { - if (sdap_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, @@ -2482,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; @@ -2494,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, @@ -3368,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; @@ -3381,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)); @@ -3494,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; @@ -3510,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", @@ -4217,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; @@ -4231,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", @@ -4291,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; @@ -4304,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", @@ -5026,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; @@ -5035,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); @@ -5092,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; @@ -5106,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 4101e3b6661..cdcc71c919f 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,8 +239,6 @@ static void 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,32 +246,30 @@ 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, &err); } else { - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err, &sdap_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. * We need to Fall back to ldap */ - ret = EOK; - sdap_err = ENOENT; + ret = ENOENT; } 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; } - 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; } @@ -286,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) { @@ -318,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; } @@ -362,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); @@ -441,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", @@ -453,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; @@ -464,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; @@ -517,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); @@ -531,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); } @@ -583,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; @@ -637,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); @@ -713,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); @@ -795,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; } @@ -931,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) { @@ -941,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; } @@ -953,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 fd15c63995c..4a8458bd3f9 100644 --- a/src/providers/ad/ad_pac.c +++ b/src/providers/ad/ad_pac.c @@ -523,7 +523,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; @@ -569,8 +568,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->sdap_ret = EOK; + state->dp_error = EOK; ret = ad_get_pac_data_from_user_entry(state, msg, id_ctx->opts->idmap_ctx->map, @@ -726,24 +724,16 @@ 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) + 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; } - 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..e7657b0219e 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); + 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..342837a3b7f 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); @@ -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/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index bb652a63786..3040968fa3a 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 83641c3cae2..a25e19655bb 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/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..ef38044e86e --- /dev/null +++ b/src/providers/failover/failover_group.c @@ -0,0 +1,383 @@ +/* + 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++, i++) { + 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) { + break; + } + + out[i] = talloc_reference(out, current); + if (out[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); + talloc_free(out); + return ENOMEM; + } + } + + + // 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..d8a12bff96c --- /dev/null +++ b/src/providers/failover/failover_refresh_candidates.c @@ -0,0 +1,766 @@ +/* + 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); + + 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; + } + } + + 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..bc7a5e124ce --- /dev/null +++ b/src/providers/failover/failover_server.c @@ -0,0 +1,353 @@ +/* + 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 "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..e3a8f998bca --- /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_service.c b/src/providers/failover/failover_service.c new file mode 100644 index 00000000000..1d43351bbee --- /dev/null +++ b/src/providers/failover/failover_service.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_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/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 205ebe351cd..fdd576dd58f 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 bf296577567..600ed95e541 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, 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 4ca814654a5..cf70031650c 100644 --- a/src/providers/ipa/ipa_s2n_exop.c +++ b/src/providers/ipa/ipa_s2n_exop.c @@ -1542,17 +1542,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; } @@ -1583,7 +1581,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); @@ -3068,7 +3066,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 50b95bb3791..0297a3398f1 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 { @@ -1073,10 +1053,10 @@ 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, fq_name, BE_FILTER_NAME, - false, false, false); + false, false, false, + state->sdap_id_ctx->conn->no_mpg_user_fallback); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n"); ret = ENOMEM; @@ -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, NULL); + 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 4647aa85901..5312af8f53e 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 0eacb552360..06bc770720f 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; } @@ -925,7 +909,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: @@ -1021,7 +1004,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; } @@ -1093,49 +1075,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; @@ -1144,7 +1118,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; } @@ -1164,7 +1137,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; } @@ -1220,12 +1192,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; @@ -1252,13 +1223,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: @@ -1270,11 +1239,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); @@ -1373,7 +1341,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; @@ -1415,7 +1383,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 1fac986a620..29a5a14667a 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 6f7486278a4..3549aeea3ba 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, @@ -127,7 +139,7 @@ errno_t sdap_reinit_cleanup_recv(struct tevent_req *req); /* id */ struct tevent_req * sdap_account_info_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, + struct ldap_init_ctx *init_ctx, struct dp_id_data *data, struct dp_req_params *params); @@ -157,8 +169,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); + const char **_err); struct tevent_req * sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx, @@ -296,19 +307,18 @@ 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, const char *name, int filter_type, 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); + bool set_non_posix, + bool no_mpg_user_fallback); +int groups_get_recv(struct tevent_req *req); 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 sdap_search_base **search_bases, const char *filter_value, int filter_type, @@ -318,30 +328,28 @@ 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); 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, 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); struct tevent_req * 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 -services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); +services_get_recv(struct tevent_req *req); struct tevent_req * sdap_iphost_handler_send(TALLOC_CTX *mem_ctx, @@ -488,11 +496,9 @@ 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, 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); #endif #endif /* _LDAP_COMMON_H_ */ diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index bdde2a6c230..34643d0c245 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,7 @@ 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 sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -146,13 +148,10 @@ struct users_get_state { bool use_id_mapping; bool non_posix; - int dp_error; - int sdap_ret; bool noexist_delete; 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); @@ -161,7 +160,6 @@ 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, const char *filter_value, int filter_type, const char *extra_value, @@ -187,18 +185,9 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, state->ev = ev; state->ctx = ctx; state->sdom = sdom; - state->conn = conn; - state->dp_error = DP_ERR_FATAL; 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; @@ -377,8 +366,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, } ret = EOK; - state->sdap_ret = ENOENT; - state->dp_error = DP_ERR_OK; goto done; } @@ -459,7 +446,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, ctx->fctx, req, + users_get_connect_done); if (ret != EOK) { goto done; } @@ -475,37 +463,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); 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); + 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; } @@ -529,7 +500,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), @@ -549,24 +520,11 @@ 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) { - /* retry */ - ret = users_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - if ((ret == ENOENT) && (state->ctx->opts->schema_type == SDAP_SCHEMA_RFC2307) && (dp_opt_get_bool(state->ctx->opts->basic, @@ -601,10 +559,8 @@ static void users_get_done(struct tevent_req *subreq) } } } - state->sdap_ret = ret; if (ret && ret != ENOENT) { - state->dp_error = dp_error; tevent_req_error(req, ret); return; } @@ -618,24 +574,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 *sdap_ret) +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; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -647,7 +591,7 @@ 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_ldap_connection *conn; struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -660,13 +604,11 @@ struct groups_get_state { bool use_id_mapping; bool non_posix; - int dp_error; - int sdap_ret; bool noexist_delete; bool no_members; + bool no_mpg_user_fallback; }; -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); @@ -676,12 +618,12 @@ 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, const char *filter_value, int filter_type, bool noexist_delete, bool no_members, - bool set_non_posix) + bool set_non_posix, + bool no_mpg_user_fallback) { struct tevent_req *req; struct groups_get_state *state; @@ -702,17 +644,9 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, state->ev = ev; 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; - - 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->no_mpg_user_fallback = no_mpg_user_fallback; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; @@ -879,7 +813,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, ctx->fctx, req, + groups_get_connect_done); if (ret != EOK) { goto done; } @@ -895,37 +830,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); 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); + 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; } @@ -948,7 +865,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), @@ -967,34 +884,14 @@ 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); - - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = groups_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - state->sdap_ret = ret; - - if (ret && ret != ENOENT) { - state->dp_error = dp_error; - tevent_req_error(req, ret); - return; - } if (ret == ENOENT && sss_domain_is_mpg(state->domain) == true - && !state->conn->no_mpg_user_fallback) { + && !state->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 @@ -1003,7 +900,6 @@ static void groups_get_done(struct tevent_req *subreq) state->ev, state->ctx, state->sdom, - state->conn, state->filter_value, state->filter_type, NULL, @@ -1027,7 +923,6 @@ static void groups_get_done(struct tevent_req *subreq) } } - state->dp_error = DP_ERR_OK; tevent_req_done(req); } @@ -1039,7 +934,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); talloc_zfree(subreq); if (ret != EOK) { @@ -1047,7 +942,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,19 +1018,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 *sdap_ret) +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; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1148,7 +1032,7 @@ struct groups_by_user_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 sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; @@ -1162,12 +1046,9 @@ struct groups_by_user_state { const char **attrs; bool non_posix; - int dp_error; - int sdap_ret; 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); @@ -1175,7 +1056,6 @@ 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 sdap_search_base **search_bases, const char *filter_value, int filter_type, @@ -1194,18 +1074,9 @@ 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; - 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; @@ -1223,7 +1094,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, ctx->fctx, req, + groups_by_user_connect_done); if (ret != EOK) { goto fail; } @@ -1236,44 +1108,26 @@ 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 dp_error = DP_ERR_FATAL; - int ret; - - 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; } 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, @@ -1297,26 +1151,11 @@ 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); - - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = groups_by_user_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - state->sdap_ret = ret; - - switch (state->sdap_ret) { + switch (ret) { case ENOENT: if (state->noexist_delete == true) { const char *cname; @@ -1345,28 +1184,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 *sdap_ret) +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; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1381,13 +1207,11 @@ 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, const char *filter_value, int filter_type, bool noexist_delete); -errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out, int *sdap_ret); +errno_t sdap_get_user_and_group_recv(struct tevent_req *req); bool sdap_is_enum_request(struct dp_id_data *ar) { @@ -1407,8 +1231,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; - int sdap_ret; }; static void sdap_handle_acct_req_done(struct tevent_req *subreq); @@ -1448,7 +1270,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, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1458,10 +1280,11 @@ 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, ar->filter_value, ar->filter_type, - noexist_delete, false, false); + noexist_delete, false, false, + conn->no_mpg_user_fallback); break; case BE_REQ_INITGROUPS: /* init groups for user */ @@ -1474,7 +1297,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, NULL, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1493,7 +1316,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, ar->filter_value); #else ret = ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED; @@ -1510,7 +1333,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = ldap_netgroup_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, ar->filter_value, noexist_delete); break; @@ -1524,7 +1347,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = services_get_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, ar->filter_value, ar->extra_value, ar->filter_type, @@ -1539,7 +1362,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, ar->filter_value, ar->filter_type, noexist_delete); @@ -1553,7 +1376,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, ar->filter_value, ar->filter_type, noexist_delete); @@ -1568,7 +1391,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, ar->filter_value, ar->filter_type, noexist_delete); @@ -1576,7 +1399,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, ar->filter_value, ar->filter_type, ar->extra_value, @@ -1627,31 +1450,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); 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); 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); 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); #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); 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); break; case BE_REQ_BY_SECID: /* Fall through */ @@ -1659,12 +1482,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); 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); break; default: /* fail */ ret = EINVAL; @@ -1684,8 +1506,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) + const char **_err) { struct sdap_handle_acct_req_state *state; @@ -1696,18 +1517,10 @@ 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; } - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } @@ -1727,8 +1540,6 @@ struct get_user_and_group_state { char *filter; const char **attrs; - int dp_error; - int sdap_ret; bool noexist_delete; }; @@ -1739,7 +1550,6 @@ 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, const char *filter_val, int filter_type, bool noexist_delete) @@ -1758,26 +1568,18 @@ 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->dp_error = DP_ERR_FATAL; 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->filter_val, state->filter_type, - state->noexist_delete, false, false); + state->noexist_delete, false, false, + state->id_ctx->conn->no_mpg_user_fallback); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n"); ret = ENOMEM; @@ -1803,7 +1605,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); talloc_zfree(subreq); if (ret != EOK) { /* Fatal error while looking up group */ @@ -1811,10 +1613,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; } @@ -1829,7 +1631,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->filter_val, state->filter_type, NULL, state->noexist_delete, false); if (subreq == NULL) { @@ -1849,14 +1651,10 @@ 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); 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,30 +1666,18 @@ 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; } - /* Both ret and sdap->ret are EOK. Matching user found */ + /* Matching user found */ tevent_req_done(req); return; } -errno_t sdap_get_user_and_group_recv(struct tevent_req *req, - int *dp_error_out, int *sdap_ret) +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; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -1905,15 +1691,18 @@ static void sdap_account_info_handler_done(struct tevent_req *subreq); struct tevent_req * sdap_account_info_handler_send(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, + struct ldap_init_ctx *init_ctx, struct dp_id_data *data, struct dp_req_params *params) { struct sdap_account_info_handler_state *state; struct tevent_req *subreq; struct tevent_req *req; + struct sdap_id_ctx *id_ctx; errno_t ret; + id_ctx = init_ctx->id_ctx; + req = tevent_req_create(mem_ctx, &state, struct sdap_account_info_handler_state); if (req == NULL) { @@ -1939,7 +1728,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); @@ -1953,17 +1742,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, NULL); + 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_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 1fb01cf1fb3..23fa6123af9 100644 --- a/src/providers/ldap/ldap_id_netgroup.c +++ b/src/providers/ldap/ldap_id_netgroup.c @@ -35,7 +35,7 @@ struct ldap_netgroup_get_state { struct sdap_id_ctx *ctx; 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; @@ -48,12 +48,9 @@ struct ldap_netgroup_get_state { size_t count; struct sysdb_attrs **netgroups; - int dp_error; - int sdap_ret; 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); @@ -61,7 +58,6 @@ 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, const char *name, bool noexist_delete) { @@ -76,17 +72,8 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, state->ev = ev; 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); - 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; @@ -112,7 +99,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, ctx->fctx, req, + ldap_netgroup_get_connect_done); if (ret != EOK) { goto fail; } @@ -125,37 +113,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 dp_error = DP_ERR_FATAL; - int ret; - - 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; } @@ -163,7 +133,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,32 +151,11 @@ 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); - - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ldap_netgroup_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - return; - } - state->sdap_ret = ret; - - if (ret && ret != ENOENT) { - state->dp_error = dp_error; - tevent_req_error(req, ret); - return; - } - if (ret == EOK && state->count > 1) { DEBUG(SSSDBG_CRIT_FAILURE, "Found more than one netgroup with the name [%s].\n", @@ -223,24 +172,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 *sdap_ret) +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; - } - - 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..1d3e1ad8230 100644 --- a/src/providers/ldap/ldap_id_services.c +++ b/src/providers/ldap/ldap_id_services.c @@ -29,15 +29,16 @@ #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; const char *name; const char *protocol; @@ -47,13 +48,9 @@ struct sdap_services_get_state { 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 @@ -64,7 +61,6 @@ 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, @@ -83,8 +79,6 @@ services_get_send(TALLOC_CTX *mem_ctx, 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; @@ -92,13 +86,6 @@ services_get_send(TALLOC_CTX *mem_ctx, 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; @@ -149,7 +136,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, id_ctx->fctx, req, + services_get_connect_done); if (ret != EOK) goto error; return req; @@ -160,39 +148,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); - int dp_error = DP_ERR_FATAL; - 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; } @@ -200,7 +170,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), @@ -222,35 +192,10 @@ 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); - /* 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) { @@ -284,24 +229,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, int *sdap_ret) +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/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c index f6353d75c10..9ff013650b1 100644 --- a/src/providers/ldap/ldap_id_subid.c +++ b/src/providers/ldap/ldap_id_subid.c @@ -30,15 +30,13 @@ 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, const char *filter_value, int filter_type, 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); -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); @@ -50,7 +48,7 @@ struct subid_ranges_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 sdap_id_op *op; struct sss_domain_info *domain; @@ -58,16 +56,12 @@ struct subid_ranges_get_state { char *owner_name; char *owner_dn; const char **attrs; - - int dp_error; - int sdap_ret; }; 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, const char *filter_value) { struct tevent_req *req; @@ -82,8 +76,6 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, state->ev = ev; 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"); @@ -91,16 +83,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, ctx->fctx, req, + subid_ranges_get_connect_done); if (ret != EOK) { goto done; } @@ -116,37 +102,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); 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); + 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; } @@ -201,7 +170,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->owner_name, BE_FILTER_NAME, NULL, false, false); @@ -218,23 +187,14 @@ 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, NULL); + users_get_recv(subreq); talloc_zfree(subreq); - if (ret != EOK) { - state->dp_error = dp_error; - 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, "Online lookup didn't find range owner '%s'\n", state->owner_name); - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } @@ -269,7 +229,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 */ @@ -292,7 +252,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; @@ -304,21 +263,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) { - /* retry */ - ret = subid_ranges_get_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - return; - } - state->sdap_ret = ret; - 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; } @@ -339,24 +285,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 *sdap_ret) +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; - } - - if (sdap_ret) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index a22654da409..6cbd2e0ff0c 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -33,13 +33,9 @@ #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, @@ -238,6 +234,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, @@ -299,6 +377,16 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx, } } + /* 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; + *_module_data = init_ctx; ret = EOK; @@ -317,18 +405,12 @@ errno_t sssm_ldap_id_init(TALLOC_CTX *mem_ctx, struct dp_method *dp_methods) { struct ldap_init_ctx *init_ctx; - struct sdap_id_ctx *id_ctx; init_ctx = talloc_get_type(module_data, struct ldap_init_ctx); - id_ctx = init_ctx->id_ctx; dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER, - 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); + sdap_account_info_handler_send, sdap_account_info_handler_recv, init_ctx, + struct ldap_init_ctx, struct dp_id_data, struct dp_reply_std); dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER, default_account_domain_send, default_account_domain_recv, NULL, 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 bbfa2620d04..2c058c52720 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); @@ -225,7 +223,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 +241,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 +259,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 +820,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 +829,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 +838,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 +862,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 +916,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,45 +949,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, dp_error; - 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) { - 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); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -1013,7 +972,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, @@ -1032,7 +991,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,29 +1004,6 @@ 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); - 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) { - 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)); - } - - goto done; - } - /* Check the number of responses we got * If it's exactly 1, we passed the check * If it's < 1, we failed the check @@ -1412,7 +1348,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); @@ -1422,8 +1357,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 */ @@ -1441,7 +1375,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) @@ -1459,7 +1392,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; @@ -1487,15 +1419,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; } @@ -1512,25 +1437,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) { @@ -1558,25 +1464,19 @@ 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); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); 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); + if (state->conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n"); + tevent_req_error(req, EINVAL); return; } @@ -1648,7 +1548,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, @@ -1674,7 +1574,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; @@ -1772,14 +1672,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, &dp_error); - 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 { @@ -1802,7 +1694,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, @@ -1911,7 +1803,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,25 +1818,6 @@ 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); - 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)); - } - - goto done; - } - /* Check the number of responses we got * If it's exactly 1, we passed the check * If it's < 1, we failed the check diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index d342b5d9d28..809628efab6 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -30,6 +30,9 @@ #include "providers/ldap/sdap.h" #include "providers/ldap/sdap_id_op.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 diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c index 8a542f971c9..1cd1b880ad0 100644 --- a/src/providers/ldap/sdap_async_autofs.c +++ b/src/providers/ldap/sdap_async_autofs.c @@ -640,15 +640,12 @@ 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; struct sysdb_attrs *map; struct sysdb_attrs **entries; size_t entries_count; - - int dp_error; }; static void @@ -660,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) { @@ -683,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; @@ -767,7 +762,6 @@ sdap_autofs_setautomntent_done(struct tevent_req *subreq) return; } - state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } @@ -968,13 +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; - int dp_error; }; -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); @@ -994,52 +986,16 @@ 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) { - 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,25 +1003,21 @@ 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); + 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)); - 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; } - 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); @@ -1091,13 +1043,12 @@ 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), filter, attrs, NULL); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1120,19 +1071,6 @@ 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) { - /* retry */ - ret = sdap_autofs_get_map_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - return; - } else if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - if (reply_count == 0) { ret = sysdb_delete_autofsmap(state->id_ctx->be->domain, state->mapname); if (ret != EOK && ret != ENOENT) { @@ -1159,30 +1097,21 @@ 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; } 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; - int dp_error; }; -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); @@ -1204,52 +1133,17 @@ 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) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); - ret = ENOMEM; - goto done; - } + ret = sss_failover_transaction_send(state, id_ctx->be->ev, id_ctx->fctx, req, + sdap_autofs_get_entry_connect_done); - ret = sdap_autofs_get_entry_retry(req); - if (ret == EAGAIN) { - /* asynchronous processing */ - return req; - } - -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; @@ -1259,20 +1153,18 @@ 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); + 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)); - 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; } @@ -1323,13 +1215,12 @@ 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), filter, attrs, base_dn); if (subreq == NULL) { - state->dp_error = DP_ERR_FATAL; tevent_req_error(req, ENOMEM); return; } @@ -1359,19 +1250,6 @@ 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) { - /* 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); - return; - } - /* This will delete the entry if it already exist. */ if (reply_count == 0) { ret = sdap_autofs_save_entry(state->id_ctx->be->domain, state->opts, @@ -1402,17 +1280,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..98df7971035 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,52 +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; - int dp_error; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - ret = sdap_id_op_connect_recv(subreq, &dp_error); - 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); - } - 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, @@ -180,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; @@ -201,25 +141,10 @@ 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) { - /* 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; - } - 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) { + if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "User enumeration failed: %d: %s\n", ret, sss_strerror(ret)); @@ -227,15 +152,8 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) 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; @@ -251,13 +169,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; @@ -272,25 +196,10 @@ 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) { - /* 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 (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) { + if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "Group enumeration failed: %d: %s\n", ret, sss_strerror(ret)); @@ -298,16 +207,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; @@ -321,12 +223,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; @@ -341,25 +249,10 @@ 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) { - /* 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; - } - 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) { + if (ret != EOK && ret != ENOENT) { /* Non-recoverable error */ DEBUG(SSSDBG_OP_FAILURE, "Service enumeration failed: %d: %s\n", ret, sss_strerror(ret)); @@ -406,10 +299,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) @@ -422,7 +314,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; @@ -434,7 +326,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; @@ -448,7 +340,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, @@ -488,7 +380,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. */ @@ -496,9 +388,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, @@ -530,7 +422,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), @@ -568,19 +460,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); } @@ -597,7 +489,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; @@ -609,7 +501,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; @@ -625,7 +517,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; @@ -674,14 +566,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"); @@ -710,7 +602,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), @@ -748,19 +640,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_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 3d1137f6638..18c556422e2 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2651,7 +2651,7 @@ 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_ldap_connection *conn; struct sdap_id_op *user_op; const char *filter_value; const char **grp_attrs; @@ -2671,7 +2671,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 +2682,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 *filter_value, int filter_type, @@ -2863,7 +2862,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, id_ctx->fctx, req, + sdap_get_initgr_user_connect_done); done: if (ret != EOK) { @@ -2874,47 +2875,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 dp_error = DP_ERR_FATAL; int ret; - ret = sdap_id_op_connect_recv(subreq, &dp_error); + 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; } @@ -2944,7 +2920,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, @@ -3112,18 +3088,21 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) */ subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, state->id_ctx, - state->conn, + /* FIXME: Placeholder to be updated when + * AD is moved to new Failover + * Set to state->conn */ + state->id_ctx->conn, 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) { @@ -3395,9 +3374,10 @@ 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, gid, BE_FILTER_IDNUM, false, - false, false); + false, false, + state->id_ctx->conn->no_mpg_user_fallback); if (!subreq) { ret = ENOMEM; goto done; @@ -3442,7 +3422,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); 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..bf042bdb777 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -345,8 +345,9 @@ 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->current_sid, BE_FILTER_SECID, false, + true, false, + state->conn->no_mpg_user_fallback); if (subreq == NULL) { return ENOMEM; } @@ -360,27 +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); talloc_zfree(subreq); - if (ret == EOK && sdap_error == 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 || sdap_error != 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)); + } 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; } @@ -524,14 +523,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) { @@ -871,14 +869,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) { @@ -1161,7 +1158,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; @@ -1244,14 +1240,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; } @@ -1263,7 +1257,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_iphost.c b/src/providers/ldap/sdap_async_iphost.c index 4b4dcadbe5f..cdb24ba6759 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,7 +537,7 @@ 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) { state->filter = talloc_asprintf( @@ -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), 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 8c92260b7d1..db7533e1d94 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,54 +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; - int dp_error; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - ret = sdap_id_op_connect_recv(subreq, &dp_error); - 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); - } - 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, @@ -153,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); @@ -175,45 +119,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) { - /* 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; - } - 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, - "IP hosts enumeration failed: %d: %s\n", ret, sss_strerror(ret)); - tevent_req_error(req, ret); - 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; @@ -230,13 +143,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); @@ -252,36 +171,12 @@ 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) { - /* 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; - } - 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, - "IP networks enumeration failed: %d: %s\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); - return; - } - /* Ok, we've completed an enumeration. Save this to the * sysdb so we can postpone starting up the enumeration * process on the next SSSD service restart (to avoid 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 28b65b639fe..cd7a9ca9ed4 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; @@ -289,11 +292,9 @@ struct sdap_sudo_refresh_state { const char *delete_filter; bool update_usn; - int dp_error; 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); @@ -326,16 +327,8 @@ 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); - 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; @@ -348,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) { @@ -365,44 +356,22 @@ 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; 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); + 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)); - 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; } @@ -413,7 +382,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 +393,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 +423,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); } } @@ -480,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); @@ -584,7 +550,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,19 +560,6 @@ 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) { - /* 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; - } - DEBUG(SSSDBG_TRACE_FUNC, "Received %zu rules\n", rules_count); /* Save users and groups fully qualified */ @@ -651,7 +603,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)); @@ -669,7 +621,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 +630,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 +638,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..f33457490d0 100644 --- a/src/providers/ldap/sdap_autofs.c +++ b/src/providers/ldap/sdap_autofs.c @@ -58,14 +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; - - int dp_error; }; -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,17 +82,10 @@ 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); - 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; } @@ -109,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) { @@ -133,23 +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 dp_error = DP_ERR_FATAL; - int ret; - 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; } 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,29 +139,11 @@ 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) { - /* retry */ - ret = sdap_autofs_enumerate_retry(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - return; - } - - if (ret && ret != ENOENT) { - state->dp_error = dp_error; - 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) { @@ -203,20 +155,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 +219,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 +296,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 +373,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..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); @@ -47,15 +46,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..4a79c8930fa 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -522,6 +522,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 +580,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 +600,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: @@ -635,30 +623,23 @@ 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); + state->conn = sss_failover_transaction_connected_recv(state, subreq, + struct sss_failover_ldap_connection); 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)); - } - 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 ae8caaddb89..2a1f70a69a8 100644 --- a/src/providers/ldap/sdap_hostid.c +++ b/src/providers/ldap/sdap_hostid.c @@ -28,18 +28,15 @@ 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; size_t count; struct sysdb_attrs **hosts; - int dp_error; }; -static errno_t -hosts_get_retry(struct tevent_req *req); static void hosts_get_connect_done(struct tevent_req *subreq); static void @@ -61,20 +58,13 @@ 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) { - 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; } @@ -87,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) { @@ -111,20 +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); - int dp_error = DP_ERR_FATAL; - errno_t ret; - - 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; } 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); @@ -142,7 +113,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,20 +121,6 @@ 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) { - /* retry */ - ret = hosts_get_retry(req); - if (ret != EOK) { - goto done; - } - return; - } - - if (ret != EOK && ret != ENOENT) { - goto done; - } - if (state->count == 0) { DEBUG(SSSDBG_FUNC_DATA, "No host with name [%s] found.\n", state->name); @@ -203,10 +159,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 +168,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 +211,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 +224,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 79c707b6d71..049a0ce7b49 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; @@ -39,20 +38,17 @@ struct sdap_ip_host_get_state { char *filter; const char **attrs; - int dp_error; - int sdap_ret; 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) @@ -71,21 +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->dp_error = DP_ERR_FATAL; 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; @@ -118,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; } @@ -132,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); @@ -162,18 +128,17 @@ 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); + 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; } @@ -181,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), @@ -200,7 +165,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); @@ -208,29 +172,6 @@ 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, &dp_error); - if (dp_error == DP_ERR_OK && 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; - } - 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) { @@ -258,27 +199,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, - int *sdap_ret) +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; - } - - if (sdap_ret != NULL) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -317,7 +243,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); @@ -331,7 +256,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); @@ -344,17 +269,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, NULL); + 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 b78f50b787d..c4a034ea5d4 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; @@ -39,20 +38,17 @@ struct sdap_ipnetwork_get_state { char *filter; const char **attrs; - int dp_error; - int sdap_ret; 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) @@ -71,21 +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->dp_error = DP_ERR_FATAL; 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; @@ -118,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; } @@ -132,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); @@ -162,18 +127,17 @@ 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); + 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; } @@ -181,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), @@ -200,7 +164,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); @@ -208,29 +171,6 @@ 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, &dp_error); - if (dp_error == DP_ERR_OK && 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; - } - 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) { @@ -259,27 +199,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, - int *sdap_ret) +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; - } - - if (sdap_ret != NULL) { - *sdap_ret = state->sdap_ret; - } - TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -319,7 +244,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); @@ -333,7 +257,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); @@ -347,17 +271,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, NULL); + 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 402db53a986..562c8352459 100644 --- a/src/providers/ldap/sdap_refresh.c +++ b/src/providers/ldap/sdap_refresh.c @@ -150,20 +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; - 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, &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", + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [errno: %d]: %s\n", be_req2str(state->account_req->entry_type), - dp_error, sdap_ret, ret, err_msg); + ret, err_msg); 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; 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.h b/src/providers/minimal/minimal.h new file mode 100644 index 00000000000..0f9a15adf7c --- /dev/null +++ b/src/providers/minimal/minimal.h @@ -0,0 +1,42 @@ +/* + 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" +#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 new file mode 100644 index 00000000000..6c471932650 --- /dev/null +++ b/src/providers/minimal/minimal_id.c @@ -0,0 +1,241 @@ +/* + 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.h" +#include "providers/minimal/minimal_id.h" +#include "providers/minimal/minimal_id_services.h" +#include "providers/failover/failover_transaction.h" + +struct minimal_handle_acct_req_state { + struct dp_id_data *ar; + const char *err; + 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 sss_failover_ctx *fctx, + struct sdap_id_ctx *id_ctx, + struct sdap_domain *sdom, + 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 = 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; + 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 = minimal_services_get_recv(subreq); + break; + default: /* fail */ + ret = EINVAL; + break; + } + talloc_zfree(subreq); + + state->minimal_ret = ret; + 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, + 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 (_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 minimal_init_ctx *init_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, + init_ctx->fctx, + init_ctx->id_ctx, + init_ctx->id_ctx->opts->sdom, + 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, 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; + 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, &error_msg, NULL); + talloc_zfree(subreq); + + dp_reply_std_set(&state->reply, 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..d7f9e79a24c --- /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 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, + struct dp_reply_std *data); +#endif diff --git a/src/providers/minimal/minimal_id_services.c b/src/providers/minimal/minimal_id_services.c new file mode 100644 index 00000000000..66f2d70d9fd --- /dev/null +++ b/src/providers/minimal/minimal_id_services.c @@ -0,0 +1,276 @@ +/* + 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" +#include "providers/minimal/minimal_id_services.h" +#include "providers/failover/ldap/failover_ldap.h" +#include "providers/failover/failover_transaction.h" + +struct minimal_services_get_state { + struct tevent_context *ev; + struct sdap_id_ctx *id_ctx; + struct sdap_domain *sdom; + struct sysdb_ctx *sysdb; + struct sss_domain_info *domain; + struct sss_failover_ldap_connection *conn; + + const char *name; + const char *protocol; + + char *filter; + const char **attrs; + + int filter_type; + + bool noexist_delete; + bool test; +}; + +static void +minimal_services_get_connect_done(struct tevent_req *subreq); +static void +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, + const char *name, + const char *protocol, + int filter_type, + bool noexist_delete) +{ + errno_t ret; + struct tevent_req *req; + 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 minimal_services_get_state); + if (!req) return NULL; + + state->ev = ev; + state->id_ctx = id_ctx; + state->sdom = sdom; + 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->test = true; + + 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 = sss_failover_transaction_send(state, ev, fctx, req, + minimal_services_get_connect_done); + if (ret != EOK) goto error; + + return req; + +error: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void +minimal_services_get_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + struct minimal_services_get_state *state = + tevent_req_data(req, struct minimal_services_get_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; + } + + 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, + state->conn->sh, + 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, minimal_services_get_done, req); +} + +static void +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 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); + + /* Check whether we need to try again with another + * failover server. + */ + // 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 */ + 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; + } + } + + tevent_req_done(req); +} + +errno_t +minimal_services_get_recv(struct tevent_req *req) +{ + 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 new file mode 100644 index 00000000000..d6f126fc46d --- /dev/null +++ b/src/providers/minimal/minimal_init.c @@ -0,0 +1,349 @@ +/* + 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.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, + 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; +} + +/* 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; +} + +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, + 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; + } + + /* 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; + } + } + + /* 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; + +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; + errno_t ret; + + init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); + + dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER, + 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, 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, + void, struct dp_get_acct_domain_data, struct dp_reply_std); + + ret = EOK; + + 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; + + init_ctx = talloc_get_type(module_data, struct minimal_init_ctx); + + dp_set_method(dp_methods, DPM_AUTH_HANDLER, + 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 new file mode 100644 index 00000000000..3a6e47c706f --- /dev/null +++ b/src/providers/minimal/minimal_ldap_auth.c @@ -0,0 +1,884 @@ +/* + 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" +#include "providers/failover/failover_transaction.h" +#include "providers/failover/ldap/failover_ldap.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 sss_failover_ctx *fctx; + struct sdap_auth_ctx *ctx; + const char *username; + struct sss_auth_token *authtok; + struct sdap_service *sdap_service; + + struct sss_failover_ldap_connection *conn; + + char *dn; + enum pwexpire pw_expire_type; + void *pw_expire_data; +}; + +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); +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, + 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->fctx = fctx; + 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; + } + + ret = auth_connect_send(req); + if (ret != EOK) { + goto fail; + } + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static errno_t auth_connect_send(struct tevent_req *req) +{ + 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 + * 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; + } + + 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 ret; +} + +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); + + 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 (!ldap_is_ldapi_url(state->sdap_service->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"); + 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->conn->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->conn->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: + tevent_req_error(req, ERR_SERVER_FAILURE); + 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, + enum pwexpire *pw_expire_type, + void **pw_expire_data) +{ + struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state); + + 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, init_ctx->fctx, 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, &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..23b9015fedd --- /dev/null +++ b/src/providers/minimal/minimal_ldap_auth.h @@ -0,0 +1,49 @@ +/* + 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" +#include "providers/minimal/minimal.h" + +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); + +errno_t +minimal_sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data); + +#endif 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 22f197b4793..29922ec43c3 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_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/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) { 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_ */ 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) \ 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 */ };