diff options
-rw-r--r-- | contrib/sssd.spec.in | 1 | ||||
-rw-r--r-- | server/Makefile.am | 4 | ||||
-rw-r--r-- | server/man/sssd-ipa.5.xml | 182 | ||||
-rw-r--r-- | server/providers/data_provider.h | 18 | ||||
-rw-r--r-- | server/providers/data_provider_opts.c | 179 | ||||
-rw-r--r-- | server/providers/ipa/ipa_common.c | 319 | ||||
-rw-r--r-- | server/providers/ipa/ipa_common.h | 61 | ||||
-rw-r--r-- | server/providers/ipa/ipa_init.c | 23 |
8 files changed, 779 insertions, 8 deletions
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index f652802d..4d1e0c99 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -142,6 +142,7 @@ rm -rf $RPM_BUILD_ROOT %attr(700,root,root) %dir %{_sysconfdir}/sssd/sssd.api.d %config %{_sysconfdir}/sssd/sssd.api.d/ %{_mandir}/man5/sssd.conf.5* +%{_mandir}/man5/sssd-ipa.5* %{_mandir}/man5/sssd-krb5.5* %{_mandir}/man5/sssd-ldap.5* %{_mandir}/man8/sssd.8* diff --git a/server/Makefile.am b/server/Makefile.am index 88d22088..81f438d3 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -265,6 +265,7 @@ dist_noinst_HEADERS = \ providers/ldap/ldap_common.h \ providers/ldap/sdap.h \ providers/ldap/sdap_async.h \ + providers/ipa/ipa_common.h \ tools/tools_util.h \ tools/sss_sync_ops.h \ resolv/async_resolv.h \ @@ -472,6 +473,7 @@ libsss_krb5_la_LDFLAGS = \ libsss_ipa_la_SOURCES = \ providers/ipa/ipa_init.c \ + providers/ipa/ipa_common.c \ providers/ldap/ldap_id.c \ providers/ldap/ldap_auth.c \ providers/ldap/ldap_common.c \ @@ -552,7 +554,7 @@ XSLTPROC_FLAGS = --catalogs --xinclude --nonet dist_man_MANS = man/sss_useradd.8 man/sss_userdel.8 man/sss_usermod.8 \ man/sss_groupadd.8 man/sss_groupdel.8 man/sss_groupmod.8 \ man/sssd.8 man/sssd.conf.5 man/sssd-ldap.5 man/sssd-krb5.5 \ - man/sssd_krb5_locator_plugin.8 + man/sssd-ipa.5 man/sssd_krb5_locator_plugin.8 SUFFIXES = .1.xml .1 .3.xml .3 .5.xml .5 .8.xml .8 .1.xml.1: diff --git a/server/man/sssd-ipa.5.xml b/server/man/sssd-ipa.5.xml new file mode 100644 index 00000000..c5c96d11 --- /dev/null +++ b/server/man/sssd-ipa.5.xml @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.4//EN" +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> +<reference> +<title>SSSD Manual pages</title> +<refentry> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" /> + + <refmeta> + <refentrytitle>sssd-ipa</refentrytitle> + <manvolnum>5</manvolnum> + <refmiscinfo class="manual">File Formats and Conventions</refmiscinfo> + </refmeta> + + <refnamediv id='name'> + <refname>sssd-ipa</refname> + <refpurpose>the configuration file for SSSD</refpurpose> + </refnamediv> + + <refsect1 id='description'> + <title>DESCRIPTION</title> + <para> + This manual page describes the configuration of the IPA Provider + for + <citerefentry> + <refentrytitle>sssd</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry>. + For a detailed syntax reference, please refer to the <quote>FILE FORMAT</quote> section of the + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page + </para> + <para> + The IPA provider is a backend useful to connect to an IPA server. + (see freeipa.org for information about IPa servers). + It requires that the machine has been joined to the IPA domain, + and configuration is almost entirely self discovered and obtained + directly from the server. + </para> + + </refsect1> + + <refsect1 id='file-format'> + <title>CONFIGURATION OPTIONS</title> + <para> + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page, section <quote>DOMAIN SECTIONS</quote> + for details on the configuration of a SSSD domain. + <variablelist> + <varlistentry> + <term>ipa_domain (string)</term> + <listitem> + <para> + Specifies the name of the IPA domain. + This is optional, if not provided the configuration + domain name is used. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ipa_server (string)</term> + <listitem> + <para> + The name of the IPA server. + If autodiscovery is enabled this is optional. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ipa_hostname (string)</term> + <listitem> + <para> + Optional. Maybe set on some machine where the + hostname(5) does not reflect the fully qualified + name used in the IPA domain to identify this host. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>krb5_ccachedir (string)</term> + <listitem> + <para> + Directory to store credential caches. + </para> + <para> + Default: /tmp + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ipa_search_timeout (integer)</term> + <listitem> + <para> + Specifies the timeout (in seconds) after which + a search against the ipa server is forcibly + terminated. + </para> + <para> + Default: 60 + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ipa_network_timeout (integer)</term> + <listitem> + <para> + Specifies the timeout (in seconds) after which + the + <citerefentry> + <refentrytitle>poll</refentrytitle> + <manvolnum>2</manvolnum> + </citerefentry>/<citerefentry> + <refentrytitle>select</refentrytitle> + <manvolnum>2</manvolnum> + </citerefentry> + following a non-search operation against the ipa + server is forcibly terminated. + </para> + <para> + Default: 6 + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ipa_offline_timeout (integer)</term> + <listitem> + <para> + Specifies the "black-out" time before any new + network operation is attempted after the ipa + provider has turned into offline operation mode. + </para> + <para> + Default: 60 + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + </refsect1> + + <refsect1 id='example'> + <title>EXAMPLE</title> + <para> + The following example assumes that SSSD is correctly + configured and example.com is one of the domains in the + <replaceable>[sssd]</replaceable> section. This examples shows only + the ipa provider specific options. + </para> + <para> +<programlisting> + [domain/example.com] + id_provider = ipa + ipa_server = ipaserver.example.com + ipa_hostname = myhost.example.com +</programlisting> + </para> + </refsect1> + + <refsect1 id='see_also'> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>sssd</refentrytitle><manvolnum>8</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> +</reference> diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h index 7653f078..57b318fd 100644 --- a/server/providers/data_provider.h +++ b/server/providers/data_provider.h @@ -180,6 +180,11 @@ int dp_get_options(TALLOC_CTX *memctx, int num_opts, struct dp_option **_opts); +int dp_copy_options(TALLOC_CTX *memctx, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts); + const char *_dp_opt_get_cstring(struct dp_option *opts, int id, const char *location); char *_dp_opt_get_string(struct dp_option *opts, @@ -196,4 +201,17 @@ bool _dp_opt_get_bool(struct dp_option *opts, #define dp_opt_get_int(o, i) _dp_opt_get_int(o, i, __FUNCTION__) #define dp_opt_get_bool(o, i) _dp_opt_get_bool(o, i, __FUNCTION__) +int _dp_opt_set_string(struct dp_option *opts, int id, + const char *s, const char *location); +int _dp_opt_set_blob(struct dp_option *opts, int id, + struct dp_opt_blob b, const char *location); +int _dp_opt_set_int(struct dp_option *opts, int id, + int i, const char *location); +int _dp_opt_set_bool(struct dp_option *opts, int id, + bool b, const char *location); +#define dp_opt_set_string(o, i, v) _dp_opt_set_string(o, i, v, __FUNCTION__) +#define dp_opt_set_blob(o, i, v) _dp_opt_set_blob(o, i, v, __FUNCTION__) +#define dp_opt_set_int(o, i, v) _dp_opt_set_int(o, i, v, __FUNCTION__) +#define dp_opt_set_bool(o, i, v) _dp_opt_set_bool(o, i, v, __FUNCTION__) + #endif /* __DATA_PROVIDER_ */ diff --git a/server/providers/data_provider_opts.c b/server/providers/data_provider_opts.c index 581b9287..98283e43 100644 --- a/server/providers/data_provider_opts.c +++ b/server/providers/data_provider_opts.c @@ -33,7 +33,7 @@ int dp_get_options(TALLOC_CTX *memctx, struct dp_option *opts; int i, ret; - opts = talloc_array(memctx, struct dp_option, num_opts); + opts = talloc_zero_array(memctx, struct dp_option, num_opts); if (!opts) return ENOMEM; for (i = 0; i < num_opts; i++) { @@ -80,7 +80,7 @@ int dp_get_options(TALLOC_CTX *memctx, opts[i].val.blob.length = 0; } - DEBUG(6, ("Option %s has %s value\n", + DEBUG(6, ("Option %s has %s binary value.\n", opts[i].opt_name, opts[i].val.blob.length?"a":"no")); break; @@ -126,6 +126,95 @@ done: /* =Basic-Option-Helpers================================================== */ +int dp_copy_options(TALLOC_CTX *memctx, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts) +{ + struct dp_option *opts; + int i, ret; + + opts = talloc_zero_array(memctx, struct dp_option, num_opts); + if (!opts) return ENOMEM; + + for (i = 0; i < num_opts; i++) { + opts[i].opt_name = src_opts[i].opt_name; + opts[i].type = src_opts[i].type; + opts[i].def_val = src_opts[i].def_val; + ret = EOK; + + switch (src_opts[i].type) { + case DP_OPT_STRING: + if (src_opts[i].val.string) { + ret = dp_opt_set_string(opts, i, src_opts[i].val.string); + } else if (src_opts[i].def_val.string) { + ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string); + } + if (ret != EOK) { + DEBUG(0, ("Failed to copy value for option (%s)\n", + opts[i].opt_name)); + goto done; + } + DEBUG(6, ("Option %s has value %s\n", + opts[i].opt_name, opts[i].val.cstring)); + break; + + case DP_OPT_BLOB: + if (src_opts[i].val.blob.data) { + ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob); + } else if (src_opts[i].def_val.blob.data) { + ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob); + } + if (ret != EOK) { + DEBUG(0, ("Failed to retrieve value for option (%s)\n", + opts[i].opt_name)); + goto done; + } + DEBUG(6, ("Option %s has %s binary value.\n", + opts[i].opt_name, + opts[i].val.blob.length?"a":"no")); + break; + + case DP_OPT_NUMBER: + if (src_opts[i].val.number) { + ret = dp_opt_set_int(opts, i, src_opts[i].val.number); + } else if (src_opts[i].def_val.number) { + ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number); + } + if (ret != EOK) { + DEBUG(0, ("Failed to retrieve value for option (%s)\n", + opts[i].opt_name)); + goto done; + } + DEBUG(6, ("Option %s has value %d\n", + opts[i].opt_name, opts[i].val.number)); + break; + + case DP_OPT_BOOL: + if (src_opts[i].val.boolean) { + ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean); + } else if (src_opts[i].def_val.boolean) { + ret = dp_opt_set_int(opts, i, src_opts[i].def_val.boolean); + } + if (ret != EOK) { + DEBUG(0, ("Failed to retrieve value for option (%s)\n", + opts[i].opt_name)); + goto done; + } + DEBUG(6, ("Option %s is %s\n", + opts[i].opt_name, + opts[i].val.boolean?"TRUE":"FALSE")); + break; + } + } + + *_opts = opts; + +done: + if (ret != EOK) talloc_zfree(opts); + return ret; +} + static const char *dp_opt_type_to_string(enum dp_opt_type type) { switch (type) { @@ -141,6 +230,7 @@ static const char *dp_opt_type_to_string(enum dp_opt_type type) return NULL; } +/* Getters */ const char *_dp_opt_get_cstring(struct dp_option *opts, int id, const char *location) { @@ -207,3 +297,88 @@ bool _dp_opt_get_bool(struct dp_option *opts, return opts[id].val.boolean; } +/* Setters */ +int _dp_opt_set_string(struct dp_option *opts, int id, + const char *s, const char *location) +{ + if (opts[id].type != DP_OPT_STRING) { + DEBUG(0, ("[%s] Requested type 'String' for option '%s'" + " but type is '%s'!\n", + location, opts[id].opt_name, + dp_opt_type_to_string(opts[id].type))); + return EINVAL; + } + + if (opts[id].val.string) { + talloc_zfree(opts[id].val.string); + } + if (s) { + opts[id].val.string = talloc_strdup(opts, s); + if (!opts[id].val.string) { + DEBUG(0, ("talloc_strdup() failed!\n")); + return ENOMEM; + } + } + + return EOK; +} + +int _dp_opt_set_blob(struct dp_option *opts, int id, + struct dp_opt_blob b, const char *location) +{ + if (opts[id].type != DP_OPT_BLOB) { + DEBUG(0, ("[%s] Requested type 'Blob' for option '%s'" + " but type is '%s'!\n", + location, opts[id].opt_name, + dp_opt_type_to_string(opts[id].type))); + return EINVAL; + } + + if (opts[id].val.blob.data) { + talloc_zfree(opts[id].val.blob.data); + opts[id].val.blob.length = 0; + } + if (b.data) { + opts[id].val.blob.data = talloc_memdup(opts, b.data, b.length); + if (!opts[id].val.blob.data) { + DEBUG(0, ("talloc_memdup() failed!\n")); + return ENOMEM; + } + } + opts[id].val.blob.length = b.length; + + return EOK; +} + +int _dp_opt_set_int(struct dp_option *opts, int id, + int i, const char *location) +{ + if (opts[id].type != DP_OPT_NUMBER) { + DEBUG(0, ("[%s] Requested type 'Number' for option '%s'" + " but type is '%s'!\n", + location, opts[id].opt_name, + dp_opt_type_to_string(opts[id].type))); + return EINVAL; + } + + opts[id].val.number = i; + + return EOK; +} + +int _dp_opt_set_bool(struct dp_option *opts, int id, + bool b, const char *location) +{ + if (opts[id].type != DP_OPT_BOOL) { + DEBUG(0, ("[%s] Requested type 'Boolean' for option '%s'" + " but type is '%s'!\n", + location, opts[id].opt_name, + dp_opt_type_to_string(opts[id].type))); + return EINVAL; + } + + opts[id].val.boolean = b; + + return EOK; +} + diff --git a/server/providers/ipa/ipa_common.c b/server/providers/ipa/ipa_common.c new file mode 100644 index 00000000..799ac2f9 --- /dev/null +++ b/server/providers/ipa/ipa_common.c @@ -0,0 +1,319 @@ +/* + SSSD + + IPA Provider Common Functions + + Authors: + Simo Sorce <ssorce@redhat.com> + + Copyright (C) 2009 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/ipa/ipa_common.h" + +struct dp_option ipa_basic_opts[] = { + { "ipa_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ipa_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ipa_hostname", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ipa_search_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, + { "ipa_network_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER }, + { "ipa_opt_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER }, + { "ipa_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, + { "ipa_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER }, + { "ipa_stale_time", DP_OPT_NUMBER, { .number = 1800 }, NULL_NUMBER }, +}; + +struct dp_option ipa_def_ldap_opts[] = { + { "ldap_uri", 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, NULL_STRING, NULL_STRING}, + { "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB }, + { "ldap_search_timeout", DP_OPT_NUMBER, { .number = 60 }, 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_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 }, + { "ldap_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER }, + { "ldap_stale_time", DP_OPT_NUMBER, { .number = 1800 }, NULL_NUMBER }, + { "ldap_tls_cacert", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_tls_cacertdir", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_id_use_start_tls", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_sasl_mech", DP_OPT_STRING, { "GSSAPI" } , NULL_STRING }, + { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "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_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING } +}; + +struct sdap_id_map ipa_user_map[] = { + { "ldap_user_object_class", "posixAccount", SYSDB_USER_CLASS, NULL }, + { "ldap_user_name", "uid", SYSDB_NAME, NULL }, + { "ldap_user_pwd", "userPassword", 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", "homeDirectory", SYSDB_HOMEDIR, NULL }, + { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL }, + { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL }, + { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL }, + { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL }, + { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL }, + { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_user_shadow_last_change", "shadowLastChange", SYSDB_SHADOWPW_LASTCHANGE, NULL }, + { "ldap_user_shadow_min", "shadowMin", SYSDB_SHADOWPW_MIN, NULL }, + { "ldap_user_shadow_max", "shadowMax", SYSDB_SHADOWPW_MAX, NULL }, + { "ldap_user_shadow_warning", "shadowWarning", SYSDB_SHADOWPW_WARNING, NULL }, + { "ldap_user_shadow_inactive", "shadowInactive", SYSDB_SHADOWPW_INACTIVE, NULL }, + { "ldap_user_shadow_expire", "shadowExpire", SYSDB_SHADOWPW_EXPIRE, NULL }, + { "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL }, + { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, + { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, + { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL } +}; + +struct sdap_id_map ipa_group_map[] = { + { "ldap_group_object_class", "posixGroup", SYSDB_GROUP_CLASS, NULL }, + { "ldap_group_name", "cn", SYSDB_NAME, NULL }, + { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL }, + { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, + { "ldap_group_member", "member", SYSDB_MEMBER, NULL }, + { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL }, + { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL } +}; + +int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn) +{ + const char *s; + char *dn; + char *p; + int l; + + s = domain; + dn = talloc_strdup(memctx, "dc="); + + while ((p = strchr(s, '.'))) { + l = p - s; + dn = talloc_asprintf_append_buffer(dn, "%.*s,dc=", l, s); + if (!dn) { + return ENOMEM; + } + s = p + 1; + } + dn = talloc_strdup_append_buffer(dn, s); + if (!dn) { + return ENOMEM; + } + + *basedn = dn; + return EOK; +} + +int ipa_get_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sss_domain_info *dom, + struct ipa_options **_opts) +{ + struct ipa_options *opts; + char *domain; + char *server; + int ret; + + opts = talloc_zero(memctx, struct ipa_options); + if (!opts) return ENOMEM; + + ret = dp_get_options(opts, cdb, conf_path, + ipa_basic_opts, + IPA_OPTS_BASIC, + &opts->basic); + if (ret != EOK) { + goto done; + } + + domain = dp_opt_get_string(opts->basic, IPA_DOMAIN); + if (!domain) { + ret = dp_opt_set_string(opts->basic, IPA_DOMAIN, dom->name); + if (ret != EOK) { + goto done; + } + } + + /* FIXME: Make non-fatal once we have discovery */ + server = dp_opt_get_string(opts->basic, IPA_SERVER); + if (!server) { + DEBUG(0, ("Can't find ipa server, missing option!\n")); + ret = EINVAL; + goto done; + } + + ret = EOK; + *_opts = opts; + +done: + if (ret != EOK) { + talloc_zfree(opts); + } + return ret; +} + +/* the following preprocessor code is 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 build error */ +#if SDAP_OPTS_BASIC > 27 +#error There are ldap options not accounted for +#endif + +int ipa_get_id_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct ipa_options *ipa_opts, + struct sdap_options **_opts) +{ + TALLOC_CTX *tmpctx; + char *hostname; + char *basedn; + char *realm; + char *value; + int ret; + int i; + + tmpctx = talloc_new(memctx); + if (!tmpctx) { + return ENOMEM; + } + + ipa_opts->id = talloc_zero(memctx, struct sdap_options); + if (!ipa_opts->id) { + ret = ENOMEM; + goto done; + } + + /* generate sdap options */ + ret = dp_copy_options(ipa_opts, ipa_def_ldap_opts, + SDAP_OPTS_BASIC, &ipa_opts->id->basic); + if (ret != EOK) { + goto done; + } + + /* set ldap_uri */ + value = talloc_asprintf(tmpctx, "ldap://%s", + dp_opt_get_string(ipa_opts->basic, IPA_SERVER)); + if (!value) { + ret = ENOMEM; + goto done; + } + ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_URI, value); + if (ret != EOK) { + goto done; + } + + ret = domain_to_basedn(tmpctx, + dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN), + &basedn); + if (ret != EOK) { + goto done; + } + + /* FIXME: get values by querying IPA */ + /* set ldap_user_search_base */ + value = talloc_asprintf(tmpctx, "cn=users,cn=accounts,%s", basedn); + if (!value) { + ret = ENOMEM; + goto done; + } + ret = dp_opt_set_string(ipa_opts->id->basic, + SDAP_USER_SEARCH_BASE, value); + if (ret != EOK) { + goto done; + } + + /* set ldap_group_search_base */ + value = talloc_asprintf(tmpctx, "cn=groups,cn=accounts,%s", basedn); + if (!value) { + ret = ENOMEM; + goto done; + } + ret = dp_opt_set_string(ipa_opts->id->basic, + SDAP_GROUP_SEARCH_BASE, value); + if (ret != EOK) { + goto done; + } + + /* set the ldap_sasl_authid if the ipa_hostname override was specified */ + hostname = dp_opt_get_string(ipa_opts->basic, IPA_HOSTNAME); + if (hostname) { + value = talloc_asprintf(tmpctx, "host/%s", hostname); + if (!value) { + ret = ENOMEM; + goto done; + } + ret = dp_opt_set_string(ipa_opts->id->basic, + SDAP_SASL_AUTHID, value); + if (ret != EOK) { + goto done; + } + } + + /* set krb realm */ + realm = dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN); + for (i = 0; realm[i]; i++) { + realm[i] = toupper(realm[i]); + } + ret = dp_opt_set_string(ipa_opts->id->basic, + SDAP_KRB5_REALM, realm); + if (ret != EOK) { + goto done; + } + + ret = sdap_get_map(ipa_opts->id, + cdb, conf_path, + ipa_user_map, + SDAP_OPTS_USER, + &ipa_opts->id->user_map); + if (ret != EOK) { + goto done; + } + + ret = sdap_get_map(ipa_opts->id, + cdb, conf_path, + ipa_group_map, + SDAP_OPTS_GROUP, + &ipa_opts->id->group_map); + if (ret != EOK) { + goto done; + } + + ret = EOK; + *_opts = ipa_opts->id; + +done: + talloc_zfree(tmpctx); + if (ret != EOK) { + talloc_zfree(ipa_opts->id); + } + return ret; +} + diff --git a/server/providers/ipa/ipa_common.h b/server/providers/ipa/ipa_common.h new file mode 100644 index 00000000..80f5294a --- /dev/null +++ b/server/providers/ipa/ipa_common.h @@ -0,0 +1,61 @@ +/* + SSSD + + IPA Common utility code + + Copyright (C) Simo Sorce <ssorce@redhat.com> 2009 + + 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 _IPA_COMMON_H_ +#define _IPA_COMMON_H_ + +#include "util/util.h" +#include "confdb/confdb.h" +#include "providers/ldap/ldap_common.h" + +enum ipa_basic_opt { + IPA_DOMAIN = 0, + IPA_SERVER, + IPA_HOSTNAME, + IPA_SEARCH_TIMEOUT, + IPA_NETWORK_TIMEOUT, + IPA_OPT_TIMEOUT, + IPA_OFFLINE_TIMEOUT, + IPA_ENUM_REFRESH_TIMEOUT, + IPA_STALE_TIME, + + IPA_OPTS_BASIC /* opts counter */ +}; + +struct ipa_options { + struct dp_option *basic; + struct sdap_options *id; +}; + +/* options parsers */ +int ipa_get_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sss_domain_info *dom, + struct ipa_options **_opts); + +int ipa_get_id_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct ipa_options *ipa_opts, + struct sdap_options **_opts); + +#endif /* _IPA_COMMON_H_ */ diff --git a/server/providers/ipa/ipa_init.c b/server/providers/ipa/ipa_init.c index ebbeec4a..9cdcf4b0 100644 --- a/server/providers/ipa/ipa_init.c +++ b/server/providers/ipa/ipa_init.c @@ -25,9 +25,11 @@ #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> -#include "providers/ldap/ldap_common.h" +#include "providers/ipa/ipa_common.h" #include "providers/krb5/krb5_auth.h" +struct ipa_options *ipa_options = NULL; + /* Id Handler */ struct bet_ops ipa_id_ops = { .handler = sdap_account_info_handler, @@ -51,13 +53,24 @@ int sssm_ipa_init(struct be_ctx *bectx, struct sdap_id_ctx *ctx; int ret; - ctx = talloc_zero(bectx, struct sdap_id_ctx); - if (!ctx) return ENOMEM; + if (!ipa_options) { + ipa_get_options(bectx, bectx->cdb, + bectx->conf_path, + bectx->domain, &ipa_options); + } + if (!ipa_options) { + return ENOMEM; + } + ctx = talloc_zero(bectx, struct sdap_id_ctx); + if (!ctx) { + return ENOMEM; + } ctx->be = bectx; - ret = ldap_get_options(ctx, bectx->cdb, - bectx->conf_path, &ctx->opts); + ret = ipa_get_id_options(ctx, bectx->cdb, + bectx->conf_path, + ipa_options, &ctx->opts); if (ret != EOK) { goto done; } |