summaryrefslogtreecommitdiff
path: root/server/providers/ipa
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-11-20 12:11:28 -0500
committerStephen Gallagher <sgallagh@redhat.com>2009-11-20 16:55:16 -0500
commite115c25af2df3549fb44b260e516d8c93d2adc8a (patch)
treeddae338c26e8fd39b29f4fb106fd831280ca23d5 /server/providers/ipa
parent74bd0f69d2ff2da63949e7660aa2f48f06734b90 (diff)
downloadsssd-e115c25af2df3549fb44b260e516d8c93d2adc8a.tar.gz
sssd-e115c25af2df3549fb44b260e516d8c93d2adc8a.tar.bz2
sssd-e115c25af2df3549fb44b260e516d8c93d2adc8a.zip
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.
Diffstat (limited to 'server/providers/ipa')
-rw-r--r--server/providers/ipa/ipa_access.c6
-rw-r--r--server/providers/ipa/ipa_common.c165
-rw-r--r--server/providers/ipa/ipa_common.h10
-rw-r--r--server/providers/ipa/ipa_init.c50
4 files changed, 183 insertions, 48 deletions
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 <http://www.gnu.org/licenses/>.
*/
+#include <netdb.h>
#include <ctype.h>
#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,