diff options
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | src/config/SSSDConfig.py | 8 | ||||
-rw-r--r-- | src/man/sssd-ldap.5.xml | 101 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.c | 25 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.h | 2 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.c | 106 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.h | 5 | ||||
-rw-r--r-- | src/providers/ldap/ldap_init.c | 31 | ||||
-rw-r--r-- | src/providers/ldap/sdap.c | 13 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 19 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_autofs.c | 833 | ||||
-rw-r--r-- | src/providers/ldap/sdap_autofs.c | 291 | ||||
-rw-r--r-- | src/providers/ldap/sdap_autofs.h | 47 |
13 files changed, 1488 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index becc67ba..97d2bff4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -354,6 +354,7 @@ dist_noinst_HEADERS = \ src/providers/ldap/sdap_sudo_cache.h \ src/providers/ldap/sdap_sudo_timer.h \ src/providers/ldap/sdap_sudo.h \ + src/providers/ldap/sdap_autofs.h \ src/providers/ldap/sdap_id_op.h \ src/providers/ipa/ipa_common.h \ src/providers/ipa/ipa_access.h \ @@ -997,6 +998,10 @@ libsss_ldap_la_SOURCES += src/providers/ldap/sdap_sudo_cache.c \ src/providers/ldap/sdap_sudo_timer.c \ src/providers/ldap/sdap_sudo.c endif +if BUILD_AUTOFS +libsss_ldap_la_SOURCES += src/providers/ldap/sdap_autofs.c \ + src/providers/ldap/sdap_async_autofs.c +endif libsss_proxy_la_SOURCES = \ src/providers/proxy/proxy_common.c \ @@ -1116,6 +1121,10 @@ libsss_ipa_la_SOURCES += src/providers/ldap/sdap_sudo_cache.c \ src/providers/ldap/sdap_sudo_timer.c \ src/providers/ldap/sdap_sudo.c endif +if BUILD_AUTOFS +libsss_ipa_la_SOURCES += src/providers/ldap/sdap_autofs.c \ + src/providers/ldap/sdap_async_autofs.c +endif krb5_child_SOURCES = \ diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index 740ab27f..c27bade9 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -277,6 +277,14 @@ option_strings = { 'ldap_sudorule_notafter' : _('Sudo rule notafter attribute'), 'ldap_sudorule_order' : _('Sudo rule order attribute'), + # [provider/ldap/autofs] + 'ldap_autofs_map_object_class' : _('Object class for automounter maps'), + 'ldap_autofs_map_name' : _('Automounter map name attribute'), + 'ldap_autofs_entry_object_class' : _('Object class for automounter map entries'), + 'ldap_autofs_entry_key' : _('Automounter map entry key attribute'), + 'ldap_autofs_entry_value' : _('Automounter map entry value attribute'), + 'ldap_autofs_search_base' : _('Base DN for automonter map lookups'), + # [provider/simple/access] 'simple_allow_users' : _('Comma separated list of allowed users'), 'simple_deny_users' : _('Comma separated list of prohibited users'), diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml index fc396d94..0d4885d2 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -1813,6 +1813,85 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com </para> </refsect1> + <refsect1 id='autofs-options' condition="with_autofs"> + <title>AUTOFS OPTIONS</title> + <para> + Please note that the default values correspond to the default + schema which is RFC2307. + </para> + <para> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/experimental.xml" /> + <variablelist> + <varlistentry> + <term>ldap_autofs_map_object_class (string)</term> + <listitem> + <para> + The object class of an automount map entry in LDAP. + </para> + <para> + Default: automountMap + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term>ldap_autofs_map_name (string)</term> + <listitem> + <para> + The name of an automount map entry in LDAP. + </para> + <para> + Default: ou + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term>ldap_autofs_entry_object_class (string)</term> + <listitem> + <para> + The object class of an automount map entry + in LDAP. + </para> + <para> + Default: automountMap + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term>ldap_autofs_entry_key (string)</term> + <listitem> + <para> + The key of an automount entry in LDAP. The + entry usually corresponds to a mount point. + </para> + <para> + Default: cn + </para> + </listitem> + </varlistentry> + </variablelist> + <variablelist> + <varlistentry> + <term>ldap_autofs_entry_value (string)</term> + <listitem> + <para> + The key of an automount entry in LDAP. The + entry usually corresponds to a mount point. + </para> + <para> + Default: automountInformation + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + <refsect1 id='advanced-options'> <title>ADVANCED OPTIONS</title> <para> @@ -1943,6 +2022,28 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com </listitem> </varlistentry> + <varlistentry condition="with_autofs"> + <term>ldap_autofs_search_base (string)</term> + <listitem> + <para> + An optional base DN to restrict automounter searches + to a specific subtree. + </para> + <para> + See <quote>ldap_search_base</quote> for + information about configuring multiple search + bases. + </para> + <para> + Default: the value of + <emphasis>ldap_search_base</emphasis> + </para> + <para> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/experimental.xml" /> + </para> + </listitem> + </varlistentry> + </variablelist> </para> </refsect1> diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index e8df5e15..2e6dad8a 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -65,6 +65,7 @@ struct dp_option ipa_def_ldap_opts[] = { { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_sudo_refresh_enabled", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "ldap_sudo_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER }, + { "ldap_autofs_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_schema", DP_OPT_STRING, { "ipa_v1" }, NULL_STRING }, { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, @@ -478,6 +479,30 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, if (ret != EOK) goto done; if (NULL == dp_opt_get_string(ipa_opts->id->basic, + SDAP_AUTOFS_SEARCH_BASE)) { + value = talloc_asprintf(tmpctx, "cn=default,cn=automount,%s", basedn); + if (!value) { + ret = ENOMEM; + goto done; + } + + ret = dp_opt_set_string(ipa_opts->id->basic, + SDAP_AUTOFS_SEARCH_BASE, + value); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_TRACE_LIBS, ("Option %s set to %s\n", + ipa_opts->id->basic[SDAP_AUTOFS_SEARCH_BASE].opt_name, + dp_opt_get_string(ipa_opts->id->basic, + SDAP_AUTOFS_SEARCH_BASE))); + } + ret = sdap_parse_search_base(ipa_opts->id, ipa_opts->id->basic, + SDAP_AUTOFS_SEARCH_BASE, + &ipa_opts->id->autofs_search_bases); + + if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_SUDO_SEARCH_BASE)) { #if 0 ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_SUDO_SEARCH_BASE, diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 5bf1b7c9..9cbd993f 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -35,7 +35,7 @@ struct ipa_service { /* the following defines are used to keep track of the options in the ldap * module, so that if they change and ipa is not updated correspondingly * this will trigger a runtime abort error */ -#define IPA_OPTS_BASIC_TEST 59 +#define IPA_OPTS_BASIC_TEST 60 #define IPA_OPTS_SVC_TEST 5 diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index cce3c0bc..3b8e0eeb 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -28,6 +28,7 @@ #include "providers/krb5/krb5_common.h" #include "db/sysdb_sudo.h" #include "db/sysdb_services.h" +#include "db/sysdb_autofs.h" #include "util/sss_krb5.h" #include "util/crypto/sss_crypto.h" @@ -55,6 +56,7 @@ struct dp_option default_basic_opts[] = { { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_sudo_refresh_enabled", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "ldap_sudo_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER }, + { "ldap_autofs_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_schema", DP_OPT_STRING, { "rfc2307" }, NULL_STRING }, { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, @@ -242,6 +244,28 @@ struct sdap_attr_map service_map[] = { { "ldap_service_entry_usn", NULL, SYSDB_USN, NULL } }; +struct sdap_attr_map rfc2307_autofs_mobject_map[] = { + { "ldap_autofs_map_object_class", "automountMap", SYSDB_AUTOFS_MAP_OC, NULL }, + { "ldap_autofs_map_name", "ou", SYSDB_AUTOFS_MAP_NAME, NULL } +}; + +struct sdap_attr_map rfc2307_autofs_entry_map[] = { + { "ldap_autofs_entry_object_class", "automount", SYSDB_AUTOFS_ENTRY_OC, NULL }, + { "ldap_autofs_entry_key", "cn", SYSDB_AUTOFS_ENTRY_KEY, NULL }, + { "ldap_autofs_entry_value", "automountInformation", SYSDB_AUTOFS_ENTRY_VALUE, NULL }, +}; + +struct sdap_attr_map rfc2307bis_autofs_mobject_map[] = { + { "ldap_autofs_map_object_class", "automountMap", SYSDB_AUTOFS_MAP_OC, NULL }, + { "ldap_autofs_map_name", "automountMapName", SYSDB_AUTOFS_MAP_NAME, NULL } +}; + +struct sdap_attr_map rfc2307bis_autofs_entry_map[] = { + { "ldap_autofs_entry_object_class", "automount", SYSDB_AUTOFS_ENTRY_OC, NULL }, + { "ldap_autofs_entry_key", "automountKey", SYSDB_AUTOFS_ENTRY_KEY, NULL }, + { "ldap_autofs_entry_value", "automountInformation", SYSDB_AUTOFS_ENTRY_VALUE, NULL }, +}; + int ldap_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb, const char *conf_path, @@ -595,6 +619,86 @@ int ldap_get_sudo_options(TALLOC_CTX *memctx, return EOK; } +int ldap_get_autofs_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sdap_options *opts) +{ + const char *search_base; + struct sdap_attr_map *default_entry_map; + struct sdap_attr_map *default_mobject_map; + int ret; + + /* search base */ + search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE); + if (search_base != NULL) { + /* set autofs search bases if they are not */ + if (dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE) == NULL) { + ret = dp_opt_set_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE, + search_base); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not set autofs search base" + "to default value\n")); + return ret; + } + + DEBUG(SSSDBG_FUNC_DATA, ("Option %s set to %s\n", + opts->basic[SDAP_AUTOFS_SEARCH_BASE].opt_name, + dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE))); + } + } else { + DEBUG(SSSDBG_OP_FAILURE, ("Error: no autofs search base set\n")); + return ENOENT; + } + + ret = sdap_parse_search_base(opts, opts->basic, + SDAP_AUTOFS_SEARCH_BASE, + &opts->autofs_search_bases); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not parse autofs search base\n")); + return ret; + } + + /* attribute maps */ + switch (opts->schema_type) { + case SDAP_SCHEMA_RFC2307: + default_mobject_map = rfc2307_autofs_mobject_map; + default_entry_map = rfc2307_autofs_entry_map; + break; + case SDAP_SCHEMA_RFC2307BIS: + case SDAP_SCHEMA_IPA_V1: + case SDAP_SCHEMA_AD: + default_mobject_map = rfc2307bis_autofs_mobject_map; + default_entry_map = rfc2307bis_autofs_entry_map; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown LDAP schema!\n")); + return EINVAL; + } + + ret = sdap_get_map(opts, cdb, conf_path, + default_mobject_map, + SDAP_OPTS_AUTOFS_MAP, + &opts->autofs_mobject_map); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Could not get autofs map object attribute map\n")); + return ret; + } + + ret = sdap_get_map(opts, cdb, conf_path, + default_entry_map, + SDAP_OPTS_AUTOFS_ENTRY, + &opts->autofs_entry_map); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Could not get autofs entry object attribute map\n")); + return ret; + } + + return EOK; +} + errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx, struct dp_option *opts, int class, struct sdap_search_base ***_search_bases) @@ -635,6 +739,8 @@ errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx, break; case SDAP_SERVICE_SEARCH_BASE: class_name = "SERVICE"; + case SDAP_AUTOFS_SEARCH_BASE: + class_name = "AUTOFS"; break; default: DEBUG(SSSDBG_CONF_SETTINGS, diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 603a1ed9..c377bcb6 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -124,6 +124,11 @@ int ldap_get_sudo_options(TALLOC_CTX *memctx, const char *conf_path, struct sdap_options *opts); +int ldap_get_autofs_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sdap_options *opts); + int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index dd61a1e1..8c98c8ea 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -27,6 +27,7 @@ #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/sdap_access.h" #include "providers/ldap/sdap_sudo.h" +#include "providers/ldap/sdap_autofs.h" static void sdap_shutdown(struct be_req *req); @@ -411,6 +412,36 @@ int sssm_ldap_sudo_init(struct be_ctx *be_ctx, return sdap_sudo_init(be_ctx, id_ctx, ops, &data); } +int sssm_ldap_autofs_init(struct be_ctx *be_ctx, + struct bet_ops **ops, + void **pvt_data) +{ +#ifdef BUILD_AUTOFS + struct sdap_id_ctx *id_ctx; + void *data; + int ret; + + ret = sssm_ldap_id_init(be_ctx, ops, &data); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot init LDAP ID provider [%d]: %s\n", + ret, strerror(ret))); + return ret; + } + + id_ctx = talloc_get_type(data, struct sdap_id_ctx); + if (!id_ctx) { + DEBUG(SSSDBG_CRIT_FAILURE, ("No ID provider?\n")); + return EIO; + } + + return sdap_autofs_init(be_ctx, id_ctx, ops, pvt_data); +#else + DEBUG(SSSDBG_MINOR_FAILURE, ("Autofs init handler called but SSSD is " + "built without autofs support, ignoring\n")); + return EOK; +#endif +} + static void sdap_shutdown(struct be_req *req) { /* TODO: Clean up any internal data */ diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index 27cffd79..1f97f554 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -717,6 +717,8 @@ static errno_t sdap_set_search_base(struct sdap_options *opts, break; case SDAP_SERVICE_SEARCH_BASE: bases = &opts->service_search_bases; + case SDAP_AUTOFS_SEARCH_BASE: + bases = &opts->autofs_search_bases; break; default: return EINVAL; @@ -750,7 +752,8 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, ||!opts->user_search_bases || !opts->group_search_bases || !opts->netgroup_search_bases - || !opts->sudo_search_bases) { + || !opts->sudo_search_bases + || !opts->autofs_search_bases) { naming_context = get_naming_context(opts->basic, rootdse); if (naming_context == NULL) { DEBUG(1, ("get_naming_context failed.\n")); @@ -812,6 +815,14 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (ret != EOK) goto done; } + /* autofs */ + if (!opts->autofs_search_bases) { + ret = sdap_set_search_base(opts, + SDAP_AUTOFS_SEARCH_BASE, + naming_context); + if (ret != EOK) goto done; + } + ret = EOK; done: diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 2e1dfa95..0a0f996d 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -168,6 +168,7 @@ enum sdap_basic_opt { SDAP_SUDO_SEARCH_BASE, SDAP_SUDO_REFRESH_ENABLED, SDAP_SUDO_REFRESH_TIMEOUT, + SDAP_AUTOFS_SEARCH_BASE, SDAP_SCHEMA, SDAP_OFFLINE_TIMEOUT, SDAP_FORCE_UPPER_CASE_REALM, @@ -311,6 +312,21 @@ enum sdap_service_attrs { SDAP_OPTS_SERVICES /* attrs counter */ }; +enum sdap_autofs_map_attrs { + SDAP_OC_AUTOFS_MAP, + SDAP_AT_AUTOFS_MAP_NAME, + + SDAP_OPTS_AUTOFS_MAP /* attrs counter */ +}; + +enum sdap_autofs_entry_attrs { + SDAP_OC_AUTOFS_ENTRY, + SDAP_AT_AUTOFS_ENTRY_KEY, + SDAP_AT_AUTOFS_ENTRY_VALUE, + + SDAP_OPTS_AUTOFS_ENTRY /* attrs counter */ +}; + struct sdap_attr_map { const char *opt_name; const char *def_name; @@ -335,6 +351,8 @@ struct sdap_options { /* FIXME - should this go to a special struct to avoid mixing with name-service-switch maps? */ struct sdap_attr_map *sudorule_map; + struct sdap_attr_map *autofs_mobject_map; + struct sdap_attr_map *autofs_entry_map; /* supported schema types */ enum schema_type { @@ -350,6 +368,7 @@ struct sdap_options { struct sdap_search_base **netgroup_search_bases; struct sdap_search_base **sudo_search_bases; struct sdap_search_base **service_search_bases; + struct sdap_search_base **autofs_search_bases; }; struct sdap_server_opts { diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c new file mode 100644 index 00000000..ce8a1f96 --- /dev/null +++ b/src/providers/ldap/sdap_async_autofs.c @@ -0,0 +1,833 @@ +/* + SSSD + + Async LDAP Helper routines for autofs + + Authors: + Jakub Hrozek <jhrozek@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 "db/sysdb.h" +#include "providers/ldap/sdap_async_private.h" +#include "db/sysdb_autofs.h" +#include "providers/ldap/ldap_common.h" + +/* ====== Utility functions ====== */ +static const char * +get_autofs_map_name(struct sysdb_attrs *map, struct sdap_options *opts) +{ + errno_t ret; + struct ldb_message_element *el; + + ret = sysdb_attrs_get_el(map, + opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].sys_name, + &el); + if (ret) return NULL; + if (el->num_values == 0) return NULL; + + return (const char *)el->values[0].data; +} + +static const char * +get_autofs_entry_key(struct sysdb_attrs *entry, struct sdap_options *opts) +{ + errno_t ret; + struct ldb_message_element *el; + + ret = sysdb_attrs_get_el(entry, + opts->autofs_entry_map[SDAP_AT_AUTOFS_ENTRY_KEY].sys_name, + &el); + if (ret) return NULL; + if (el->num_values == 0) return NULL; + + return (const char *)el->values[0].data; +} + +static errno_t +save_autofs_entry(struct sysdb_ctx *sysdb, + struct sdap_options *opts, + struct sysdb_attrs *entry) +{ + const char *key; + const char *value; + struct ldb_message_element *el; + errno_t ret; + + key = get_autofs_entry_key(entry, opts); + if (!key) return EINVAL; + + ret = sysdb_attrs_get_el(entry, + opts->autofs_entry_map[SDAP_AT_AUTOFS_ENTRY_VALUE].sys_name, + &el); + if (ret) return ret; + if (el->num_values == 0) return EINVAL; + else value = (const char *)el->values[0].data; + + ret = sysdb_save_autofsentry(sysdb, key, value, NULL); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +static errno_t +save_autofs_entries(struct sysdb_ctx *sysdb, + struct sdap_options *opts, + char **add_entries, + struct sysdb_attrs **entries, + size_t num_entries) +{ + errno_t ret, tret; + const char *key; + bool in_transaction = false; + int i, j; + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot start sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + in_transaction = true; + + for (i=0; add_entries[i]; i++) { + for (j=0; j < num_entries; j++) { + key = get_autofs_entry_key(entries[j], opts); + if (!key) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("An entry without name? Skipping\n")); + return EINVAL; + } + + if (strcmp(add_entries[i], key)) { + continue; + } + + ret = save_autofs_entry(sysdb, opts, entries[j]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot save autofs entry [%d]: %s. Ignoring.\n", + ret, strerror(ret))); + continue; + } + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot commit sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + in_transaction = false; + + ret = EOK; +done: + if (in_transaction) { + tret = sysdb_transaction_cancel(sysdb); + if (tret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot cancel sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + } + } + return ret; +} + +static errno_t +save_autofs_map(struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_options *opts, + struct sysdb_attrs *map) +{ + const char *mapname; + errno_t ret; + time_t now; + + mapname = get_autofs_map_name(map, opts); + if (!mapname) return EINVAL; + + now = time(NULL); + + ret = sysdb_save_autofsmap(sysdb, mapname, mapname, + NULL, dom->autofsmap_timeout, now); + if (ret != EOK) { + return ret; + } + + return EOK; +} + +struct automntmaps_process_members_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; + struct sss_domain_info *dom; + int timeout; + struct sysdb_ctx *sysdb; + + char *filter; + const char **attrs; + + struct sysdb_attrs *map; + + struct sysdb_attrs **entries; + size_t entries_count; +}; + +static void +automntmaps_process_members_done(struct tevent_req *subreq); + +static struct tevent_req * +automntmaps_process_members_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_options *opts, + struct sdap_handle *sh, + struct sss_domain_info *dom, + int timeout, + struct sysdb_ctx *sysdb, + struct sysdb_attrs *map) +{ + errno_t ret; + struct tevent_req *req; + struct tevent_req *subreq; + struct automntmaps_process_members_state *state; + const char *orig_dn; + char *clean_orig_dn; + + req = tevent_req_create(mem_ctx, &state, + struct automntmaps_process_members_state); + if (!req) return NULL; + + state->ev = ev; + state->opts = opts; + state->dom = dom; + state->sh = sh; + state->sysdb = sysdb; + state->timeout = timeout; + + state->map = map; + + state->filter = talloc_asprintf(state, "(&(%s=*)(objectclass=%s))", + opts->autofs_entry_map[SDAP_AT_AUTOFS_ENTRY_KEY].name, + opts->autofs_entry_map[SDAP_OC_AUTOFS_ENTRY].name); + if (!state->filter) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to build filter\n")); + ret = ENOMEM; + goto immediate; + } + + ret = build_attrs_from_map(state, opts->autofs_entry_map, + SDAP_OPTS_AUTOFS_ENTRY, &state->attrs); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to build attributes from map\n")); + ret = ENOMEM; + goto immediate; + } + + ret = sysdb_attrs_get_string(state->map, SYSDB_ORIG_DN, &orig_dn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get originalDN\n")); + goto immediate; + } + + /* FIXME - should test if the DN is in the current base? */ + ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot sanitize originalDN\n")); + goto immediate; + } + + DEBUG(SSSDBG_TRACE_FUNC, + ("Examining autofs map [%s]\n", clean_orig_dn)); + + subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, + clean_orig_dn, LDAP_SCOPE_SUBTREE, + state->filter, state->attrs, + opts->autofs_entry_map, + SDAP_OPTS_AUTOFS_ENTRY, + state->timeout); + if (!subreq) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot start search for entries\n")); + goto immediate; + } + tevent_req_set_callback(subreq, automntmaps_process_members_done, req); + return req; + +immediate: + if (ret != EOK) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } + tevent_req_post(req, ev); + return req; +} + +static void +automntmaps_process_members_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct automntmaps_process_members_state *state = + tevent_req_data(req, struct automntmaps_process_members_state); + errno_t ret; + + ret = sdap_get_generic_recv(subreq, state, + &state->entries_count, &state->entries); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, + ("Search for autofs entries, returned %d results.\n", + state->entries_count)); + + tevent_req_done(req); + return; +} + +static errno_t +automntmaps_process_members_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + size_t *entries_count, + struct sysdb_attrs ***entries) +{ + struct automntmaps_process_members_state *state; + state = tevent_req_data(req, struct automntmaps_process_members_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (entries_count) { + *entries_count = state->entries_count; + } + + if (entries) { + *entries = talloc_steal(mem_ctx, state->entries); + } + + return EOK; +} + +struct sdap_get_automntmap_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; + struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; + const char **attrs; + const char *base_filter; + char *filter; + int timeout; + + char *higher_timestamp; + + struct sysdb_attrs **map; + size_t count; + + struct sysdb_attrs **entries; + size_t entries_count; + + size_t base_iter; + struct sdap_search_base **search_bases; +}; + +static errno_t +sdap_get_automntmap_next_base(struct tevent_req *req); +static void +sdap_get_automntmap_process(struct tevent_req *subreq); + +static struct tevent_req * +sdap_get_automntmap_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sss_domain_info *dom, + struct sysdb_ctx *sysdb, + struct sdap_options *opts, + struct sdap_search_base **search_bases, + struct sdap_handle *sh, + const char **attrs, + const char *filter, + int timeout) +{ + errno_t ret; + struct tevent_req *req; + struct sdap_get_automntmap_state *state; + + req = tevent_req_create(memctx, &state, struct sdap_get_automntmap_state); + if (!req) return NULL; + + state->ev = ev; + state->opts = opts; + state->dom = dom; + state->sh = sh; + state->sysdb = sysdb; + state->attrs = attrs; + state->higher_timestamp = NULL; + state->map = NULL; + state->count = 0; + state->timeout = timeout; + state->base_filter = filter; + state->base_iter = 0; + state->search_bases = search_bases; + + ret = sdap_get_automntmap_next_base(req); + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, state->ev); + } + return req; +} + +static errno_t +sdap_get_automntmap_next_base(struct tevent_req *req) +{ + struct tevent_req *subreq; + struct sdap_get_automntmap_state *state; + + state = tevent_req_data(req, struct sdap_get_automntmap_state); + + talloc_zfree(state->filter); + state->filter = sdap_get_id_specific_filter(state, + state->base_filter, + state->search_bases[state->base_iter]->filter); + if (!state->filter) { + return ENOMEM; + } + + DEBUG(SSSDBG_TRACE_FUNC, + ("Searching for automount maps with base [%s]\n", + state->search_bases[state->base_iter]->basedn)); + + subreq = sdap_get_generic_send( + state, state->ev, state->opts, state->sh, + state->search_bases[state->base_iter]->basedn, + state->search_bases[state->base_iter]->scope, + state->filter, state->attrs, + state->opts->autofs_mobject_map, SDAP_OPTS_AUTOFS_MAP, + state->timeout); + if (!subreq) { + return EIO; + } + tevent_req_set_callback(subreq, sdap_get_automntmap_process, req); + + return EOK; +} + +static void +sdap_get_automntmap_done(struct tevent_req *subreq); + +static void +sdap_get_automntmap_process(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_automntmap_state *state = tevent_req_data(req, + struct sdap_get_automntmap_state); + errno_t ret; + + ret = sdap_get_generic_recv(subreq, state, + &state->count, &state->map); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, + ("Search for autofs maps, returned %d results.\n", state->count)); + + if (state->count == 0) { + /* No maps found in this search */ + state->base_iter++; + if (state->search_bases[state->base_iter]) { + /* There are more search bases to try */ + ret = sdap_get_automntmap_next_base(req); + if (ret != EOK) { + tevent_req_error(req, ENOENT); + } + return; + } + + tevent_req_error(req, ENOENT); + return; + } else if (state->count > 1) { + DEBUG(SSSDBG_OP_FAILURE, + ("The search yielded more than one autofs map\n")); + tevent_req_error(req, EIO); + return; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, ("Processing autofs maps\n")); + subreq = automntmaps_process_members_send(state, state->ev, state->opts, + state->sh, state->dom, + state->timeout, state->sysdb, + state->map[0]); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_get_automntmap_done, req); + + return; +} + +static void +sdap_get_automntmap_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_automntmap_state *state = tevent_req_data(req, + struct sdap_get_automntmap_state); + errno_t ret; + + ret = automntmaps_process_members_recv(subreq, state, &state->entries_count, + &state->entries); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("automount map members received\n")); + tevent_req_done(req); + return; +} + +static errno_t +sdap_get_automntmap_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct sysdb_attrs **map, + size_t *entries_count, + struct sysdb_attrs ***entries) +{ + struct sdap_get_automntmap_state *state = tevent_req_data(req, + struct sdap_get_automntmap_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (map) { + *map = talloc_steal(mem_ctx, state->map[0]); + } + + if (entries_count) { + *entries_count = state->entries_count; + } + + if (entries) { + *entries = talloc_steal(mem_ctx, state->entries); + } + + return EOK; +} + +struct sdap_autofs_setautomntent_state { + char *filter; + const char **attrs; + 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 +sdap_autofs_setautomntent_done(struct tevent_req *subreq); + +struct tevent_req * +sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + 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) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct sdap_autofs_setautomntent_state *state; + char *clean_mapname; + errno_t ret; + + req = tevent_req_create(memctx, &state, + struct sdap_autofs_setautomntent_state); + if (!req) return NULL; + + if (!mapname) { + DEBUG(SSSDBG_CRIT_FAILURE, ("No map name given\n")); + ret = EINVAL; + goto fail; + } + + state->sh = sh; + state->sysdb = sysdb; + state->opts = opts; + state->sdap_op = op; + state->dom = dom; + state->mapname = mapname; + + ret = sss_filter_sanitize(state, mapname, &clean_mapname); + if (ret != EOK) { + goto fail; + } + + state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", + state->opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].name, + clean_mapname, + state->opts->autofs_mobject_map[SDAP_OC_AUTOFS_MAP].name); + if (!state->filter) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to build filter\n")); + ret = ENOMEM; + goto fail; + } + talloc_free(clean_mapname); + + ret = build_attrs_from_map(state, state->opts->autofs_mobject_map, + SDAP_OPTS_AUTOFS_MAP, &state->attrs); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to build attributes from map\n")); + ret = ENOMEM; + goto fail; + } + + subreq = sdap_get_automntmap_send(state, ev, dom, + sysdb, state->opts, + state->opts->autofs_search_bases, + state->sh, + state->attrs, state->filter, + dp_opt_get_int(state->opts->basic, + SDAP_SEARCH_TIMEOUT)); + if (!subreq) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n")); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sdap_autofs_setautomntent_done, req); + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static errno_t +sdap_autofs_setautomntent_save(struct tevent_req *req); + +static void +sdap_autofs_setautomntent_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_autofs_setautomntent_state *state = tevent_req_data(req, + struct sdap_autofs_setautomntent_state); + + ret = sdap_get_automntmap_recv(subreq, state, &state->map, + &state->entries_count, &state->entries); + talloc_zfree(subreq); + if (ret != EOK) { + if (ret == ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Could not find automount map\n")); + } else { + DEBUG(SSSDBG_OP_FAILURE, + ("sdap_get_automntmap_recv failed [%d]: %s\n", + ret, strerror(ret))); + } + tevent_req_error(req, ret); + return; + } + + ret = sdap_autofs_setautomntent_save(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not save automount map\n")); + tevent_req_error(req, ret); + return; + } + + state->dp_error = DP_ERR_OK; + tevent_req_done(req); + return; +} + +static errno_t +sdap_autofs_setautomntent_save(struct tevent_req *req) +{ + struct sdap_autofs_setautomntent_state *state = tevent_req_data(req, + struct sdap_autofs_setautomntent_state); + errno_t ret, tret; + bool in_transaction = false; + TALLOC_CTX *tmp_ctx; + struct ldb_message *sysdb_map; + struct ldb_message_element *map_members = NULL; + char **sysdb_entrylist; + char **ldap_entrylist; + char **add_entries; + char **del_entries; + size_t i; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + + if (state->entries_count == 0) { + /* No entries for this map in LDAP. + * We need to ensure that there are no entries + * in the sysdb either. + */ + ldap_entrylist = NULL; + } else { + ret = sysdb_attrs_to_list( + tmp_ctx, state->entries, + state->entries_count, + state->opts->autofs_entry_map[SDAP_AT_AUTOFS_ENTRY_KEY].name, + &ldap_entrylist); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("sysdb_attrs_primary_name_list failed [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + } + + ret = sysdb_get_map_byname(tmp_ctx, state->sysdb, state->mapname, + &sysdb_map); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + ("cache lookup for the map failed [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + + if (sysdb_map) { + map_members = ldb_msg_find_element(sysdb_map, SYSDB_MEMBER); + } + + if (!map_members || map_members->num_values == 0) { + /* No map members for this map in sysdb currently */ + sysdb_entrylist = NULL; + } else { + sysdb_entrylist = talloc_array(state, char *, map_members->num_values+1); + if (!sysdb_entrylist) { + ret = ENOMEM; + goto done; + } + + /* Get a list of the map members by name only */ + for (i=0; i < map_members->num_values; i++) { + ret = sysdb_map_entry_name(sysdb_entrylist, state->sysdb, + (const char *) map_members->values[i].data, + &sysdb_entrylist[i]); + if (ret != EOK) { + goto done; + } + } + sysdb_entrylist[map_members->num_values] = NULL; + } + + /* Find the differences between the sysdb and LDAP lists + * Entries in the sysdb only must be removed. + */ + ret = diff_string_lists(tmp_ctx, ldap_entrylist, sysdb_entrylist, + &add_entries, &del_entries, NULL); + if (ret != EOK) goto done; + + ret = sysdb_transaction_start(state->sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot start sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + in_transaction = true; + + /* Save the map itself */ + ret = save_autofs_map(state->sysdb, state->dom, state->opts, state->map); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot save autofs map entry [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + + /* Create entries that don't exist yet */ + if (add_entries && add_entries[0]) { + ret = save_autofs_entries(state->sysdb, state->opts, + add_entries, state->entries, + state->entries_count); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot save autofs entries [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + } + + /* Save the memberships */ + DEBUG(SSSDBG_TRACE_FUNC, ("Updating memberships for %s\n", state->mapname)); + ret = sysdb_autofs_map_update_members(state->sysdb, state->mapname, + (const char *const *) add_entries, + (const char *const *) del_entries); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Membership update failed [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + + ret = sysdb_transaction_commit(state->sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot commit sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + in_transaction = false; + + ret = EOK; +done: + if (in_transaction) { + tret = sysdb_transaction_cancel(state->sysdb); + if (tret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot cancel sysdb transaction [%d]: %s\n", + ret, strerror(ret))); + } + } + talloc_zfree(tmp_ctx); + return ret; +} + +errno_t +sdap_autofs_setautomntent_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c new file mode 100644 index 00000000..5e3e3320 --- /dev/null +++ b/src/providers/ldap/sdap_autofs.c @@ -0,0 +1,291 @@ +/* + SSSD + + LDAP handler for autofs + + Authors: + Jakub Hrozek <jhrozek@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 <errno.h> +#include <tevent.h> + +#include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_autofs.h" +#include "providers/ldap/sdap.h" +#include "providers/ldap/sdap_async.h" +#include "providers/dp_backend.h" +#include "db/sysdb_autofs.h" +#include "util/util.h" + +static void +sdap_autofs_shutdown(struct be_req *req) +{ + sdap_handler_done(req, DP_ERR_OK, EOK, NULL); +} + +void sdap_autofs_handler(struct be_req *be_req); + +/* Autofs Handler */ +struct bet_ops sdap_autofs_ops = { + .handler = sdap_autofs_handler, + .finalize = sdap_autofs_shutdown +}; + +int sdap_autofs_init(struct be_ctx *be_ctx, + struct sdap_id_ctx *id_ctx, + struct bet_ops **ops, + void **pvt_data) +{ + int ret; + + DEBUG(SSSDBG_TRACE_INTERNAL, ("Initializing autofs LDAP back end\n")); + + *ops = &sdap_autofs_ops; + *pvt_data = id_ctx; + + ret = ldap_get_autofs_options(id_ctx, be_ctx->cdb, + be_ctx->conf_path, id_ctx->opts); + if (ret != EOK) { + return ret; + } + + return ret; +} + +static struct tevent_req * +sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, + const char *map_name); + +static void sdap_autofs_handler_done(struct tevent_req *req); + +void sdap_autofs_handler(struct be_req *be_req) +{ + struct sdap_id_ctx *id_ctx; + struct be_autofs_req *autofs_req; + struct tevent_req *req; + int ret = EOK; + + DEBUG(SSSDBG_TRACE_INTERNAL, ("sdap autofs handler called\n")); + + id_ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_AUTOFS].pvt_bet_data, + struct sdap_id_ctx); + + if (be_is_offline(id_ctx->be)) { + return sdap_handler_done(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline"); + } + + autofs_req = talloc_get_type(be_req->req_data, struct be_autofs_req); + + DEBUG(SSSDBG_FUNC_DATA, ("Requested refresh for: %s\n", + autofs_req->mapname ? autofs_req->mapname : "<ALL>\n")); + + req = sdap_autofs_get_map_send(be_req, be_req->be_ctx->ev, + id_ctx, autofs_req->mapname); + if (!req) { + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(req, sdap_autofs_handler_done, be_req); + + return; +fail: + be_req->fn(be_req, DP_ERR_FATAL, ret, NULL); +} + +struct autofs_get_map_state { + struct tevent_context *ev; + struct sdap_id_ctx *ctx; + struct sdap_id_op *op; + const char *map_name; + + 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 *req); + +static struct tevent_req * +sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, + const char *map_name) +{ + struct tevent_req *req; + struct autofs_get_map_state *state; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct autofs_get_map_state); + if (!req) return NULL; + + 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_cache); + if (!state->op) { + DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed\n")); + ret = ENOMEM; + goto fail; + } + + ret = sdap_autofs_get_map_retry(req); + if (ret != EOK) { + goto fail; + } + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static errno_t +sdap_autofs_get_map_retry(struct tevent_req *req) +{ + struct autofs_get_map_state *state = + tevent_req_data(req, struct autofs_get_map_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_get_map_connect_done, req); + return EOK; +} + +static void +sdap_autofs_get_map_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct autofs_get_map_state *state = + tevent_req_data(req, struct autofs_get_map_state); + int dp_error = DP_ERR_FATAL; + int ret; + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + + subreq = sdap_autofs_setautomntent_send(state, state->ev, + state->ctx->be->domain, + state->ctx->be->sysdb, + sdap_id_op_handle(state->op), + state->op, + state->ctx->opts, + state->map_name); + if (!subreq) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("sdap_autofs_setautomntent_send failed\n")); + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_autofs_get_map_done, req); + +} + +static void +sdap_autofs_get_map_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct autofs_get_map_state *state = + tevent_req_data(req, struct autofs_get_map_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_get_map_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->sysdb, state->map_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot delete autofs map %s [%d]: %s\n", + state->map_name, ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + } + + state->dp_error = DP_ERR_OK; + tevent_req_done(req); +} + +static errno_t +sdap_autofs_get_map_recv(struct tevent_req *req, int *dp_error_out) +{ + struct autofs_get_map_state *state = + tevent_req_data(req, struct autofs_get_map_state); + + if (dp_error_out) { + *dp_error_out = state->dp_error; + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +static void +sdap_autofs_handler_done(struct tevent_req *req) +{ + struct be_req *be_req = + tevent_req_callback_data(req, struct be_req); + int dperr; + errno_t ret; + + ret = sdap_autofs_get_map_recv(req, &dperr); + sdap_handler_done(be_req, dperr, ret, strerror(ret)); +} + diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h new file mode 100644 index 00000000..0369e264 --- /dev/null +++ b/src/providers/ldap/sdap_autofs.h @@ -0,0 +1,47 @@ +/* + SSSD + + LDAP handler for autofs + + Authors: + Jakub Hrozek <jhrozek@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 _SDAP_AUTOFS_H_ +#define _SDAP_AUTOFS_H_ + +int sdap_autofs_init(struct be_ctx *be_ctx, + struct sdap_id_ctx *id_ctx, + struct bet_ops **ops, + void **pvt_data); + +struct tevent_req * +sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + 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); + +errno_t +sdap_autofs_setautomntent_recv(struct tevent_req *req); + +#endif /* _SDAP_AUTOFS_H_ */ + |