summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/providers/ad/ad_common.c190
-rw-r--r--src/providers/ad/ad_common.h5
-rw-r--r--src/providers/ad/ad_init.c16
3 files changed, 178 insertions, 33 deletions
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 713f3194..ea124d96 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -25,6 +25,10 @@
#include "providers/ad/ad_opts.h"
#include "providers/dp_dyndns.h"
+struct ad_server_data {
+ bool gc;
+};
+
errno_t
ad_get_common_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
@@ -142,6 +146,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server);
static errno_t
_ad_servers_init(TALLOC_CTX *mem_ctx,
+ struct ad_service *service,
struct be_ctx *bectx,
const char *servers,
struct ad_options *options,
@@ -151,6 +156,7 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
errno_t ret = 0;
char **list;
char *ad_domain;
+ struct ad_server_data *sdata;
TALLOC_CTX *tmp_ctx;
tmp_ctx = talloc_new(NULL);
@@ -176,9 +182,33 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
continue;
}
+ sdata = talloc(service, struct ad_server_data);
+ if (sdata == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ sdata->gc = true;
+
+ ret = be_fo_add_srv_server(bectx, AD_SERVICE_NAME, "gc",
+ ad_domain, BE_FO_PROTO_TCP,
+ false, sdata);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Failed to add service discovery to failover: [%s]",
+ strerror(ret)));
+ goto done;
+ }
+
+ sdata = talloc(service, struct ad_server_data);
+ if (sdata == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ sdata->gc = false;
+
ret = be_fo_add_srv_server(bectx, AD_SERVICE_NAME, "ldap",
ad_domain, BE_FO_PROTO_TCP,
- false, NULL);
+ false, sdata);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Failed to add service discovery to failover: [%s]",
@@ -197,7 +227,27 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, NULL, primary);
+ sdata = talloc(service, struct ad_server_data);
+ if (sdata == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ sdata->gc = true;
+
+ ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, sdata, primary);
+ if (ret && ret != EEXIST) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
+ goto done;
+ }
+
+ sdata = talloc(service, struct ad_server_data);
+ if (sdata == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ sdata->gc = false;
+
+ ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, sdata, primary);
if (ret && ret != EEXIST) {
DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
goto done;
@@ -211,22 +261,53 @@ done:
}
static inline errno_t
-ad_primary_servers_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
- const char *servers, struct ad_options *options)
+ad_primary_servers_init(TALLOC_CTX *mem_ctx, struct ad_service *service,
+ struct be_ctx *bectx, const char *servers,
+ struct ad_options *options)
{
- return _ad_servers_init(mem_ctx, bectx, servers, options, true);
+ return _ad_servers_init(mem_ctx, service, bectx, servers, options, true);
}
static inline errno_t
-ad_backup_servers_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
- const char *servers, struct ad_options *options)
+ad_backup_servers_init(TALLOC_CTX *mem_ctx, struct ad_service *service,
+ struct be_ctx *bectx, const char *servers,
+ struct ad_options *options)
{
- return _ad_servers_init(mem_ctx, bectx, servers, options, false);
+ return _ad_servers_init(mem_ctx, service, bectx, servers, options, false);
}
static int ad_user_data_cmp(void *ud1, void *ud2)
{
- return strcasecmp((char*) ud1, (char*) ud2);
+ struct ad_server_data *sd1, *sd2;
+
+ sd1 = talloc_get_type(ud1, struct ad_server_data);
+ sd2 = talloc_get_type(ud2, struct ad_server_data);
+ if (sd1 == NULL || sd2 == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No user data\n"));
+ return sd1 == sd2 ? 0 : 1;
+ }
+
+ DEBUG(SSSDBG_TRACE_LIBS, ("Comparing %s with %s\n",
+ sd1->gc ? "GC" : "LDAP",
+ sd2->gc ? "GC" : "LDAP"));
+
+ if (sd1->gc == sd2->gc) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void ad_online_cb(void *pvt)
+{
+ struct ad_service *service = talloc_get_type(pvt, struct ad_service);
+
+ if (service == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid private pointer\n"));
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("The AD provider is online\n"));
}
errno_t
@@ -251,7 +332,15 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
}
service->sdap = talloc_zero(service, struct sdap_service);
- if (!service->sdap) {
+ service->gc = talloc_zero(service, struct sdap_service);
+ if (!service->sdap || !service->gc) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ service->sdap->name = talloc_strdup(service->sdap, AD_SERVICE_NAME);
+ service->gc->name = talloc_strdup(service->gc, AD_SERVICE_NAME);
+ if (!service->sdap->name || !service->gc->name) {
ret = ENOMEM;
goto done;
}
@@ -268,18 +357,14 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
goto done;
}
- service->sdap->name = talloc_strdup(service, AD_SERVICE_NAME);
- if (!service->sdap->name) {
- ret = ENOMEM;
- goto done;
- }
-
- service->krb5_service->name = talloc_strdup(service, AD_SERVICE_NAME);
+ service->krb5_service->name = talloc_strdup(service->krb5_service,
+ AD_SERVICE_NAME);
if (!service->krb5_service->name) {
ret = ENOMEM;
goto done;
}
service->sdap->kinit_service_name = service->krb5_service->name;
+ service->gc->kinit_service_name = service->krb5_service->name;
realm = dp_opt_get_string(options->basic, AD_KRB5_REALM);
if (!realm) {
@@ -300,18 +385,26 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
primary_servers = BE_SRV_IDENTIFIER;
}
- ret = ad_primary_servers_init(mem_ctx, bectx, primary_servers, options);
+ ret = ad_primary_servers_init(mem_ctx, service, bectx,
+ primary_servers, options);
if (ret != EOK) {
goto done;
}
if (backup_servers) {
- ret = ad_backup_servers_init(mem_ctx, bectx, backup_servers, options);
+ ret = ad_backup_servers_init(mem_ctx, service, bectx,
+ backup_servers, options);
if (ret != EOK) {
goto done;
}
}
+ ret = be_add_online_cb(bectx, bectx, ad_online_cb, service, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not set up AD online callback\n"));
+ return ret;
+ }
+
ret = be_fo_service_add_callback(mem_ctx, bectx, AD_SERVICE_NAME,
ad_resolve_callback, service);
if (ret != EOK) {
@@ -341,6 +434,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
const char *safe_address;
char *new_uri;
const char *srv_name;
+ struct ad_server_data *sdata = NULL;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
@@ -348,6 +442,12 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
return;
}
+ sdata = fo_get_server_user_data(server);
+ if (fo_is_srv_lookup(server) == false && sdata == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("No user data?\n"));
+ return;
+ }
+
service = talloc_get_type(private_data, struct ad_service);
if (!service) {
ret = EINVAL;
@@ -363,13 +463,6 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
goto done;
}
- sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT);
- if (sockaddr == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("resolv_get_sockaddr_address failed.\n"));
- ret = EIO;
- goto done;
- }
-
address = resolv_get_string_address(tmp_ctx, srvaddr);
if (address == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("resolv_get_string_address failed.\n"));
@@ -384,7 +477,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
goto done;
}
- new_uri = talloc_asprintf(service, "ldap://%s", srv_name);
+ new_uri = talloc_asprintf(service->sdap, "ldap://%s", srv_name);
if (!new_uri) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to copy URI\n"));
ret = ENOMEM;
@@ -392,12 +485,53 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
}
DEBUG(SSSDBG_CONF_SETTINGS, ("Constructed uri '%s'\n", new_uri));
+ sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT);
+ if (sockaddr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("resolv_get_sockaddr_address failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+
/* free old one and replace with new one */
talloc_zfree(service->sdap->uri);
service->sdap->uri = new_uri;
talloc_zfree(service->sdap->sockaddr);
- service->sdap->sockaddr = talloc_steal(service, sockaddr);
+ service->sdap->sockaddr = talloc_steal(service->sdap, sockaddr);
+
+ talloc_zfree(service->gc->uri);
+ talloc_zfree(service->gc->sockaddr);
+ if (sdata && sdata->gc) {
+ service->gc->uri = talloc_asprintf(service->gc, "%s:%d",
+ new_uri, AD_GC_PORT);
+
+ service->gc->sockaddr = resolv_get_sockaddr_address(service->gc,
+ srvaddr,
+ AD_GC_PORT);
+ } else {
+ /* Make sure there always is an URI even if we know that this
+ * server doesn't support GC. That way the lookup would go through
+ * just not return anything
+ */
+ service->gc->uri = talloc_strdup(service->gc, service->sdap->uri);
+ service->gc->sockaddr = talloc_memdup(service->gc, service->sdap->sockaddr,
+ sizeof(struct sockaddr_storage));
+ }
+
+ if (!service->gc->uri) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to append to URI\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Constructed GC uri '%s'\n", service->gc->uri));
+
+ if (service->gc->sockaddr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("resolv_get_sockaddr_address failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+ /* Write krb5 info files */
safe_address = sss_escape_ip_address(tmp_ctx,
srvaddr->family,
address);
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 792f32e0..80181552 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -27,6 +27,8 @@
#include "providers/ldap/ldap_common.h"
#define AD_SERVICE_NAME "AD"
+/* The port the Global Catalog runs on */
+#define AD_GC_PORT 3268
struct ad_options;
@@ -44,11 +46,14 @@ enum ad_basic_opt {
struct ad_id_ctx {
struct sdap_id_ctx *sdap_id_ctx;
+ struct sdap_id_conn_ctx *ldap_ctx;
+ struct sdap_id_conn_ctx *gc_ctx;
struct ad_options *ad_options;
};
struct ad_service {
struct sdap_service *sdap;
+ struct sdap_service *gc;
struct krb5_service *krb5_service;
};
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index aada14ec..cb73aca3 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -140,6 +140,12 @@ sssm_ad_id_init(struct be_ctx *bectx,
return ENOMEM;
}
ad_ctx->sdap_id_ctx = sdap_ctx;
+ ad_ctx->ldap_ctx = sdap_ctx->conn;
+
+ ad_ctx->gc_ctx = sdap_id_ctx_conn_add(sdap_ctx, ad_options->service->gc);
+ if (sdap_ctx == NULL) {
+ return ENOMEM;
+ }
ret = ad_dyndns_init(sdap_ctx->be, ad_options);
if (ret != EOK) {
@@ -148,11 +154,6 @@ sssm_ad_id_init(struct be_ctx *bectx,
/* Continue without DNS updates */
}
- ret = sdap_id_setup_tasks(sdap_ctx);
- if (ret != EOK) {
- goto done;
- }
-
ret = sdap_setup_child();
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
@@ -169,6 +170,11 @@ sssm_ad_id_init(struct be_ctx *bectx,
goto done;
}
+ ret = sdap_id_setup_tasks(sdap_ctx);
+ if (ret != EOK) {
+ goto done;
+ }
+
/* Set up the ID mapping object */
ret = sdap_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx);
if (ret != EOK) goto done;