summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am42
-rw-r--r--src/providers/ad/ad_common.c600
-rw-r--r--src/providers/ad/ad_common.h85
-rw-r--r--src/providers/ad/ad_id.c37
-rw-r--r--src/providers/ad/ad_id.h29
-rw-r--r--src/providers/ad/ad_init.c184
-rw-r--r--src/providers/ad/ad_opts.h230
-rw-r--r--src/tests/ad_ldap_opt-tests.c109
8 files changed, 1316 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 99565ee1b..c638f0223 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -117,6 +117,7 @@ if HAVE_CHECK
find_uid-tests \
auth-tests \
ipa_ldap_opt-tests \
+ ad_ldap_opt-tests \
simple_access-tests \
crypto-tests \
util-tests \
@@ -151,6 +152,7 @@ sssdlib_LTLIBRARIES = \
libsss_krb5.la \
libsss_proxy.la \
libsss_ipa.la \
+ libsss_ad.la \
libsss_simple.la
ldblib_LTLIBRARIES = \
@@ -931,6 +933,16 @@ ipa_ldap_opt_tests_LDADD = \
$(TALLOC_LIBS) \
libsss_test_common.la
+ad_ldap_opt_tests_SOURCES = \
+ src/tests/ad_ldap_opt-tests.c
+ad_ldap_opt_tests_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(CHECK_CFLAGS)
+ad_ldap_opt_tests_LDADD = \
+ $(CHECK_LIBS) \
+ $(TALLOC_LIBS) \
+ libsss_test_common.la
+
simple_access_tests_SOURCES = \
src/tests/simple_access-tests.c \
src/providers/simple/simple_access.c
@@ -1335,6 +1347,36 @@ libsss_ipa_la_SOURCES += src/providers/ipa/ipa_hostid.c
endif
+libsss_ad_la_SOURCES = \
+ src/providers/ad/ad_common.c \
+ src/providers/ad/ad_common.h \
+ src/providers/ad/ad_init.c \
+ src/providers/ad/ad_id.c \
+ src/providers/ad/ad_id.h \
+ src/providers/ad/ad_opts.h \
+ src/util/find_uid.c \
+ src/util/user_info_msg.c \
+ src/util/sss_krb5.c \
+ src/util/sss_ldap.c
+
+libsss_ad_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(LDAP_CFLAGS) \
+ $(DHASH_CFLAGS) \
+ $(KRB5_CFLAGS)
+libsss_ad_la_LIBADD = \
+ $(OPENLDAP_LIBS) \
+ $(DHASH_LIBS) \
+ $(KEYUTILS_LIBS) \
+ $(KRB5_LIBS) \
+ libsss_util.la \
+ libsss_ldap_common.la \
+ libsss_krb5_common.la \
+ libsss_idmap.la
+libsss_ad_la_LDFLAGS = \
+ -avoid-version \
+ -module
+
krb5_child_SOURCES = \
src/providers/krb5/krb5_become_user.c \
src/providers/krb5/krb5_child.c \
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
new file mode 100644
index 000000000..92cd40eca
--- /dev/null
+++ b/src/providers/ad/ad_common.c
@@ -0,0 +1,600 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+#include <ctype.h>
+
+#include "providers/ad/ad_common.h"
+#include "providers/ad/ad_opts.h"
+
+errno_t
+ad_get_common_options(TALLOC_CTX *mem_ctx,
+ struct confdb_ctx *cdb,
+ const char *conf_path,
+ struct sss_domain_info *dom,
+ struct ad_options **_opts)
+{
+ errno_t ret;
+ int gret;
+ size_t i;
+ struct ad_options *opts = NULL;
+ char *domain;
+ char *server;
+ char *realm;
+ char *ad_hostname;
+ char hostname[HOST_NAME_MAX + 1];
+
+ opts = talloc_zero(mem_ctx, struct ad_options);
+ if (!opts) return ENOMEM;
+
+ ret = dp_get_options(opts, cdb, conf_path,
+ ad_basic_opts,
+ AD_OPTS_BASIC,
+ &opts->basic);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* If the AD domain name wasn't explicitly set, assume that it
+ * matches the SSSD domain name
+ */
+ domain = dp_opt_get_string(opts->basic, AD_DOMAIN);
+ if (!domain) {
+ ret = dp_opt_set_string(opts->basic, AD_DOMAIN, dom->name);
+ if (ret != EOK) {
+ goto done;
+ }
+ domain = dom->name;
+ }
+
+ /* Did we get an explicit server name, or are we discovering it? */
+ server = dp_opt_get_string(opts->basic, AD_SERVER);
+ if (!server) {
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("No AD server set, will use service discovery!\n"));
+ }
+
+ /* Set the machine's hostname to the local host name if it
+ * wasn't explicitly specified.
+ */
+ ad_hostname = dp_opt_get_string(opts->basic, AD_HOSTNAME);
+ if (ad_hostname == NULL) {
+ gret = gethostname(hostname, HOST_NAME_MAX);
+ if (gret != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("gethostname failed [%s].\n",
+ strerror(ret)));
+ goto done;
+ }
+ hostname[HOST_NAME_MAX] = '\0';
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Setting ad_hostname to [%s].\n", hostname));
+ ret = dp_opt_set_string(opts->basic, AD_HOSTNAME, hostname);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Setting ad_hostname failed [%s].\n",
+ strerror(ret)));
+ goto done;
+ }
+ }
+
+
+ /* Always use the upper-case AD domain for the kerberos realm */
+ realm = talloc_strdup(opts, domain);
+ if (!realm) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; realm[i]; i++) {
+ realm[i] = toupper(realm[i]);
+ }
+
+ ret = dp_opt_set_string(opts->basic, AD_KRB5_REALM, realm);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = EOK;
+ *_opts = opts;
+
+done:
+ if (ret != EOK) {
+ talloc_zfree(opts);
+ }
+ return ret;
+}
+
+static void
+ad_resolve_callback(void *private_data, struct fo_server *server);
+
+errno_t
+ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
+ const char *servers,
+ struct ad_options *options,
+ struct ad_service **_service)
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ struct ad_service *service;
+ char *ad_domain;
+ char *realm;
+ char **list;
+ size_t i;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) return ENOMEM;
+
+ service = talloc_zero(tmp_ctx, struct ad_service);
+ if (!service) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ service->sdap = talloc_zero(service, struct sdap_service);
+ if (!service->sdap) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ service->krb5_service = talloc_zero(service, struct krb5_service);
+ if (!service->krb5_service) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = be_fo_add_service(bectx, AD_SERVICE_NAME);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to create failover service!\n"));
+ 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);
+ if (!service->krb5_service->name) {
+ ret = ENOMEM;
+ goto done;
+ }
+ service->sdap->kinit_service_name = service->krb5_service->name;
+
+ realm = dp_opt_get_string(options->basic, AD_KRB5_REALM);
+ if (!realm) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("No Kerberos realm set\n"));
+ ret = EINVAL;
+ goto done;
+ }
+ service->krb5_service->realm =
+ talloc_strdup(service->krb5_service, realm);
+ if (!service->krb5_service->realm) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (!servers) {
+ servers = BE_SRV_IDENTIFIER;
+ }
+
+ /* Split the server list */
+ ret = split_on_separator(tmp_ctx, servers, ',', true, &list, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to parse server list!\n"));
+ goto done;
+ }
+
+ ad_domain = dp_opt_get_string(options->basic, AD_DOMAIN);
+
+ /* Add each of these servers to the failover service */
+ for (i = 0; list[i]; i++) {
+ if (be_fo_is_srv_identifier(list[i])) {
+ ret = be_fo_add_srv_server(bectx, AD_SERVICE_NAME, "ldap",
+ ad_domain, BE_FO_PROTO_TCP,
+ false, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Failed to add service discovery to failover: [%s]",
+ strerror(ret)));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Added service discovery for AD\n"));
+ continue;
+ }
+
+ ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, NULL);
+ if (ret && ret != EEXIST) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Added failover server %s\n", list[i]));
+ }
+
+ ret = be_fo_service_add_callback(mem_ctx, bectx, AD_SERVICE_NAME,
+ ad_resolve_callback, service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Failed to add failover callback! [%s]\n", strerror(ret)));
+ goto done;
+ }
+
+ *_service = talloc_steal(mem_ctx, service);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static void
+ad_resolve_callback(void *private_data, struct fo_server *server)
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ struct ad_service *service;
+ struct resolv_hostent *srvaddr;
+ struct sockaddr_storage *sockaddr;
+ char *address;
+ const char *safe_address;
+ char *new_uri;
+ const char *srv_name;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
+ return;
+ }
+
+ service = talloc_get_type(private_data, struct ad_service);
+ if (!service) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ srvaddr = fo_get_server_hostent(server);
+ if (!srvaddr) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("No hostent available for server (%s)\n",
+ fo_get_server_str_name(server)));
+ ret = EINVAL;
+ 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"));
+ ret = EIO;
+ goto done;
+ }
+
+ srv_name = fo_get_server_name(server);
+ if (srv_name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get server host name\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ new_uri = talloc_asprintf(service, "ldap://%s", srv_name);
+ if (!new_uri) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to copy URI\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Constructed uri '%s'\n", new_uri));
+
+ /* free old one and replace with new one */
+ talloc_zfree(service->sdap->uri);
+ service->sdap->uri = new_uri;
+ talloc_zfree(service->sdap->sockaddr);
+ service->sdap->sockaddr = talloc_steal(service, sockaddr);
+
+ safe_address = sss_escape_ip_address(tmp_ctx,
+ srvaddr->family,
+ address);
+ if (safe_address == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("sss_escape_ip_address failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = write_krb5info_file(service->krb5_service->realm, safe_address,
+ SSS_KRB5KDC_FO_SRV);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("write_krb5info_file failed, authentication might fail.\n"));
+ }
+
+ ret = EOK;
+done:
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Error: [%s]\n", strerror(ret)));
+ }
+ talloc_free(tmp_ctx);
+ return;
+}
+
+errno_t
+ad_set_search_bases(struct sdap_options *id_opts);
+
+errno_t
+ad_get_id_options(struct ad_options *ad_opts,
+ struct confdb_ctx *cdb,
+ const char *conf_path,
+ struct sdap_options **_opts)
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ struct sdap_options *id_opts;
+ char *krb5_realm;
+ char *sasl_primary;
+ char *desired_primary;
+ char *sasl_realm;
+ char *desired_realm;
+ char *keytab_path;
+ bool primary_requested = true;
+ bool realm_requested = true;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) return ENOMEM;
+
+ id_opts = talloc_zero(tmp_ctx, struct sdap_options);
+ if (!id_opts) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = dp_get_options(id_opts, cdb, conf_path,
+ ad_def_ldap_opts,
+ SDAP_OPTS_BASIC,
+ &id_opts->basic);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Set up search bases if they were assigned explicitly */
+ ret = ad_set_search_bases(id_opts);
+ if (ret != EOK) goto done;
+
+ /* We only support Kerberos password policy with AD, so
+ * force that on.
+ */
+ ret = dp_opt_set_string(id_opts->basic,
+ SDAP_PWD_POLICY,
+ PWD_POL_OPT_MIT);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Could not set password policy\n"));
+ goto done;
+ }
+
+ /* Set the Kerberos Realm for GSSAPI */
+ krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
+ if (!krb5_realm) {
+ /* Should be impossible, this is set in ad_get_common_options() */
+ DEBUG(SSSDBG_FATAL_FAILURE, ("No Kerberos realm\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = dp_opt_set_string(id_opts->basic, SDAP_KRB5_REALM, krb5_realm);
+ if (ret != EOK) goto done;
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Option %s set to %s\n",
+ id_opts->basic[SDAP_KRB5_REALM].opt_name,
+ krb5_realm));
+
+ /* Configuration of SASL auth ID and realm */
+ desired_primary = dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID);
+ if (!desired_primary) {
+ primary_requested = false;
+ desired_primary = dp_opt_get_string(ad_opts->basic, AD_HOSTNAME);
+ }
+
+ desired_realm = dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM);
+ if (!desired_realm) {
+ realm_requested = false;
+ desired_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
+ }
+
+ keytab_path = dp_opt_get_string(id_opts->basic, SDAP_KRB5_KEYTAB);
+ /* It's okay if this is NULL here */
+
+ ret = select_principal_from_keytab(tmp_ctx,
+ desired_primary, desired_realm,
+ keytab_path, NULL,
+ &sasl_primary, &sasl_realm);
+ if (ret != EOK) goto done;
+
+ if ((primary_requested && strcmp(desired_primary, sasl_primary) != 0) ||
+ (realm_requested && strcmp(desired_realm, sasl_realm) != 0)) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Configured SASL auth ID/realm not found in keytab.\n"));
+ ret = ENOENT;
+ goto done;
+ }
+
+ ret = dp_opt_set_string(id_opts->basic, SDAP_SASL_AUTHID, sasl_primary);
+ if (ret != EOK) goto done;
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Option %s set to %s\n",
+ id_opts->basic[SDAP_SASL_AUTHID].opt_name,
+ sasl_primary));
+
+ ret = dp_opt_set_string(id_opts->basic, SDAP_SASL_REALM, sasl_realm);
+ if (ret != EOK) goto done;
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Option %s set to %s\n",
+ id_opts->basic[SDAP_SASL_REALM].opt_name,
+ sasl_realm));
+
+ /* fix schema to AD */
+ id_opts->schema_type = SDAP_SCHEMA_AD;
+
+ /* Get sdap option maps */
+
+ /* General Attribute Map */
+ ret = sdap_get_map(id_opts,
+ cdb, conf_path,
+ ad_2008r2_attr_map,
+ SDAP_AT_GENERAL,
+ &id_opts->gen_map);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* User map */
+ ret = sdap_get_map(id_opts,
+ cdb, conf_path,
+ ad_2008r2_user_map,
+ SDAP_OPTS_USER,
+ &id_opts->user_map);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Group map */
+ ret = sdap_get_map(id_opts,
+ cdb, conf_path,
+ ad_2008r2_group_map,
+ SDAP_OPTS_GROUP,
+ &id_opts->group_map);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Netgroup map */
+ ret = sdap_get_map(id_opts,
+ cdb, conf_path,
+ ad_netgroup_map,
+ SDAP_OPTS_NETGROUP,
+ &id_opts->netgroup_map);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Services map */
+ ret = sdap_get_map(id_opts,
+ cdb, conf_path,
+ ad_service_map,
+ SDAP_OPTS_SERVICES,
+ &id_opts->service_map);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ad_opts->id = talloc_steal(ad_opts, id_opts);
+ *_opts = id_opts;
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+errno_t
+ad_set_search_bases(struct sdap_options *id_opts)
+{
+ errno_t ret;
+ char *default_search_base;
+ size_t o;
+ const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
+ SDAP_GROUP_SEARCH_BASE,
+ SDAP_NETGROUP_SEARCH_BASE,
+ SDAP_SERVICE_SEARCH_BASE,
+ -1 };
+
+ /* AD servers provide defaultNamingContext, so we will
+ * rely on that to specify the search base unless it has
+ * been specifically overridden.
+ */
+
+ default_search_base =
+ dp_opt_get_string(id_opts->basic, SDAP_SEARCH_BASE);
+
+ if (default_search_base) {
+ /* set search bases if they are not */
+ for (o = 0; search_base_options[o] != -1; o++) {
+ if (NULL == dp_opt_get_string(id_opts->basic,
+ search_base_options[o])) {
+ ret = dp_opt_set_string(id_opts->basic,
+ search_base_options[o],
+ default_search_base);
+ if (ret != EOK) {
+ goto done;
+ }
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Option %s set to %s\n",
+ id_opts->basic[search_base_options[o]].opt_name,
+ dp_opt_get_string(id_opts->basic,
+ search_base_options[o])));
+ }
+ }
+ } else {
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ ("Search base not set. SSSd will attempt to discover it later, "
+ "when connecting to the LDAP server.\n"));
+ }
+
+ /* Default search */
+ ret = sdap_parse_search_base(id_opts, id_opts->basic,
+ SDAP_SEARCH_BASE,
+ &id_opts->search_bases);
+ if (ret != EOK && ret != ENOENT) goto done;
+
+ /* User search */
+ ret = sdap_parse_search_base(id_opts, id_opts->basic,
+ SDAP_USER_SEARCH_BASE,
+ &id_opts->user_search_bases);
+ if (ret != EOK && ret != ENOENT) goto done;
+
+ /* Group search base */
+ ret = sdap_parse_search_base(id_opts, id_opts->basic,
+ SDAP_GROUP_SEARCH_BASE,
+ &id_opts->group_search_bases);
+ if (ret != EOK && ret != ENOENT) goto done;
+
+ /* Netgroup search */
+ ret = sdap_parse_search_base(id_opts, id_opts->basic,
+ SDAP_NETGROUP_SEARCH_BASE,
+ &id_opts->netgroup_search_bases);
+ if (ret != EOK && ret != ENOENT) goto done;
+
+ /* Service search */
+ ret = sdap_parse_search_base(id_opts, id_opts->basic,
+ SDAP_SERVICE_SEARCH_BASE,
+ &id_opts->service_search_bases);
+ if (ret != EOK && ret != ENOENT) goto done;
+
+ ret = EOK;
+done:
+ return ret;
+}
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
new file mode 100644
index 000000000..fefb67b60
--- /dev/null
+++ b/src/providers/ad/ad_common.h
@@ -0,0 +1,85 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef AD_COMMON_H_
+#define AD_COMMON_H_
+
+#include "util/util.h"
+#include "providers/ldap/ldap_common.h"
+
+#define AD_SERVICE_NAME "AD"
+
+struct ad_options;
+
+enum ad_basic_opt {
+ AD_DOMAIN = 0,
+ AD_SERVER,
+ AD_HOSTNAME,
+ AD_KRB5_REALM,
+
+ AD_OPTS_BASIC /* opts counter */
+};
+
+struct ad_id_ctx {
+ struct sdap_id_ctx *sdap_id_ctx;
+ struct ad_options *ad_options;
+};
+
+struct ad_service {
+ struct sdap_service *sdap;
+ struct krb5_service *krb5_service;
+};
+
+struct ad_options {
+ /* Common options */
+ struct dp_option *basic;
+ struct ad_service *service;
+
+ /* ID Provider */
+ struct sdap_options *id;
+ struct ad_id_ctx *id_ctx;
+
+ /* Auth and chpass Provider */
+ struct dp_option *auth;
+ struct ad_auth_ctx *auth_ctx;
+};
+
+errno_t
+ad_get_common_options(TALLOC_CTX *mem_ctx,
+ struct confdb_ctx *cdb,
+ const char *conf_path,
+ struct sss_domain_info *dom,
+ struct ad_options **_opts);
+
+errno_t
+ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
+ const char *servers,
+ struct ad_options *options,
+ struct ad_service **_service);
+
+errno_t
+ad_get_id_options(struct ad_options *ad_opts,
+ struct confdb_ctx *cdb,
+ const char *conf_path,
+ struct sdap_options **_opts);
+
+#endif /* AD_COMMON_H_ */
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
new file mode 100644
index 000000000..41510b245
--- /dev/null
+++ b/src/providers/ad/ad_id.c
@@ -0,0 +1,37 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+#include "util/util.h"
+#include "providers/ad/ad_common.h"
+#include "providers/ad/ad_id.h"
+
+void
+ad_account_info_handler(struct be_req *breq)
+{
+ struct ad_id_ctx *ad_ctx;
+ struct sdap_id_ctx *sdap_id_ctx;
+
+ ad_ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
+ struct ad_id_ctx);
+ sdap_id_ctx = ad_ctx->sdap_id_ctx;
+
+ return sdap_handle_account_info(breq, sdap_id_ctx);
+}
diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h
new file mode 100644
index 000000000..7f480aab7
--- /dev/null
+++ b/src/providers/ad/ad_id.h
@@ -0,0 +1,29 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef AD_ID_H_
+#define AD_ID_H_
+
+void
+ad_account_info_handler(struct be_req *breq);
+
+#endif /* AD_ID_H_ */
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
new file mode 100644
index 000000000..da659da25
--- /dev/null
+++ b/src/providers/ad/ad_init.c
@@ -0,0 +1,184 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "util/util.h"
+#include "providers/ad/ad_common.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_idmap.h"
+#include "providers/krb5/krb5_auth.h"
+#include "providers/ad/ad_id.h"
+
+struct ad_options *ad_options = NULL;
+
+static void
+ad_shutdown(struct be_req *req);
+
+struct bet_ops ad_id_ops = {
+ .handler = ad_account_info_handler,
+ .finalize = ad_shutdown,
+ .check_online = sdap_check_online
+};
+
+struct bet_ops ad_auth_ops = {
+ .handler = krb5_pam_handler,
+ .finalize = NULL
+};
+
+struct bet_ops ad_chpass_ops = {
+ .handler = krb5_pam_handler,
+ .finalize = NULL
+};
+
+static errno_t
+common_ad_init(struct be_ctx *bectx)
+{
+ errno_t ret;
+ char *ad_servers = NULL;
+
+ /* Get AD-specific options */
+ ret = ad_get_common_options(bectx, bectx->cdb,
+ bectx->conf_path,
+ bectx->domain,
+ &ad_options);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Could not parse common options: [%s]\n",
+ strerror(ret)));
+ goto done;
+ }
+
+ ad_servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
+
+ /* Set up the failover service */
+ ret = ad_failover_init(ad_options, bectx, ad_servers, ad_options,
+ &ad_options->service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Failed to init AD failover service: [%s]\n",
+ strerror(ret)));
+ goto done;
+ }
+
+ ret = EOK;
+done:
+ return ret;
+}
+
+int
+sssm_ad_id_init(struct be_ctx *bectx,
+ struct bet_ops **ops,
+ void **pvt_data)
+{
+ errno_t ret;
+ struct ad_id_ctx *ad_ctx;
+ struct sdap_id_ctx *sdap_ctx;
+
+ if (!ad_options) {
+ ret = common_ad_init(bectx);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+
+ if (ad_options->id_ctx) {
+ /* already initialized */
+ *ops = &ad_id_ops;
+ *pvt_data = ad_options->id_ctx;
+ return EOK;
+ }
+
+ ad_ctx = talloc_zero(ad_options, struct ad_id_ctx);
+ if (!ad_options) {
+ return ENOMEM;
+ }
+ ad_ctx->ad_options = ad_options;
+ ad_options->id_ctx = ad_ctx;
+
+ sdap_ctx = talloc_zero(ad_options, struct sdap_id_ctx);
+ if (!sdap_ctx) {
+ return ENOMEM;
+ }
+ sdap_ctx->be = bectx;
+ sdap_ctx->service = ad_options->service->sdap;
+ ad_ctx->sdap_id_ctx = sdap_ctx;
+
+ ret = ad_get_id_options(ad_options, bectx->cdb,
+ bectx->conf_path,
+ &sdap_ctx->opts);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = setup_tls_config(sdap_ctx->opts->basic);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("setup_tls_config failed [%s]\n", strerror(ret)));
+ goto done;
+ }
+
+ ret = sdap_id_conn_cache_create(sdap_ctx, sdap_ctx, &sdap_ctx->conn_cache);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (dp_opt_get_bool(sdap_ctx->opts->basic, SDAP_ID_MAPPING)) {
+ /* Set up the ID mapping object */
+ ret = sdap_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx);
+ if (ret != EOK) goto done;
+ }
+
+ ret = sdap_id_setup_tasks(sdap_ctx);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = setup_child(sdap_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("setup_child failed [%d][%s].\n",
+ ret, strerror(ret)));
+ goto done;
+ }
+
+ *ops = &ad_id_ops;
+ *pvt_data = ad_ctx;
+
+ ret = EOK;
+done:
+ if (ret != EOK) {
+ talloc_zfree(ad_options->id_ctx);
+ }
+ return ret;
+}
+
+static void
+ad_shutdown(struct be_req *req)
+{
+ /* TODO: Clean up any internal data */
+ sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
+}
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
new file mode 100644
index 000000000..178d097f6
--- /dev/null
+++ b/src/providers/ad/ad_opts.h
@@ -0,0 +1,230 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef AD_OPTS_H_
+#define AD_OPTS_H_
+
+#include "src/providers/data_provider.h"
+#include "db/sysdb_services.h"
+#include "db/sysdb_autofs.h"
+
+struct dp_option ad_basic_opts[] = {
+ { "ad_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ad_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ad_hostname", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING},
+ DP_OPTION_TERMINATOR
+};
+
+struct dp_option ad_def_ldap_opts[] = {
+ { "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_default_authtok_type", DP_OPT_STRING, { "password" }, NULL_STRING},
+ { "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
+ { "ldap_search_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
+ { "ldap_network_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
+ { "ldap_opt_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
+ { "ldap_tls_reqcert", DP_OPT_STRING, { "hard" }, NULL_STRING },
+ { "ldap_user_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_user_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
+ { "ldap_user_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
+ { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_service_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER }, /* 360 mins */
+ { "ldap_sudo_smart_refresh_interval", DP_OPT_NUMBER, { .number = 900 }, NULL_NUMBER }, /* 15 mins */
+ { "ldap_sudo_use_host_filter", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "ldap_sudo_hostnames", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sudo_ip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sudo_include_netgroups", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "ldap_sudo_include_regexp", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "ldap_autofs_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_schema", DP_OPT_STRING, { "ad" }, NULL_STRING },
+ { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER },
+ { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE },
+ { "ldap_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER },
+ { "ldap_purge_cache_timeout", DP_OPT_NUMBER, { .number = 10800 }, NULL_NUMBER },
+ { "ldap_tls_cacert", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_tls_cacertdir", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_tls_cert", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_tls_key", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_tls_cipher_suite", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_id_use_start_tls", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_id_mapping", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE },
+ { "ldap_sasl_mech", DP_OPT_STRING, { "gssapi" }, NULL_STRING },
+ { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sasl_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_sasl_minssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
+ { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ /* use the same parm name as the krb5 module so we set it only once */
+ { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_TRUE },
+ { "ldap_pwd_policy", DP_OPT_STRING, { "none" }, NULL_STRING },
+ { "ldap_referrals", DP_OPT_BOOL, BOOL_FALSE, BOOL_TRUE },
+ { "account_cache_expiration", DP_OPT_NUMBER, { .number = 0 }, NULL_NUMBER },
+ { "ldap_dns_service_name", DP_OPT_STRING, { SSS_LDAP_SRV_NAME }, NULL_STRING },
+ { "ldap_krb5_ticket_lifetime", DP_OPT_NUMBER, { .number = (24 * 60 * 60) }, NULL_NUMBER },
+ { "ldap_access_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_netgroup_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_group_nesting_level", DP_OPT_NUMBER, { .number = 2 }, NULL_NUMBER },
+ { "ldap_deref", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_account_expire_policy", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_access_order", DP_OPT_STRING, { "filter" }, NULL_STRING },
+ { "ldap_chpass_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_chpass_dns_service_name", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_chpass_update_last_change", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_enumeration_search_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER },
+ /* Do not include ldap_auth_disable_tls_never_use_in_production in the
+ * manpages or SSSDConfig API
+ */
+ { "ldap_auth_disable_tls_never_use_in_production", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_page_size", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER },
+ { "ldap_deref_threshold", DP_OPT_NUMBER, { .number = 10 }, NULL_NUMBER },
+ { "ldap_sasl_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_connection_expire_timeout", DP_OPT_NUMBER, { .number = 900 }, NULL_NUMBER },
+ { "ldap_disable_paging", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_idmap_range_min", DP_OPT_NUMBER, { .number = 100001 }, NULL_NUMBER },
+ { "ldap_idmap_range_max", DP_OPT_NUMBER, { .number = 2000100000LL }, NULL_NUMBER },
+ { "ldap_idmap_range_size", DP_OPT_NUMBER, { .number = 200000 }, NULL_NUMBER },
+ { "ldap_idmap_autorid_compat", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_idmap_default_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE },
+ DP_OPTION_TERMINATOR
+};
+
+struct dp_option ad_def_krb5_opts[] = {
+ { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
+ { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
+ { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
+ { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
+ { "krb5_validate", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "krb5_kpasswd", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_renew_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER },
+ { "krb5_use_fast", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_fast_principal", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }
+};
+
+struct sdap_attr_map ad_2008r2_attr_map[] = {
+ { "ldap_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
+ { "ldap_rootdse_last_usn", SDAP_AD_LAST_USN, SYSDB_HIGH_USN, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_2008r2_user_map[] = {
+ { "ldap_user_object_class", "user", SYSDB_USER_CLASS, NULL },
+ { "ldap_user_name", "sAMAccountName", SYSDB_NAME, NULL },
+ { "ldap_user_pwd", "unixUserPassword", SYSDB_PWD, NULL },
+ { "ldap_user_uid_number", "uidNumber", SYSDB_UIDNUM, NULL },
+ { "ldap_user_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
+ { "ldap_user_gecos", "gecos", SYSDB_GECOS, NULL },
+ { "ldap_user_home_directory", "unixHomeDirectory", SYSDB_HOMEDIR, NULL },
+ { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL },
+ { "ldap_user_principal", "userPrincipalName", SYSDB_UPN, NULL },
+ { "ldap_user_fullname", "name", SYSDB_FULLNAME, NULL },
+ { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
+ { "ldap_user_uuid", "objectGUID", SYSDB_UUID, NULL },
+ { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
+ { "ldap_user_primary_group", "primaryGroupID", SYSDB_PRIMARY_GROUP, NULL },
+ { "ldap_user_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
+ { "ldap_user_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
+ { "ldap_user_shadow_last_change", NULL, SYSDB_SHADOWPW_LASTCHANGE, NULL },
+ { "ldap_user_shadow_min", NULL, SYSDB_SHADOWPW_MIN, NULL },
+ { "ldap_user_shadow_max", NULL, SYSDB_SHADOWPW_MAX, NULL },
+ { "ldap_user_shadow_warning", NULL, SYSDB_SHADOWPW_WARNING, NULL },
+ { "ldap_user_shadow_inactive", NULL, SYSDB_SHADOWPW_INACTIVE, NULL },
+ { "ldap_user_shadow_expire", NULL, SYSDB_SHADOWPW_EXPIRE, NULL },
+ { "ldap_user_shadow_flag", NULL, SYSDB_SHADOWPW_FLAG, NULL },
+ { "ldap_user_krb_last_pwd_change", NULL, SYSDB_KRBPW_LASTCHANGE, NULL },
+ { "ldap_user_krb_password_expiration", NULL, SYSDB_KRBPW_EXPIRATION, NULL },
+ { "ldap_pwd_attribute", NULL, SYSDB_PWD_ATTRIBUTE, NULL },
+ { "ldap_user_authorized_service", NULL, SYSDB_AUTHORIZED_SERVICE, NULL },
+ { "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL},
+ { "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
+ { "ldap_ns_account_lock", NULL, SYSDB_NS_ACCOUNT_LOCK, NULL},
+ { "ldap_user_authorized_host", NULL, SYSDB_AUTHORIZED_HOST, NULL },
+ { "ldap_user_nds_login_disabled", NULL, SYSDB_NDS_LOGIN_DISABLED, NULL },
+ { "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
+ { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
+ { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_2008r2_group_map[] = {
+ { "ldap_group_object_class", "group", SYSDB_GROUP_CLASS, NULL },
+ { "ldap_group_name", "name", SYSDB_NAME, NULL },
+ { "ldap_group_pwd", NULL, SYSDB_PWD, NULL },
+ { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
+ { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
+ { "ldap_group_uuid", "objectGUID", SYSDB_UUID, NULL },
+ { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
+ { "ldap_group_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
+ { "ldap_group_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_netgroup_map[] = {
+ { "ldap_netgroup_object_class", "nisNetgroup", SYSDB_NETGROUP_CLASS, NULL },
+ { "ldap_netgroup_name", "cn", SYSDB_NAME, NULL },
+ { "ldap_netgroup_member", "memberNisNetgroup", SYSDB_ORIG_NETGROUP_MEMBER, NULL },
+ { "ldap_netgroup_triple", "nisNetgroupTriple", SYSDB_NETGROUP_TRIPLE, NULL },
+ /* FIXME: this is 389ds specific */
+ { "ldap_netgroup_uuid", "nsUniqueId", SYSDB_UUID, NULL },
+ { "ldap_netgroup_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_service_map[] = {
+ { "ldap_service_object_class", "ipService", SYSDB_SVC_CLASS, NULL },
+ { "ldap_service_name", "cn", SYSDB_NAME, NULL },
+ { "ldap_service_port", "ipServicePort", SYSDB_SVC_PORT, NULL },
+ { "ldap_service_proto", "ipServiceProtocol", SYSDB_SVC_PROTO, NULL },
+ { "ldap_service_entry_usn", NULL, SYSDB_USN, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_autofs_mobject_map[] = {
+ { "ldap_autofs_map_object_class", "nisMap", SYSDB_AUTOFS_MAP_OC, NULL },
+ { "ldap_autofs_map_name", "nisMapName", SYSDB_AUTOFS_MAP_NAME, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+struct sdap_attr_map ad_autofs_entry_map[] = {
+ { "ldap_autofs_entry_object_class", "nisObject", SYSDB_AUTOFS_ENTRY_OC, NULL },
+ { "ldap_autofs_entry_key", "cn", SYSDB_AUTOFS_ENTRY_KEY, NULL },
+ { "ldap_autofs_entry_value", "nisMapEntry", SYSDB_AUTOFS_ENTRY_VALUE, NULL },
+ SDAP_ATTR_MAP_TERMINATOR
+};
+
+#endif /* AD_OPTS_H_ */
diff --git a/src/tests/ad_ldap_opt-tests.c b/src/tests/ad_ldap_opt-tests.c
new file mode 100644
index 000000000..e9ce9d02b
--- /dev/null
+++ b/src/tests/ad_ldap_opt-tests.c
@@ -0,0 +1,109 @@
+/*
+ SSSD
+
+ Tests if AD and LDAP backend options are in sync
+
+ Authors:
+ Jakub Hrozek <jhrozek@redhat.com>
+ Stephen Gallagher <sgallagh@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <check.h>
+#include <stdlib.h>
+#include <talloc.h>
+
+#include "providers/ad/ad_common.h"
+#include "providers/ad/ad_opts.h"
+#include "providers/ldap/sdap.h"
+#include "providers/ldap/ldap_opts.h"
+#include "providers/krb5/krb5_opts.h"
+#include "providers/krb5/krb5_common.h"
+#include "tests/common.h"
+
+START_TEST(test_compare_opts)
+{
+ errno_t ret;
+
+ ret = compare_dp_options(default_basic_opts, SDAP_OPTS_BASIC,
+ ad_def_ldap_opts);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+ ret = compare_dp_options(default_krb5_opts, KRB5_OPTS,
+ ad_def_krb5_opts);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+}
+END_TEST
+
+START_TEST(test_compare_sdap_attrs)
+{
+ errno_t ret;
+
+ /* General Attributes */
+ ret = compare_sdap_attr_maps(generic_attr_map, SDAP_AT_GENERAL,
+ ad_2008r2_attr_map);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+ /* User Attributes */
+ ret = compare_sdap_attr_maps(rfc2307_user_map, SDAP_OPTS_USER,
+ ad_2008r2_user_map);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+ /* Group Attributes */
+ ret = compare_sdap_attr_maps(rfc2307_group_map, SDAP_OPTS_GROUP,
+ ad_2008r2_group_map);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+ /* Netgroup Attributes */
+ ret = compare_sdap_attr_maps(netgroup_map, SDAP_OPTS_NETGROUP,
+ ad_netgroup_map);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+ /* Service Attributes */
+ ret = compare_sdap_attr_maps(service_map, SDAP_OPTS_SERVICES,
+ ad_service_map);
+ fail_unless(ret == EOK, "[%s]", strerror(ret));
+}
+END_TEST
+
+Suite *ad_ldap_opt_suite (void)
+{
+ Suite *s = suite_create ("ad_ldap_opt");
+
+ TCase *tc_ad_ldap_opt = tcase_create ("ad_ldap_opt");
+
+ tcase_add_test (tc_ad_ldap_opt, test_compare_opts);
+ tcase_add_test (tc_ad_ldap_opt, test_compare_sdap_attrs);
+ suite_add_tcase (s, tc_ad_ldap_opt);
+
+ return s;
+}
+
+int main(void)
+{
+ int number_failed;
+
+ tests_set_cwd();
+
+ Suite *s = ad_ldap_opt_suite ();
+ SRunner *sr = srunner_create (s);
+ /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
+ srunner_run_all(sr, CK_ENV);
+ number_failed = srunner_ntests_failed (sr);
+ srunner_free (sr);
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}