On Wed, Apr 23, 2014 at 11:28:51AM -0400, Simo Sorce wrote:
> On Wed, 2014-04-23 at 17:12 +0200, Jakub Hrozek wrote:
> > 
> > OK, new patches that use ':' as a separator are attached. This version
> > uses key:value, but that can be swapped.
> 
> Why do you consider the 'key' to be the remote attribute name ?
> I can't make sense of it :-)
> 
> The "key" sssd looks for in it's cache is the sysdb name, no ?
> 
> Simo.
> 

I don't really mind too much and appears Jan does not either. So I
simply swapped the order in the attached patches, now it's sysdb:LDAP.

Man page was changed accordingly.

Jan, could you check if the man page change (src/man/sssd-ldap.5.xml in
the second patch) reads good to you?
>From 92acd3f95ef5ae8ce49f398f9ef616a79887193f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Mon, 21 Apr 2014 21:33:36 +0200
Subject: [PATCH 1/3] LDAP: Fix off-by-one bug in sdap_copy_opts

The sdap_copy_opts function copied all the arguments except for the
sentinel.
---
 Makefile.am                    |  3 +++
 src/providers/ldap/sdap.c      |  5 +++-
 src/tests/ipa_ldap_opt-tests.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 
5dc359596416f1202c5bbf5cc2585b60eeeea6f1..56d8e1df648822a1fe8b3ca5fc8995f3c78a8566
 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1215,6 +1215,9 @@ auth_tests_LDADD = \
 
 ipa_ldap_opt_tests_SOURCES = \
     src/providers/data_provider_opts.c \
+    src/providers/ldap/sdap.c \
+    src/providers/ldap/sdap_range.c \
+    src/util/sss_ldap.c \
     src/tests/ipa_ldap_opt-tests.c
 ipa_ldap_opt_tests_CFLAGS = \
     $(AM_CFLAGS) \
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 
aa6b0e921767ab97f025998276e16ec9abdfc03f..b303547a4524f5dc90eaf16dc6ca0e579a8240ae
 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -36,7 +36,7 @@ int sdap_copy_map(TALLOC_CTX *memctx,
     struct sdap_attr_map *map;
     int i;
 
-    map = talloc_array(memctx, struct sdap_attr_map, num_entries);
+    map = talloc_array(memctx, struct sdap_attr_map, num_entries + 1);
     if (!map) {
         return ENOMEM;
     }
@@ -64,6 +64,9 @@ int sdap_copy_map(TALLOC_CTX *memctx,
               map[i].name ? map[i].name : "");
     }
 
+    /* Include the sentinel */
+    memset(&map[num_entries], 0, sizeof(struct sdap_attr_map));
+
     *_map = map;
     return EOK;
 }
diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c
index 
25a094082dc369092f10ad823d98909027dd9a7e..bbb49935dec47983c4d04ef73385a4ed8a1ea372
 100644
--- a/src/tests/ipa_ldap_opt-tests.c
+++ b/src/tests/ipa_ldap_opt-tests.c
@@ -48,6 +48,14 @@ struct test_domain test_domains[] = {
     { NULL, NULL}
 };
 
+/* Mock parsing search base without overlinking the test */
+errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx,
+                               struct dp_option *opts, int class,
+                               struct sdap_search_base ***_search_bases)
+{
+    return EOK;
+}
+
 START_TEST(test_domain_to_basedn)
 {
     int ret;
@@ -226,6 +234,49 @@ START_TEST(test_copy_opts)
 }
 END_TEST
 
+START_TEST(test_copy_sdap_map)
+{
+    errno_t ret;
+    struct sdap_attr_map *out_map;
+
+    ret = sdap_copy_map(global_talloc_context,
+                        rfc2307_user_map, SDAP_OPTS_USER, &out_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].def_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].sys_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].opt_name == NULL);
+    talloc_free(out_map);
+
+    ret = sdap_copy_map(global_talloc_context,
+                        rfc2307bis_user_map, SDAP_OPTS_USER, &out_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].def_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].sys_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].opt_name == NULL);
+    talloc_free(out_map);
+
+    ret = sdap_copy_map(global_talloc_context,
+                        ipa_user_map, SDAP_OPTS_USER, &out_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].def_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].sys_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].opt_name == NULL);
+    talloc_free(out_map);
+
+    ret = sdap_copy_map(global_talloc_context,
+                        gen_ad2008r2_user_map, SDAP_OPTS_USER, &out_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].def_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].sys_name == NULL);
+    fail_unless(out_map[SDAP_OPTS_USER].opt_name == NULL);
+    talloc_free(out_map);
+}
+END_TEST
+
 Suite *ipa_ldap_opt_suite (void)
 {
     Suite *s = suite_create ("ipa_ldap_opt");
@@ -245,6 +296,10 @@ Suite *ipa_ldap_opt_suite (void)
     tcase_add_test (tc_dp_opts, test_copy_opts);
     suite_add_tcase (s, tc_dp_opts);
 
+    TCase *tc_sdap_opts = tcase_create ("sdap_opts");
+    tcase_add_test (tc_sdap_opts, test_copy_sdap_map);
+    suite_add_tcase (s, tc_sdap_opts);
+
     return s;
 }
 
-- 
1.9.0

>From 38101cd4c40b2938f448ade44cc4f90210d06a31 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Wed, 31 Jul 2013 10:59:43 +0200
Subject: [PATCH 2/3] LDAP: Make it possible to extend an attribute map

https://fedorahosted.org/sssd/ticket/2073

This commit adds a new option ldap_user_extra_attrs that is unset by
default. When set, the option contains a list of LDAP attributes the LDAP
provider would download and store in addition to the usual set.

The list can either contain LDAP attribute names only, or colon-separated
tuples of LDAP attribute and SSSD cache attribute name. In case only LDAP
attribute name is specified, the attribute is saved to the cache verbatim.
Using a custom SSSD attribute name might be required by environments that
configure several SSSD domains with different LDAP schemas.
---
 src/config/SSSDConfig/__init__.py.in          |   1 +
 src/config/etc/sssd.api.d/sssd-ldap.conf      |   1 +
 src/man/sssd-ldap.5.xml                       |  48 +++++++++++
 src/providers/ad/ad_common.c                  |   9 ++
 src/providers/ad/ad_opts.h                    |   1 +
 src/providers/ipa/ipa_common.c                |   9 ++
 src/providers/ipa/ipa_netgroups.c             |   3 +-
 src/providers/ipa/ipa_opts.h                  |   1 +
 src/providers/ldap/ldap_id.c                  |   3 +-
 src/providers/ldap/ldap_options.c             |  45 ++++++++++
 src/providers/ldap/ldap_opts.h                |   1 +
 src/providers/ldap/sdap.c                     | 116 +++++++++++++++++++++++++
 src/providers/ldap/sdap.h                     |   9 ++
 src/providers/ldap/sdap_async_enum.c          |   3 +-
 src/providers/ldap/sdap_async_groups.c        |   6 +-
 src/providers/ldap/sdap_async_groups_ad.c     |   4 +-
 src/providers/ldap/sdap_async_initgroups.c    |   6 +-
 src/providers/ldap/sdap_async_nested_groups.c |   5 +-
 src/providers/ldap/sdap_async_users.c         |   6 +-
 src/tests/ipa_ldap_opt-tests.c                | 117 ++++++++++++++++++++++++++
 src/util/util_errors.c                        |   2 +
 src/util/util_errors.h                        |   2 +
 22 files changed, 383 insertions(+), 15 deletions(-)

diff --git a/src/config/SSSDConfig/__init__.py.in 
b/src/config/SSSDConfig/__init__.py.in
index 
6382dd570dcdacd4f47adae92540643c1d369f9b..64807d8d19d6c16e6afefaebf3c2fcc2e424f6df
 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -275,6 +275,7 @@ option_strings = {
     'ldap_user_nds_login_expiration_time' : _('loginExpirationTime attribute 
of NDS'),
     'ldap_user_nds_login_allowed_time_map' : _('loginAllowedTimeMap attribute 
of NDS'),
     'ldap_user_ssh_public_key' : _('SSH public key attribute'),
+    'ldap_user_extra_attrs' : _('A list of extra attributes to download along 
with the user entry'),
 
     'ldap_group_search_base' : _('Base DN for group lookups'),
     # not used # 'ldap_group_search_scope' : _('Scope of group lookups'),
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf 
b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 
257e859df24f6c0cbd7b2dd72402790e11bf06c5..0057c080f84d4b5f75107903b03a3cc91f03cc83
 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -48,6 +48,7 @@ ldap_id_mapping = bool, None, false
 ldap_user_search_base = str, None, false
 ldap_user_search_scope = str, None, false
 ldap_user_search_filter = str, None, false
+ldap_user_extra_attrs = str, None, false
 ldap_user_object_class = str, None, false
 ldap_user_name = str, None, false
 ldap_user_uid_number = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 
f93b418c45d9bcd32499860a858c3f829bb245ca..6426fe4fca5dc9bb9bc84fcbf633404144052d01
 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -616,6 +616,54 @@
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>ldap_user_extra_attrs (string)</term>
+                    <listitem>
+                        <para>
+                            Comma-separated list of LDAP attributes that SSSD
+                            would fetch along with the usual set of user
+                            attributes.
+                        </para>
+                        <para>
+                            The list can either contain LDAP attribute names
+                            only, or colon-separated tuples of SSSD cache
+                            attribute name and LDAP attribute name. In
+                            case only LDAP attribute name is specified,
+                            the attribute is saved to the cache verbatim.
+                            Using a custom SSSD attribute name might be
+                            required by environments that configure several
+                            SSSD domains with different LDAP schemas.
+                        </para>
+                        <para>
+                            Please note that several attribute names are
+                            reserved by SSSD, notably the <quote>name</quote>
+                            attribute. SSSD would report an error if any of
+                            the reserved attribute names is used as an extra
+                            attribute name.
+                        </para>
+                        <para>
+                            Examples:
+                        </para>
+                        <para>
+                            ldap_user_extra_attrs = telephoneNumber
+                        </para>
+                        <para>
+                            Save the <quote>telephoneNumber</quote> attribute 
from LDAP
+                            as <quote>telephoneNumber</quote> to the cache.
+                        </para>
+                        <para>
+                            ldap_user_extra_attrs = phone:telephoneNumber
+                        </para>
+                        <para>
+                            Save the <quote>telephoneNumber</quote> attribute 
from LDAP
+                            as <quote>phone</quote> to the cache.
+                        </para>
+                        <para>
+                            Default: not set
+                        </para>
+                    </listitem>
+                </varlistentry>
+
                 <varlistentry condition="with_ssh">
                     <term>ldap_user_ssh_public_key (string)</term>
                     <listitem>
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 
57a0a3c39c55fec127948c19238f12d3e8827913..8528ad3dcdab58ff17c200b8f6f226cd50e8cfed
 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -201,6 +201,15 @@ ad_create_sdap_options(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    ret = sdap_extend_map(id_opts,
+                          id_opts->user_map,
+                          SDAP_OPTS_USER, NULL,
+                          &id_opts->user_map,
+                          &id_opts->user_map_cnt);
+    if (ret != EOK) {
+        goto done;
+    }
+
     /* Group map */
     ret = sdap_get_map(id_opts,
                        cdb, conf_path,
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index 
6b4e874edc8f9cac3c141cb22d4d78ee8320b75d..69a4dfa8e4d0bd4c45858b6af095b1ed512a7ec1
 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -54,6 +54,7 @@ struct dp_option ad_def_ldap_opts[] = {
     { "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_user_extra_attrs", 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 },
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 
f84748267d65bedbadf39db3466d28502bfa0e3e..19de10d8bb92a4b3d0c8353eae128f3b4709a7af
 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -547,6 +547,15 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
         goto done;
     }
 
+    ret = sdap_extend_map(ipa_opts->id,
+                          ipa_opts->id->user_map,
+                          SDAP_OPTS_USER, NULL,
+                          &ipa_opts->id->user_map,
+                          &ipa_opts->id->user_map_cnt);
+    if (ret != EOK) {
+        goto done;
+    }
+
     ret = sdap_get_map(ipa_opts->id,
                        cdb, conf_path,
                        ipa_group_map,
diff --git a/src/providers/ipa/ipa_netgroups.c 
b/src/providers/ipa/ipa_netgroups.c
index 
9cc374bc17eb53accaf607736a19555e17ebf4e1..db29d29ee8f18d3d963402c4811bdef43bae63dc
 100644
--- a/src/providers/ipa/ipa_netgroups.c
+++ b/src/providers/ipa/ipa_netgroups.c
@@ -492,7 +492,8 @@ static int ipa_netgr_fetch_users(struct 
ipa_get_netgroups_state *state,
                                                      SDAP_USER_SEARCH_BASE),
                                    LDAP_SCOPE_SUBTREE,
                                    filter, attrs, state->opts->user_map,
-                                   SDAP_OPTS_USER, state->timeout, true);
+                                   state->opts->user_map_cnt,
+                                   state->timeout, true);
 
     state->current_entity = ENTITY_USER;
     if (subreq == NULL) {
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 
909c431eefa778f97767af241829ac81256fc464..949a054ddbfb84fc523d5478aa3f038a1adcddba
 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -77,6 +77,7 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "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_user_extra_attrs", 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 },
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 
ab0a5c911e8a2b4d488b4121fbfc51b52d9ef773..297d6016ee0a64478a57036cd8efc04629a7e701
 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -215,7 +215,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
     }
 
     /* TODO: handle attrs_type */
-    ret = build_attrs_from_map(state, ctx->opts->user_map, SDAP_OPTS_USER,
+    ret = build_attrs_from_map(state, ctx->opts->user_map,
+                               ctx->opts->user_map_cnt,
                                NULL, &state->attrs, NULL);
     if (ret != EOK) goto fail;
 
diff --git a/src/providers/ldap/ldap_options.c 
b/src/providers/ldap/ldap_options.c
index 
8813572ffad65ff126d50c27e81648d63518504c..11ed9c31f0fc03113e5f7ba58b5ce8b74fe6545a
 100644
--- a/src/providers/ldap/ldap_options.c
+++ b/src/providers/ldap/ldap_options.c
@@ -23,6 +23,44 @@
 #include "providers/ldap/sdap_async_private.h"
 #include "util/crypto/sss_crypto.h"
 
+static int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
+                                     struct sdap_options *opts,
+                                     int extra_attr_index,
+                                     struct sdap_attr_map *src_map,
+                                     size_t num_entries,
+                                     struct sdap_attr_map **_map,
+                                     size_t *_new_size)
+{
+    const char *extra_attrs;
+    char **extra_attrs_list;
+    errno_t ret;
+
+    extra_attrs = dp_opt_get_string(opts->basic, extra_attr_index);
+    if (extra_attrs == NULL) {
+        *_map = src_map;
+        *_new_size = num_entries;
+        return EOK;
+    }
+
+    /* split server parm into a list */
+    ret = split_on_separator(mem_ctx, extra_attrs, ',', true, true,
+                             &extra_attrs_list, NULL);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "Failed to parse server list!\n");
+        return ret;
+    }
+
+    ret = sdap_extend_map(mem_ctx, src_map,
+                          num_entries, extra_attrs_list,
+                          _map, _new_size);
+    talloc_free(extra_attrs_list);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    return EOK;
+}
+
 int ldap_get_options(TALLOC_CTX *memctx,
                      struct sss_domain_info *dom,
                      struct confdb_ctx *cdb,
@@ -257,6 +295,13 @@ int ldap_get_options(TALLOC_CTX *memctx,
         goto done;
     }
 
+    ret = sdap_extend_map_with_list(opts, opts, SDAP_USER_EXTRA_ATTRS,
+                                    opts->user_map, SDAP_OPTS_USER,
+                                    &opts->user_map, &opts->user_map_cnt);
+    if (ret != EOK) {
+        goto done;
+    }
+
     ret = sdap_get_map(opts, cdb, conf_path,
                        default_group_map,
                        SDAP_OPTS_GROUP,
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index 
d45ad46f078d06b22d16aa6312e449dcdef4d21c..90899b94800420fdbcd2c5c0213e2790343e1dc4
 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -43,6 +43,7 @@ struct dp_option default_basic_opts[] = {
     { "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_user_extra_attrs", 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 },
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 
b303547a4524f5dc90eaf16dc6ca0e579a8240ae..37a187436a6e17e9e41f981970b9c5ab5e685f46
 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -71,6 +71,122 @@ int sdap_copy_map(TALLOC_CTX *memctx,
     return EOK;
 }
 
+static errno_t split_extra_attr(TALLOC_CTX *mem_ctx,
+                                char *conf_attr,
+                                char **_sysdb_attr,
+                                char **_ldap_attr)
+{
+    char *ldap_attr;
+    char *sysdb_attr;
+    char *sep;
+
+    ldap_attr = conf_attr;
+
+    sep = strchr(conf_attr, ':');
+    if (sep == NULL) {
+        sysdb_attr = talloc_strdup(mem_ctx, conf_attr);
+        ldap_attr = talloc_strdup(mem_ctx, conf_attr);
+    } else {
+        if (sep == conf_attr || *(sep + 1) == '\0') {
+            return ERR_INVALID_EXTRA_ATTR;
+        }
+
+        sysdb_attr = talloc_strndup(mem_ctx, ldap_attr,
+                                    sep - ldap_attr);
+        ldap_attr = talloc_strdup(mem_ctx, sep+1);
+    }
+
+    if (sysdb_attr == NULL || ldap_attr == NULL) {
+        return ENOMEM;
+    }
+
+    *_sysdb_attr = sysdb_attr;
+    *_ldap_attr = ldap_attr;
+    return EOK;
+}
+
+static bool is_sysdb_duplicate(struct sdap_attr_map *map,
+                               int num_entries,
+                               const char *sysdb_attr)
+{
+    int i;
+
+    for (i = 0; i < num_entries; i++) {
+        if (strcmp(map[i].sys_name, sysdb_attr) == 0) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+int sdap_extend_map(TALLOC_CTX *memctx,
+                    struct sdap_attr_map *src_map,
+                    size_t num_entries,
+                    char **extra_attrs,
+                    struct sdap_attr_map **_map,
+                    size_t *_new_size)
+{
+    struct sdap_attr_map *map;
+    size_t nextra = 0;
+    size_t i;
+    char *ldap_attr;
+    char *sysdb_attr;
+    errno_t ret;
+
+    if (extra_attrs == NULL) {
+        DEBUG(SSSDBG_FUNC_DATA, "No extra attributes\n");
+        *_map = src_map;
+        *_new_size = num_entries;
+        return EOK;
+    }
+
+    for (nextra = 0; extra_attrs[nextra]; nextra++) ;
+    DEBUG(SSSDBG_FUNC_DATA, "%zu extra attributes\n", nextra);
+
+    map = talloc_realloc(memctx, src_map, struct sdap_attr_map,
+                         num_entries + nextra + 1);
+    if (map == NULL) {
+        return ENOMEM;
+    }
+
+    for (i = 0; extra_attrs[i]; i++) {
+        ret = split_extra_attr(map, extra_attrs[i], &sysdb_attr, &ldap_attr);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot split %s\n", extra_attrs[i]);
+            continue;
+        }
+
+        if (is_sysdb_duplicate(map, num_entries, sysdb_attr)) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                  "Attribute %s (%s in LDAP) is already used by SSSD, please "
+                  "choose a different cache name\n", sysdb_attr, ldap_attr);
+            return ERR_DUP_EXTRA_ATTR;
+        }
+
+        map[num_entries+i].name = ldap_attr;
+        map[num_entries+i].sys_name = sysdb_attr;
+        map[num_entries+i].opt_name = talloc_strdup(map,
+                                                map[num_entries+i].name);
+        map[num_entries+i].def_name = talloc_strdup(map,
+                                                map[num_entries+i].name);
+        if (map[num_entries+i].opt_name == NULL ||
+            map[num_entries+i].sys_name == NULL ||
+            map[num_entries+i].name == NULL ||
+            map[num_entries+i].def_name == NULL) {
+            return ENOMEM;
+        }
+        DEBUG(SSSDBG_TRACE_FUNC, "Extending map with %s\n", extra_attrs[i]);
+    }
+
+    /* Sentinel */
+    memset(&map[num_entries+nextra], 0, sizeof(struct sdap_attr_map));
+
+    *_map = map;
+    *_new_size = num_entries + nextra;
+    return EOK;
+}
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 
ad239a8d07a445013e5bf86a514acb505fc40a13..38eec1c4dcd10ea839457bbef442e5993a7bf762
 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -159,6 +159,7 @@ enum sdap_basic_opt {
     SDAP_USER_SEARCH_BASE,
     SDAP_USER_SEARCH_SCOPE,
     SDAP_USER_SEARCH_FILTER,
+    SDAP_USER_EXTRA_ATTRS,
     SDAP_GROUP_SEARCH_BASE,
     SDAP_GROUP_SEARCH_SCOPE,
     SDAP_GROUP_SEARCH_FILTER,
@@ -412,6 +413,7 @@ struct sdap_options {
     struct dp_option *basic;
     struct sdap_attr_map *gen_map;
     struct sdap_attr_map *user_map;
+    size_t user_map_cnt;
     struct sdap_attr_map *group_map;
     struct sdap_attr_map *netgroup_map;
     struct sdap_attr_map *service_map;
@@ -467,6 +469,13 @@ int sdap_copy_map(TALLOC_CTX *memctx,
                  int num_entries,
                  struct sdap_attr_map **_map);
 
+int sdap_extend_map(TALLOC_CTX *memctx,
+                    struct sdap_attr_map *src_map,
+                    size_t num_entries,
+                    char **extra_attrs,
+                    struct sdap_attr_map **_map,
+                    size_t *_new_size);
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
diff --git a/src/providers/ldap/sdap_async_enum.c 
b/src/providers/ldap/sdap_async_enum.c
index 
ebd9ffafbedff48d2da5773322a08163a7e0177b..1c69c07f814e3f791dcd4f98edfaa9457ab8ae47
 100644
--- a/src/providers/ldap/sdap_async_enum.c
+++ b/src/providers/ldap/sdap_async_enum.c
@@ -617,7 +617,8 @@ static struct tevent_req *enum_users_send(TALLOC_CTX 
*memctx,
     }
 
     /* TODO: handle attrs_type */
-    ret = build_attrs_from_map(state, ctx->opts->user_map, SDAP_OPTS_USER,
+    ret = build_attrs_from_map(state, ctx->opts->user_map,
+                               ctx->opts->user_map_cnt,
                                NULL, &state->attrs, NULL);
     if (ret != EOK) goto fail;
 
diff --git a/src/providers/ldap/sdap_async_groups.c 
b/src/providers/ldap/sdap_async_groups.c
index 
4240bb585d57a80199d040ac44891ee1b6429e05..89a5afb91e8fe666f834720c6b97e74e266822a6
 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -1038,7 +1038,7 @@ struct tevent_req *sdap_process_group_send(TALLOC_CTX 
*memctx,
                             struct sdap_process_group_state);
     if (!req) return NULL;
 
-    ret = build_attrs_from_map(grp_state, opts->user_map, SDAP_OPTS_USER,
+    ret = build_attrs_from_map(grp_state, opts->user_map, opts->user_map_cnt,
                                NULL, &attrs, NULL);
     if (ret) {
         goto done;
@@ -1188,7 +1188,7 @@ sdap_process_missing_member_2307bis(struct tevent_req 
*req,
                                        grp_state->filter,
                                        grp_state->attrs,
                                        grp_state->opts->user_map,
-                                       SDAP_OPTS_USER,
+                                       grp_state->opts->user_map_cnt,
                                        dp_opt_get_int(grp_state->opts->basic,
                                                       SDAP_SEARCH_TIMEOUT),
                                        false);
@@ -1495,7 +1495,7 @@ next:
                                        state->filter,
                                        state->attrs,
                                        state->opts->user_map,
-                                       SDAP_OPTS_USER,
+                                       state->opts->user_map_cnt,
                                        dp_opt_get_int(state->opts->basic,
                                                       SDAP_SEARCH_TIMEOUT),
                                        false);
diff --git a/src/providers/ldap/sdap_async_groups_ad.c 
b/src/providers/ldap/sdap_async_groups_ad.c
index 
9bb21d29bdde4bb9402d8b49f69b184969c94550..8db587c96d569fc691486b252ff8f2c7d96e29c2
 100644
--- a/src/providers/ldap/sdap_async_groups_ad.c
+++ b/src/providers/ldap/sdap_async_groups_ad.c
@@ -72,7 +72,7 @@ sdap_get_ad_match_rule_members_send(TALLOC_CTX *mem_ctx,
     state->search_bases = opts->sdom->user_search_bases;
 
     /* Request all of the user attributes that we know about. */
-    ret = build_attrs_from_map(state, opts->user_map, SDAP_OPTS_USER,
+    ret = build_attrs_from_map(state, opts->user_map, opts->user_map_cnt,
                                NULL, &state->attrs, NULL);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE,
@@ -157,7 +157,7 @@ sdap_get_ad_match_rule_members_next_base(struct tevent_req 
*req)
             state->search_bases[state->base_iter]->basedn,
             state->search_bases[state->base_iter]->scope,
             state->filter, state->attrs,
-            state->opts->user_map, SDAP_OPTS_USER,
+            state->opts->user_map, state->opts->user_map_cnt,
             state->timeout, true);
     if (!subreq) {
         return ENOMEM;
diff --git a/src/providers/ldap/sdap_async_initgroups.c 
b/src/providers/ldap/sdap_async_initgroups.c
index 
5334ef84d095b531dc16ccd853a913e27327f5f6..401ab82dcd38ba05c437618bcc1cb4a92fae9698
 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2704,7 +2704,9 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX 
*memctx,
         return NULL;
     }
 
-    ret = build_attrs_from_map(state, state->opts->user_map, SDAP_OPTS_USER,
+    ret = build_attrs_from_map(state,
+                               state->opts->user_map,
+                               state->opts->user_map_cnt,
                                NULL, &state->user_attrs, NULL);
     if (ret) {
         talloc_zfree(req);
@@ -2752,7 +2754,7 @@ static errno_t sdap_get_initgr_next_base(struct 
tevent_req *req)
             state->user_search_bases[state->user_base_iter]->basedn,
             state->user_search_bases[state->user_base_iter]->scope,
             state->filter, state->user_attrs,
-            state->opts->user_map, SDAP_OPTS_USER,
+            state->opts->user_map, state->opts->user_map_cnt,
             state->timeout,
             false);
     if (!subreq) {
diff --git a/src/providers/ldap/sdap_async_nested_groups.c 
b/src/providers/ldap/sdap_async_nested_groups.c
index 
51e88bbfb2d9bc8a7a77737baafb2b3b8b886e95..4ef3d79cbd4b9d0ee48362591106fb9413a1fcaa
 100644
--- a/src/providers/ldap/sdap_async_nested_groups.c
+++ b/src/providers/ldap/sdap_async_nested_groups.c
@@ -1587,7 +1587,8 @@ sdap_nested_group_lookup_user_send(TALLOC_CTX *mem_ctx,
     /* search */
     subreq = sdap_get_generic_send(state, ev, group_ctx->opts, group_ctx->sh,
                                    member->dn, LDAP_SCOPE_BASE, filter, attrs,
-                                   group_ctx->opts->user_map, SDAP_OPTS_USER,
+                                   group_ctx->opts->user_map,
+                                   group_ctx->opts->user_map_cnt,
                                    dp_opt_get_int(group_ctx->opts->basic,
                                                   SDAP_SEARCH_TIMEOUT),
                                    false);
@@ -2029,7 +2030,7 @@ sdap_nested_group_deref_send(TALLOC_CTX *mem_ctx,
     }
 
     maps[0].map = opts->user_map;
-    maps[0].num_attrs = SDAP_OPTS_USER;
+    maps[0].num_attrs = opts->user_map_cnt;
     maps[1].map = opts->group_map;
     maps[1].num_attrs = SDAP_OPTS_GROUP;
 
diff --git a/src/providers/ldap/sdap_async_users.c 
b/src/providers/ldap/sdap_async_users.c
index 
ef5478f9424ba7c2f26c1ceff4c9cc9c82c3f54c..be0536ef3c3ffaf398c4f2d3e85094d4deb7bd81
 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -447,7 +447,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
         }
     }
 
-    for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) {
+    for (i = SDAP_FIRST_EXTRA_USER_AT; i < opts->user_map_cnt; i++) {
         ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name,
                                   NULL, user_name, user_attrs);
         if (ret) {
@@ -475,7 +475,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
     /* Make sure that any attributes we requested from LDAP that we
      * did not receive are also removed from the sysdb
      */
-    ret = list_missing_attrs(user_attrs, opts->user_map, SDAP_OPTS_USER,
+    ret = list_missing_attrs(user_attrs, opts->user_map, opts->user_map_cnt,
                              attrs, &missing);
     if (ret != EOK) {
         goto done;
@@ -694,7 +694,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req 
*req)
             state->search_bases[state->base_iter]->basedn,
             state->search_bases[state->base_iter]->scope,
             state->filter, state->attrs,
-            state->opts->user_map, SDAP_OPTS_USER,
+            state->opts->user_map, state->opts->user_map_cnt,
             state->timeout,
             state->enumeration); /* If we're enumerating, we need paging */
     if (subreq == NULL) {
diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c
index 
bbb49935dec47983c4d04ef73385a4ed8a1ea372..fffdc7e739fe5d7f9a0a52ffb2574958472eadef
 100644
--- a/src/tests/ipa_ldap_opt-tests.c
+++ b/src/tests/ipa_ldap_opt-tests.c
@@ -277,6 +277,116 @@ START_TEST(test_copy_sdap_map)
 }
 END_TEST
 
+START_TEST(test_extra_opts)
+{
+    errno_t ret;
+    char *extra_attrs[] =  { discard_const("foo"),
+                             discard_const("baz:bar"),
+                             NULL };
+    struct sdap_attr_map *in_map;
+    struct sdap_attr_map *out_map;
+    size_t new_size;
+
+    ret = sdap_copy_map(global_talloc_context, rfc2307_user_map,
+                        SDAP_OPTS_USER, &in_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+    ret = sdap_extend_map(global_talloc_context,
+                          in_map,
+                          SDAP_OPTS_USER,
+                          extra_attrs,
+                          &out_map, &new_size);
+    fail_unless(ret == EOK, "[%s]", sss_strerror(ret));
+
+    /* Two extra and sentinel */
+    fail_unless(new_size != SDAP_OPTS_USER + 3);
+    /* Foo would be saved to sysdb verbatim */
+    ck_assert_str_eq(out_map[SDAP_OPTS_USER].name, "foo");
+    ck_assert_str_eq(out_map[SDAP_OPTS_USER].sys_name, "foo");
+    /* Bar would be saved to sysdb as baz */
+    ck_assert_str_eq(out_map[SDAP_OPTS_USER+1].name, "bar");
+    ck_assert_str_eq(out_map[SDAP_OPTS_USER+1].sys_name, "baz");
+    fail_unless(out_map[SDAP_OPTS_USER+2].name == NULL);
+
+    talloc_free(out_map);
+}
+END_TEST
+
+START_TEST(test_no_extra_opts)
+{
+    errno_t ret;
+    struct sdap_attr_map *in_map;
+    struct sdap_attr_map *out_map;
+    size_t new_size;
+
+    ret = sdap_copy_map(global_talloc_context, rfc2307_user_map,
+                        SDAP_OPTS_USER, &in_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+    ret = sdap_extend_map(global_talloc_context,
+                          in_map,
+                          SDAP_OPTS_USER,
+                          NULL,
+                          &out_map, &new_size);
+    fail_unless(ret == EOK, "[%s]", sss_strerror(ret));
+    /* Attributes and sentinel */
+    fail_unless(new_size != SDAP_OPTS_USER + 1);
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+
+    talloc_free(out_map);
+}
+END_TEST
+
+START_TEST(test_extra_opts_neg)
+{
+    errno_t ret;
+    char *extra_attrs[] =  { discard_const(":foo"),
+                             discard_const("bar:"),
+                             NULL };
+    struct sdap_attr_map *in_map;
+    struct sdap_attr_map *out_map;
+    size_t new_size;
+
+    ret = sdap_copy_map(global_talloc_context, rfc2307_user_map,
+                        SDAP_OPTS_USER, &in_map);
+    fail_unless(ret == EOK, "[%s]", sss_strerror(ret));
+
+    ret = sdap_extend_map(global_talloc_context,
+                          in_map,
+                          SDAP_OPTS_USER,
+                          extra_attrs,
+                          &out_map, &new_size);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+    /* The faulty attributes would be just skipped */
+    fail_unless(new_size != SDAP_OPTS_USER + 1);
+    fail_unless(out_map[SDAP_OPTS_USER].name == NULL);
+
+    talloc_free(out_map);
+}
+END_TEST
+
+START_TEST(test_extra_opts_dup)
+{
+    errno_t ret;
+    char *extra_attrs[] =  { discard_const("name:foo"),
+                             NULL };
+    struct sdap_attr_map *in_map;
+    struct sdap_attr_map *out_map;
+    size_t new_size;
+
+    ret = sdap_copy_map(global_talloc_context, rfc2307_user_map,
+                        SDAP_OPTS_USER, &in_map);
+    fail_unless(ret == EOK, "[%s]", strerror(ret));
+
+    ret = sdap_extend_map(global_talloc_context,
+                          in_map,
+                          SDAP_OPTS_USER,
+                          extra_attrs,
+                          &out_map, &new_size);
+    fail_unless(ret == ERR_DUP_EXTRA_ATTR, "[%s]", sss_strerror(ret));
+}
+END_TEST
+
 Suite *ipa_ldap_opt_suite (void)
 {
     Suite *s = suite_create ("ipa_ldap_opt");
@@ -300,6 +410,13 @@ Suite *ipa_ldap_opt_suite (void)
     tcase_add_test (tc_sdap_opts, test_copy_sdap_map);
     suite_add_tcase (s, tc_sdap_opts);
 
+    TCase *tc_extra_opts = tcase_create ("extra_opts");
+    tcase_add_test (tc_extra_opts, test_extra_opts);
+    tcase_add_test (tc_extra_opts, test_no_extra_opts);
+    tcase_add_test (tc_extra_opts, test_extra_opts_neg);
+    tcase_add_test (tc_extra_opts, test_extra_opts_dup);
+    suite_add_tcase (s, tc_extra_opts);
+
     return s;
 }
 
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 
8dd4380b423ef75cd246933ec739e232094e9b37..d27d20b0a511cfd9090707c62064c7d11ebc68cc
 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -54,6 +54,8 @@ struct err_string error_to_str[] = {
     { "Missing configuration file" }, /* ERR_MISSING_CONF */
     { "Malformed search filter" }, /* ERR_INVALID_FILTER, */
     { "No POSIX attributes detected" }, /* ERR_NO_POSIX */
+    { "Extra attribute is a duplicate" }, /* ERR_DUP_EXTRA_ATTR */
+    { "Malformed extra attribute" }, /* ERR_INVALID_EXTRA_ATTR */
 };
 
 
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index 
23048990da1e101397ae6bc9d5957133c1ea65af..f03fc16b1444d7e1370c22044b248585f076f32a
 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -76,6 +76,8 @@ enum sssd_errors {
     ERR_MISSING_CONF,
     ERR_INVALID_FILTER,
     ERR_NO_POSIX,
+    ERR_DUP_EXTRA_ATTR,
+    ERR_INVALID_EXTRA_ATTR,
     ERR_LAST            /* ALWAYS LAST */
 };
 
-- 
1.9.0

>From deee116c3c5dbcbf78dce22ec1c53c78d7f9c83d Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Mon, 12 Aug 2013 15:06:18 +0000
Subject: [PATCH 3/3] Make LDAP extra attributes available to IPA and AD

https://fedorahosted.org/sssd/ticket/2073
---
 src/config/etc/sssd.api.d/sssd-ad.conf  |  1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf |  1 +
 src/providers/ad/ad_common.c            | 11 +++++-----
 src/providers/ipa/ipa_common.c          | 11 +++++-----
 src/providers/ldap/ldap_options.c       | 38 --------------------------------
 src/providers/ldap/sdap.c               | 39 +++++++++++++++++++++++++++++++++
 src/providers/ldap/sdap.h               |  8 +++++++
 7 files changed, 61 insertions(+), 48 deletions(-)

diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf 
b/src/config/etc/sssd.api.d/sssd-ad.conf
index 
aa20ca0bb5b70818525d61a1480a6b56bd8c4e48..ed0189618e137d1a4b48cecd328b797e99201ad2
 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -54,6 +54,7 @@ ldap_id_mapping = bool, None, false
 ldap_user_search_base = str, None, false
 ldap_user_search_scope = str, None, false
 ldap_user_search_filter = str, None, false
+ldap_user_extra_attrs = str, None, false
 ldap_user_object_class = str, None, false
 ldap_user_name = str, None, false
 ldap_user_uid_number = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf 
b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 
9259d99792131d332cc9ccc4cf69739308e4695c..3a3f6a4cf9586b2a81844e38498ba86b504f1f52
 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -61,6 +61,7 @@ ldap_id_mapping = bool, None, false
 ldap_user_search_base = str, None, false
 ldap_user_search_scope = str, None, false
 ldap_user_search_filter = str, None, false
+ldap_user_extra_attrs = str, None, false
 ldap_user_object_class = str, None, false
 ldap_user_name = str, None, false
 ldap_user_uid_number = str, None, false
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 
8528ad3dcdab58ff17c200b8f6f226cd50e8cfed..2607e766dcbb754f20be1aa91e93de8f95a89f2c
 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -201,11 +201,12 @@ ad_create_sdap_options(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = sdap_extend_map(id_opts,
-                          id_opts->user_map,
-                          SDAP_OPTS_USER, NULL,
-                          &id_opts->user_map,
-                          &id_opts->user_map_cnt);
+    ret = sdap_extend_map_with_list(id_opts, id_opts,
+                                    SDAP_USER_EXTRA_ATTRS,
+                                    id_opts->user_map,
+                                    SDAP_OPTS_USER,
+                                    &id_opts->user_map,
+                                    &id_opts->user_map_cnt);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 
19de10d8bb92a4b3d0c8353eae128f3b4709a7af..f594de27a65ab1ff702d0c593a57e89bfd469532
 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -547,11 +547,12 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
         goto done;
     }
 
-    ret = sdap_extend_map(ipa_opts->id,
-                          ipa_opts->id->user_map,
-                          SDAP_OPTS_USER, NULL,
-                          &ipa_opts->id->user_map,
-                          &ipa_opts->id->user_map_cnt);
+    ret = sdap_extend_map_with_list(ipa_opts->id, ipa_opts->id,
+                                    SDAP_USER_EXTRA_ATTRS,
+                                    ipa_opts->id->user_map,
+                                    SDAP_OPTS_USER,
+                                    &ipa_opts->id->user_map,
+                                    &ipa_opts->id->user_map_cnt);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/providers/ldap/ldap_options.c 
b/src/providers/ldap/ldap_options.c
index 
11ed9c31f0fc03113e5f7ba58b5ce8b74fe6545a..eb00aab32a55c6841ebbf32d30f3a48722e8b165
 100644
--- a/src/providers/ldap/ldap_options.c
+++ b/src/providers/ldap/ldap_options.c
@@ -23,44 +23,6 @@
 #include "providers/ldap/sdap_async_private.h"
 #include "util/crypto/sss_crypto.h"
 
-static int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
-                                     struct sdap_options *opts,
-                                     int extra_attr_index,
-                                     struct sdap_attr_map *src_map,
-                                     size_t num_entries,
-                                     struct sdap_attr_map **_map,
-                                     size_t *_new_size)
-{
-    const char *extra_attrs;
-    char **extra_attrs_list;
-    errno_t ret;
-
-    extra_attrs = dp_opt_get_string(opts->basic, extra_attr_index);
-    if (extra_attrs == NULL) {
-        *_map = src_map;
-        *_new_size = num_entries;
-        return EOK;
-    }
-
-    /* split server parm into a list */
-    ret = split_on_separator(mem_ctx, extra_attrs, ',', true, true,
-                             &extra_attrs_list, NULL);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, "Failed to parse server list!\n");
-        return ret;
-    }
-
-    ret = sdap_extend_map(mem_ctx, src_map,
-                          num_entries, extra_attrs_list,
-                          _map, _new_size);
-    talloc_free(extra_attrs_list);
-    if (ret != EOK) {
-        return ret;
-    }
-
-    return EOK;
-}
-
 int ldap_get_options(TALLOC_CTX *memctx,
                      struct sss_domain_info *dom,
                      struct confdb_ctx *cdb,
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 
37a187436a6e17e9e41f981970b9c5ab5e685f46..e8d23c9dc5eac34fc5182305dc4be9180f8be176
 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -187,6 +187,45 @@ int sdap_extend_map(TALLOC_CTX *memctx,
     return EOK;
 }
 
+int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
+                              struct sdap_options *opts,
+                              int extra_attr_index,
+                              struct sdap_attr_map *src_map,
+                              size_t num_entries,
+                              struct sdap_attr_map **_map,
+                              size_t *_new_size)
+{
+    const char *extra_attrs;
+    char **extra_attrs_list;
+    errno_t ret;
+
+    extra_attrs = dp_opt_get_string(opts->basic, extra_attr_index);
+    if (extra_attrs == NULL) {
+        *_map = src_map;
+        *_new_size = num_entries;
+        return EOK;
+    }
+
+    /* split server parm into a list */
+    ret = split_on_separator(mem_ctx, extra_attrs, ',', true, true,
+                             &extra_attrs_list, NULL);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Failed to parse server list!\n"));
+        return ret;
+    }
+
+
+    ret = sdap_extend_map(mem_ctx, src_map,
+                          num_entries, extra_attrs_list,
+                          _map, _new_size);
+    talloc_free(extra_attrs_list);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    return EOK;
+}
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 
38eec1c4dcd10ea839457bbef442e5993a7bf762..fdf92eecf17548eb23b82c4f3a43ac7ba1695132
 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -476,6 +476,14 @@ int sdap_extend_map(TALLOC_CTX *memctx,
                     struct sdap_attr_map **_map,
                     size_t *_new_size);
 
+int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
+                              struct sdap_options *opts,
+                              int extra_attr_index,
+                              struct sdap_attr_map *src_map,
+                              size_t num_entries,
+                              struct sdap_attr_map **_map,
+                              size_t *_new_size);
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
-- 
1.9.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to