From e115c25af2df3549fb44b260e516d8c93d2adc8a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 20 Nov 2009 12:11:28 -0500 Subject: Add initial failover support for ldap and ipa The retun values are still not directly used with ldap libraries that still do their own name resolution, but this patch introduces a very basic framework to have a multiple providers in one domain use and share a single failover service if they want to. --- server/providers/ipa/ipa_access.c | 6 +- server/providers/ipa/ipa_common.c | 165 ++++++++++++++++++++++++++++++-------- server/providers/ipa/ipa_common.h | 10 +++ server/providers/ipa/ipa_init.c | 50 +++++++++--- 4 files changed, 183 insertions(+), 48 deletions(-) (limited to 'server/providers/ipa') diff --git a/server/providers/ipa/ipa_access.c b/server/providers/ipa/ipa_access.c index 230cabc1..675e7c20 100644 --- a/server/providers/ipa/ipa_access.c +++ b/server/providers/ipa/ipa_access.c @@ -386,7 +386,8 @@ static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, talloc_zfree(sdap_ctx->gsh); } - subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, NULL); + subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, + sdap_ctx->be, sdap_ctx->service, NULL); if (!subreq) { DEBUG(1, ("sdap_cli_connect_send failed.\n")); ret = ENOMEM; @@ -850,7 +851,8 @@ static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx, talloc_zfree(sdap_ctx->gsh); } - subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, NULL); + subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, + sdap_ctx->be, sdap_ctx->service, NULL); if (!subreq) { DEBUG(1, ("sdap_cli_connect_send failed.\n")); ret = ENOMEM; diff --git a/server/providers/ipa/ipa_common.c b/server/providers/ipa/ipa_common.c index 38e4d53d..2bd9c76d 100644 --- a/server/providers/ipa/ipa_common.c +++ b/server/providers/ipa/ipa_common.c @@ -22,6 +22,7 @@ along with this program. If not, see . */ +#include #include #include "providers/ipa/ipa_common.h" @@ -251,24 +252,6 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, goto done; } - /* set ldap_uri */ - if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_URI)) { - value = talloc_asprintf(tmpctx, "ldap://%s", - dp_opt_get_string(ipa_opts->basic, - IPA_SERVER)); - if (!value) { - ret = ENOMEM; - goto done; - } - ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_URI, value); - if (ret != EOK) { - goto done; - } - DEBUG(6, ("Option %s set to %s\n", - ipa_opts->id->basic[SDAP_URI].opt_name, - dp_opt_get_string(ipa_opts->id->basic, SDAP_URI))); - } - if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_SEARCH_BASE)) { ret = domain_to_basedn(tmpctx, dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN), @@ -429,22 +412,6 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, goto done; } - /* set KDC */ - if (NULL == dp_opt_get_string(ipa_opts->auth, KRB5_KDC)) { - value = dp_opt_get_string(ipa_opts->basic, IPA_SERVER); - if (!value) { - ret = ENOMEM; - goto done; - } - ret = dp_opt_set_string(ipa_opts->auth, KRB5_KDC, value); - if (ret != EOK) { - goto done; - } - DEBUG(6, ("Option %s set to %s\n", - ipa_opts->auth[KRB5_KDC].opt_name, - dp_opt_get_string(ipa_opts->auth, KRB5_KDC))); - } - /* set krb realm */ if (NULL == dp_opt_get_string(ipa_opts->auth, KRB5_REALM)) { value = dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN); @@ -473,3 +440,133 @@ done: } return ret; } + +static void ipa_resolve_callback(void *private_data, struct fo_server *server) +{ + struct ipa_service *service; + struct hostent *srvaddr; + char *address; + char *new_uri; + int ret; + + service = talloc_get_type(private_data, struct ipa_service); + if (!service) { + DEBUG(1, ("FATAL: Bad private_data\n")); + return; + } + + srvaddr = fo_get_server_hostent(server); + if (!srvaddr) { + DEBUG(1, ("FATAL: No hostent available for server (%s)\n", + fo_get_server_name(server))); + return; + } + + address = talloc_asprintf(service, srvaddr->h_name); + if (!address) { + DEBUG(1, ("Failed to copy address ...\n")); + return; + } + + new_uri = talloc_asprintf(service, "ldap://%s", address); + if (!new_uri) { + DEBUG(2, ("Failed to copy URI ...\n")); + talloc_free(address); + return; + } + + /* free old one and replace with new one */ + talloc_zfree(service->sdap->uri); + service->sdap->uri = new_uri; + talloc_zfree(service->krb_server->address); + service->krb_server->address = address; + + /* set also env variable */ + ret = setenv(SSSD_KRB5_KDC, address, 1); + if (ret != EOK) { + DEBUG(2, ("setenv %s failed, authentication might fail.\n", + SSSD_KRB5_KDC)); + } +} + +int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, + const char *servers, struct ipa_service **_service) +{ + TALLOC_CTX *tmp_ctx; + struct ipa_service *service; + char **list = NULL; + int count = 0; + int ret; + int i; + + tmp_ctx = talloc_new(memctx); + if (!tmp_ctx) { + return ENOMEM; + } + + service = talloc_zero(tmp_ctx, struct ipa_service); + if (!service) { + ret = ENOMEM; + goto done; + } + service->sdap = talloc_zero(service, struct sdap_service); + if (!service->sdap) { + ret = ENOMEM; + goto done; + } + service->krb_server = talloc_zero(service, struct krb_server); + if (!service->krb_server) { + ret = ENOMEM; + goto done; + } + + ret = be_fo_add_service(ctx, "IPA"); + if (ret != EOK) { + DEBUG(1, ("Failed to create failover service!\n")); + goto done; + } + + service->sdap->name = talloc_strdup(service, "IPA"); + if (!service->sdap->name) { + ret = ENOMEM; + goto done; + } + + /* split server parm into a list */ + ret = sss_split_list(tmp_ctx, servers, ", ", &list, &count); + if (ret != EOK) { + DEBUG(1, ("Failed to parse server list!\n")); + goto done; + } + + /* now for each one add a new server to the failover service */ + for (i = 0; i < count; i++) { + + talloc_steal(service, list[i]); + + ret = be_fo_add_server(ctx, "IPA", list[i], 0, NULL); + if (ret && ret != EEXIST) { + DEBUG(0, ("Failed to add server\n")); + goto done; + } + + DEBUG(6, ("Added Server %s\n", list[i])); + } + + ret = be_fo_service_add_callback(memctx, ctx, "IPA", + ipa_resolve_callback, service); + if (ret != EOK) { + DEBUG(1, ("Failed to add failover callback!\n")); + goto done; + } + + ret = EOK; + +done: + if (ret == EOK) { + *_service = talloc_steal(memctx, service); + } + talloc_zfree(tmp_ctx); + return ret; +} + diff --git a/server/providers/ipa/ipa_common.h b/server/providers/ipa/ipa_common.h index 21e6e1a3..8d0840c5 100644 --- a/server/providers/ipa/ipa_common.h +++ b/server/providers/ipa/ipa_common.h @@ -27,6 +27,11 @@ #include "providers/ldap/ldap_common.h" #include "providers/krb5/krb5_common.h" +struct ipa_service { + struct sdap_service *sdap; + struct krb_server *krb_server; +}; + enum ipa_basic_opt { IPA_DOMAIN = 0, IPA_SERVER, @@ -38,6 +43,8 @@ enum ipa_basic_opt { struct ipa_options { struct dp_option *basic; + struct ipa_service *service; + /* id provider */ struct sdap_options *id; struct sdap_id_ctx *id_ctx; @@ -64,4 +71,7 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, const char *conf_path, struct dp_option **_opts); +int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, + const char *servers, struct ipa_service **_service); + #endif /* _IPA_COMMON_H_ */ diff --git a/server/providers/ipa/ipa_init.c b/server/providers/ipa/ipa_init.c index 70145287..ea279978 100644 --- a/server/providers/ipa/ipa_init.c +++ b/server/providers/ipa/ipa_init.c @@ -56,6 +56,34 @@ struct bet_ops ipa_access_ops = { .finalize = NULL }; +int common_ipa_init(struct be_ctx *bectx) +{ + const char *ipa_servers; + int ret; + + ret = ipa_get_options(bectx, bectx->cdb, + bectx->conf_path, + bectx->domain, &ipa_options); + if (ret != EOK) { + return ret; + } + + ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); + if (!ipa_servers) { + DEBUG(0, ("Missing ipa_server option!\n")); + return EINVAL; + } + + ret = ipa_service_init(ipa_options, bectx, + ipa_servers, &ipa_options->service); + if (ret != EOK) { + DEBUG(0, ("Failed to init IPA failover service!\n")); + return ret; + } + + return EOK; +} + int sssm_ipa_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) @@ -64,12 +92,10 @@ int sssm_ipa_init(struct be_ctx *bectx, int ret; if (!ipa_options) { - ipa_get_options(bectx, bectx->cdb, - bectx->conf_path, - bectx->domain, &ipa_options); - } - if (!ipa_options) { - return ENOMEM; + ret = common_ipa_init(bectx); + if (ret != EOK) { + return ret; + } } if (ipa_options->id_ctx) { @@ -84,6 +110,7 @@ int sssm_ipa_init(struct be_ctx *bectx, return ENOMEM; } ctx->be = bectx; + ctx->service = ipa_options->service->sdap; ipa_options->id_ctx = ctx; ret = ipa_get_id_options(ipa_options, bectx->cdb, @@ -127,12 +154,10 @@ int sssm_ipa_auth_init(struct be_ctx *bectx, int ret; if (!ipa_options) { - ipa_get_options(bectx, bectx->cdb, - bectx->conf_path, - bectx->domain, &ipa_options); - } - if (!ipa_options) { - return ENOMEM; + ret = common_ipa_init(bectx); + if (ret != EOK) { + return ret; + } } if (ipa_options->auth_ctx) { @@ -146,6 +171,7 @@ int sssm_ipa_auth_init(struct be_ctx *bectx, if (!ctx) { return ENOMEM; } + ctx->server = ipa_options->service->krb_server; ipa_options->auth_ctx = ctx; ret = ipa_get_auth_options(ipa_options, bectx->cdb, -- cgit