[SSSD] [PATCH] NSS: replace with space with specified character in names.

Lukas Slebodnik lslebodn at redhat.com
Fri Jul 25 11:42:54 UTC 2014


On (24/07/14 17:53), Michal Židek wrote:
>On 07/24/2014 11:28 AM, Lukas Slebodnik wrote:
>>ehlo,
>>
>>This patch add possibility to replace whitespace in user and group names with
>>a specified string. With string "-", sssd will return the same result as
>>winbind enabled option "winbind normalize names"
>>
>>Resolves:
>>https://fedorahosted.org/sssd/ticket/1854
>>
>>patch is attached.
>>
>>LS
>>
>
>Hi Lukas,
>
>src/config/SSSDConfig/__init__.py.in
>76     'whitespaces_replacement_string': _('All white spaces will be replaced
>in group name with this string'),
>
>Not just group name, but also user name. IMO something
>like this would be better:
>"All white spaces in group or user names will be replaced with
>this string." Or something similar.
>
>Also please put changes in
>src/config/SSSDConfig/__init__.py.in and man page changes into a
>separate patch. We will than ping a native speaker (Stephen ?)
>to check the wording when the coding part is accepted.
>
>The option name could be at least a little shorter, maybe:
>replace_whitespace_str
>or
>replace_spaces_by
>
>But this is not a strong requirement, if you do not like the above
>names and can't come up with something better, we can stick to the
>current name.
>
>  35 static const char *replace_whitespaces(TALLOC_CTX *mem_ctx,
>  ... <snip>
>  76     while (*ptr != '\0') {
>  77         if (isspace(*ptr)){
>  78             new_name = talloc_asprintf_append(...
>  79         } else{
>               ^^^^^
>                  Missing space after else
>  80             new_name = talloc_asprintf_append(...
>  81         }
>
>The patch seem to work fine. But functions like
>replace_whitespaces and the reverse version can be
>easily unit-tested. It would be great if you could
>add unit tests for these two.
>

Attached patches fix also comments from other mails in this thread.

LS
-------------- next part --------------
>From 42a17c75f8afb7d167fa0fd94217a44dfd344391 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Fri, 25 Jul 2014 11:32:58 +0200
Subject: [PATCH 1/3] test_utils: Use common header file for libsss_util tests.

---
 Makefile.am                     |  4 +++-
 src/tests/cmocka/test_sss_ssh.c |  1 +
 src/tests/cmocka/test_utils.c   |  2 +-
 src/tests/cmocka/test_utils.h   | 29 +++++++++++++++++++++++++++++
 4 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 src/tests/cmocka/test_utils.h

diff --git a/Makefile.am b/Makefile.am
index 783a8922ede16ea3cc3eb6df568773126c5661fb..57f057633d527e75b61f4cf04c1af43c639aa608 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -575,7 +575,9 @@ dist_noinst_HEADERS = \
     src/sss_client/ssh/sss_ssh_client.h \
     src/sss_client/sudo/sss_sudo.h \
     src/lib/idmap/sss_idmap_private.h \
-    src/lib/sifp/sss_sifp_private.h
+    src/lib/sifp/sss_sifp_private.h \
+    src/tests/cmocka/test_utils.h \
+    $(NULL)
 
 
 if HAVE_NSS
diff --git a/src/tests/cmocka/test_sss_ssh.c b/src/tests/cmocka/test_sss_ssh.c
index 03d95dbc84bc2dcbc1a36dc2dc2fad42f7075a58..10e1af7160b2ef559633f82d625f037ba8670976 100644
--- a/src/tests/cmocka/test_sss_ssh.c
+++ b/src/tests/cmocka/test_sss_ssh.c
@@ -23,6 +23,7 @@
 #include "util/util.h"
 #include "util/sss_ssh.h"
 #include "tests/cmocka/common_mock.h"
+#include "test_utils.h"
 
 uint8_t key_data_noLF[] = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfymad64oZkWa6q3xLXmCt/LfCRnd6yZSDp7UK6Irx5/Dv69dEKK2kBGL9Wfn+3ZDa6ov2XZrBmUthh8KOJvTw72+axox3kcJ5HwOYZCMeKbcr10RNScGuHErA1HhjTY6M9L8d0atVH2QIxw7ZHoVVnTHC4U4+541YfJkNUiOUIj65cFFZm9ULp32ZPrK+j2wW+XZkHhrZeFMlg4x4fe5FocO6ik1eqLxBejo7tMy+1m3R2a795AIguf6vNWeE5aNMd4pcmPcZHb3JOq3ItzE/3lepXD/3wqMt36EqNykBVE7aJj+LVkcEgjP9CDDsg9j9NB+AuWYmIYqrHW/Rg/vJ developer at sssd.dev.work";
 
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 2254c0a7cfb00ff9d028b3e50fa989c401418d9a..c1dfb66e1fb972ea45b17d65276d8c23a8a8e231 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -24,6 +24,7 @@
 
 #include "tests/cmocka/common_mock.h"
 #include "util/sss_nss.h"
+#include "test_utils.h"
 
 #define TESTS_PATH "tests_utils"
 #define TEST_CONF_DB "test_utils_conf.ldb"
@@ -52,7 +53,6 @@ struct dom_list_test_ctx {
     struct sss_domain_info *dom_list;
 };
 
-void test_textual_public_key(void **state);
 
 void setup_dom_list(void **state)
 {
diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f6269305d3fbea20841d00f626dc5d350e75cbd
--- /dev/null
+++ b/src/tests/cmocka/test_utils.h
@@ -0,0 +1,29 @@
+/*
+    Authors:
+        Lukas Slebodnik <lslebodn at redhat.com>
+
+    Copyright (C) 2014 Red Hat
+
+    SSSD tests: Tests for utility functions
+
+    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 __TESTS__CMOCKA__TEST_UTILS_H__
+#define __TESTS__CMOCKA__TEST_UTILS_H__
+
+/* from src/tests/cmocka/test_sss_ssh.c */
+void test_textual_public_key(void **state);
+
+#endif /* __TESTS__CMOCKA__TEST_UTILS_H__ */
-- 
1.9.3

-------------- next part --------------
>From 365d1a1fb9e2e657f4ee7f35e69eee30c523653d Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Fri, 25 Jul 2014 10:22:59 +0200
Subject: [PATCH 2/3] UTIL: Add functions for replacing whitespaces.

---
 Makefile.am                          |   9 ++-
 src/tests/cmocka/test_string_utils.c | 150 +++++++++++++++++++++++++++++++++++
 src/tests/cmocka/test_utils.c        |   2 +
 src/tests/cmocka/test_utils.h        |   4 +
 src/util/string_utils.c              | 150 +++++++++++++++++++++++++++++++++++
 src/util/util.h                      |   8 ++
 6 files changed, 320 insertions(+), 3 deletions(-)
 create mode 100644 src/tests/cmocka/test_string_utils.c
 create mode 100644 src/util/string_utils.c

diff --git a/Makefile.am b/Makefile.am
index 57f057633d527e75b61f4cf04c1af43c639aa608..340a85cf908b0bd6563b4043af61129c1bd0c41b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -673,7 +673,9 @@ libsss_util_la_SOURCES = \
     src/util/sss_ini.c \
     src/util/io.c \
     src/util/util_sss_idmap.c \
-    src/util/well_known_sids.c
+    src/util/well_known_sids.c \
+    src/util/string_utils.c \
+    $(NULL)
 libsss_util_la_CFLAGS = \
     $(AM_CFLAGS) \
     $(SYSTEMD_LOGIN_CFLAGS)
@@ -1784,8 +1786,9 @@ test_ipa_idmap_LDADD = \
 
 test_utils_SOURCES = \
     src/tests/cmocka/test_utils.c \
-    src/tests/cmocka/test_sss_ssh.c
-
+    src/tests/cmocka/test_sss_ssh.c \
+    src/tests/cmocka/test_string_utils.c \
+    $(NULL)
 test_utils_CFLAGS = \
     $(AM_CFLAGS)
 test_utils_LDADD = \
diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..d10c3be47b83b97817e01af1e16cff987c49b2c5
--- /dev/null
+++ b/src/tests/cmocka/test_string_utils.c
@@ -0,0 +1,150 @@
+/*
+    Authors:
+        Lukas Slebodnik  <slebodnikl at redhat.com>
+
+    Copyright (C) 2014 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 "tests/cmocka/common_mock.h"
+
+void test_replace_whitespaces(void **state)
+{
+    TALLOC_CTX *mem_ctx;
+    const char *input_str = "Lorem ipsum dolor sit amet";
+    const char *res;
+    size_t i;
+
+    struct {
+        const char *input;
+        const char *output;
+        const char *replace_string;
+    } data_set[] = {
+        { "", "", "-" },
+        { " ", "-", "-" },
+        { "\t", "-", "-" },
+        { "\n", "-", "-" },
+        { " \t\n ", "----", "-" },
+        { "abcd", "abcd", "-" },
+        { "a b c d", "a-b-c-d", "-" },
+        { " a b c d ", "-a-b-c-d-", "-" },
+        { " ", "^", "^" },
+        { "\t", "^", "^" },
+        { "\n", "^", "^" },
+        { " \t\n ", "^^^^", "^" },
+        { "abcd", "abcd", "^" },
+        { "a b c d", "a^b^c^d", "^" },
+        { " a b c d ", "^a^b^c^d^", "^" },
+        { " ", "^", "^" },
+        { "\t", ";-)", ";-)" },
+        { "\n", ";-)", ";-)" },
+        { " \t\n ", ";-);-);-);-)", ";-)" },
+        { "abcd", "abcd", ";-)" },
+        { "a b c d", "a;-)b;-)c;-)d", ";-)" },
+        { " a b c d ", ";-)a;-)b;-)c;-)d;-)", ";-)" },
+        { " ", " ", " " },
+        { "    ", "    ", " " },
+        { "abcd", "abcd", " " },
+        { "a b c d", "a b c d", " " },
+        { " a b c d ", " a b c d ", " " },
+        { " ", " \t", " \t" },
+        { "    ", " \t \t \t \t", " \t" },
+        { "abcd", "abcd", " \t" },
+        { "a b c d", "a \tb \tc \td", " \t" },
+        { " a b c d ", " \ta \tb \tc \td \t", " \t" },
+        { NULL, NULL, NULL },
+    };
+
+    mem_ctx = talloc_new(NULL);
+    assert_non_null(mem_ctx);
+    check_leaks_push(mem_ctx);
+
+    res = sss_replace_whitespaces(mem_ctx, input_str, NULL);
+    assert_true(res == input_str);
+
+    res = sss_replace_whitespaces(mem_ctx, input_str, "");
+    assert_true(res == input_str);
+
+    for (i=0; data_set[i].input != NULL; ++i) {
+        res = sss_replace_whitespaces(mem_ctx, data_set[i].input,
+                                      data_set[i].replace_string);
+        assert_non_null(res);
+        assert_string_equal(res, data_set[i].output);
+        talloc_zfree(res);
+    }
+
+    assert_true(check_leaks_pop(mem_ctx) == true);
+    talloc_free(mem_ctx);
+}
+
+void test_reverse_replace_whitespaces(void **state)
+{
+    TALLOC_CTX *mem_ctx;
+    char *input_str = discard_const_p(char, "Lorem ipsum dolor sit amet");
+    char *res;
+    size_t i;
+
+    struct {
+        const char *input;
+        const char *output;
+        const char *replace_string;
+    } data_set[] = {
+        { "", "", "-" },
+        { "-", " ", "-" },
+        { "----", "    ", "-" },
+        { "abcd", "abcd", "-" },
+        { "a-b-c-d", "a b c d", "-" },
+        { "-a-b-c-d-", " a b c d ", "-" },
+        { "^", " ", "^" },
+        { "^^^^", "    ", "^" },
+        { "abcd", "abcd", "^" },
+        { "a^b^c^d", "a b c d", "^" },
+        { "^a^b^c^d^", " a b c d ", "^" },
+        { ";-)", " ", ";-)" },
+        { ";-);-);-);-)", "    ", ";-)" },
+        { "abcd", "abcd", ";-)" },
+        { "a;-)b;-)c;-)d", "a b c d", ";-)" },
+        { ";-)a;-)b;-)c;-)d;-)", " a b c d ", ";-)" },
+        { " ", " ", " " },
+        { "    ", "    ", " " },
+        { "abcd", "abcd", " " },
+        { "a b c d", "a b c d", " " },
+        { " a b c d ", " a b c d ", " " },
+        { NULL, NULL, NULL },
+    };
+
+    mem_ctx = talloc_new(NULL);
+    assert_non_null(mem_ctx);
+    check_leaks_push(mem_ctx);
+
+    res = sss_reverse_replace_whitespaces(mem_ctx, input_str, NULL);
+    assert_true(res == input_str);
+
+    res = sss_reverse_replace_whitespaces(mem_ctx, input_str, "");
+    assert_true(res == input_str);
+
+    for (i=0; data_set[i].input != NULL; ++i) {
+        input_str = discard_const_p(char, data_set[i].input);
+        res = sss_reverse_replace_whitespaces(mem_ctx, input_str,
+                                      data_set[i].replace_string);
+        assert_non_null(res);
+        assert_string_equal(res, data_set[i].output);
+        talloc_zfree(res);
+    }
+
+    assert_true(check_leaks_pop(mem_ctx) == true);
+    talloc_free(mem_ctx);
+}
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index c1dfb66e1fb972ea45b17d65276d8c23a8a8e231..9d6cbf35f7c2e33c57b3a539b409848c22cf263e 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -917,6 +917,8 @@ int main(int argc, const char *argv[])
         unit_test_setup_teardown(test_expand_homedir_template,
                                  setup_homedir_ctx, teardown_homedir_ctx),
         unit_test(test_textual_public_key),
+        unit_test(test_replace_whitespaces),
+        unit_test(test_reverse_replace_whitespaces),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h
index 8f6269305d3fbea20841d00f626dc5d350e75cbd..f85ac2f2b3c50a60099970752b06adbad38b9fd1 100644
--- a/src/tests/cmocka/test_utils.h
+++ b/src/tests/cmocka/test_utils.h
@@ -26,4 +26,8 @@
 /* from src/tests/cmocka/test_sss_ssh.c */
 void test_textual_public_key(void **state);
 
+/* from src/tests/cmocka/test_string_utils.c */
+void test_replace_whitespaces(void **state);
+void test_reverse_replace_whitespaces(void **state);
+
 #endif /* __TESTS__CMOCKA__TEST_UTILS_H__ */
diff --git a/src/util/string_utils.c b/src/util/string_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d878923f92060e7db57214add3280ecdea27601
--- /dev/null
+++ b/src/util/string_utils.c
@@ -0,0 +1,150 @@
+/*
+    SSSD
+
+    Authors:
+        Lukas Slebodnik <slebodnikl at redhat.com>
+
+    Copyright (C) 2014 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"
+
+const char * sss_replace_whitespaces(TALLOC_CTX *mem_ctx,
+                                     const char *orig_name,
+                                     const char *replace_string)
+{
+    char *new_name;
+    const char *ptr;
+    size_t replace_string_len;
+    TALLOC_CTX *tmp_ctx;
+
+    if (replace_string == NULL || replace_string[0] == '\0') {
+        return orig_name;
+    }
+
+    replace_string_len = strlen(replace_string);
+    /* faster implementations without multiple allocations */
+    if (replace_string_len == 1) {
+        char *p;
+        new_name = talloc_strdup(mem_ctx, orig_name);
+        if (new_name == NULL) {
+            return NULL;
+        }
+
+        for (p = new_name; *p != '\0'; ++p) {
+            if (isspace(*p)) {
+                *p = replace_string[0];
+            }
+        }
+
+        return new_name;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return NULL;
+    }
+
+    new_name = talloc_strdup(tmp_ctx, "");
+    if (new_name == NULL) {
+        goto done;
+    }
+
+    ptr = orig_name;
+    while (*ptr != '\0') {
+        if (isspace(*ptr)) {
+            new_name = talloc_asprintf_append(new_name, "%s", replace_string);
+        } else {
+            new_name = talloc_asprintf_append(new_name, "%c", *ptr);
+        }
+        if (new_name == NULL) {
+            goto done;;
+        }
+
+        ++ptr;
+    }
+
+    new_name = talloc_steal(mem_ctx, new_name);
+done:
+    talloc_free(tmp_ctx);
+    return new_name;
+}
+
+char * sss_reverse_replace_whitespaces(TALLOC_CTX *mem_ctx,
+                                       char *orig_name,
+                                       const char *replace_string)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *substr;
+    char *new_name;
+    const char *ptr = orig_name;
+    size_t replace_string_len;
+
+    if (replace_string == NULL || replace_string[0] == '\0') {
+        return orig_name;
+    }
+
+    replace_string_len = strlen(replace_string);
+    /* faster implementations without multiple allocations */
+    if (replace_string_len == 1) {
+        char *p;
+        new_name = talloc_strdup(mem_ctx, orig_name);
+        if (new_name == NULL) {
+            return NULL;
+        }
+
+        for (p = new_name; *p != '\0'; ++p) {
+            if (*p == replace_string[0] ) {
+                *p = ' ';
+            }
+        }
+
+        return new_name;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return NULL;
+    }
+
+    new_name = talloc_strdup(tmp_ctx, "");
+    if (new_name == NULL) {
+        goto done;
+    }
+
+    do {
+        substr = strstr(ptr, replace_string);
+        if (substr != NULL) {
+            new_name = talloc_asprintf_append(new_name, "%.*s ",
+                                              (int)(substr - ptr), ptr);
+            if (new_name == NULL) {
+                goto done;
+            }
+            ptr += substr - ptr;
+            ptr += replace_string_len;
+        } else {
+            new_name = talloc_asprintf_append(new_name, "%s", ptr);
+            if (new_name == NULL) {
+                goto done;
+            }
+        }
+    } while (substr != NULL);
+
+    new_name = talloc_steal(mem_ctx, new_name);
+done:
+    talloc_free(tmp_ctx);
+    return new_name;
+}
diff --git a/src/util/util.h b/src/util/util.h
index cc1a38283e34e2bc25189084a9f6045357c9c935..35a8814e587d3050a265d9b82d88095fb82d4680 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -567,4 +567,12 @@ errno_t well_known_sid_to_name(const char *sid, const char **dom,
 errno_t name_to_well_known_sid(const char *dom, const char *name,
                                const char **sid);
 
+/* from string_utils.c */
+const char * sss_replace_whitespaces(TALLOC_CTX *mem_ctx,
+                                     const char *orig_name,
+                                     const char *replace_string);
+char * sss_reverse_replace_whitespaces(TALLOC_CTX *mem_ctx,
+                                       char *orig_name,
+                                       const char *replace_string);
+
 #endif /* __SSSD_UTIL_H__ */
-- 
1.9.3

-------------- next part --------------
>From c385e35b5b81b7f74dc3a3f6923171f39588c31e Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Wed, 23 Jul 2014 17:23:00 +0200
Subject: [PATCH 3/3] NSS: Replace spaces with specified string in names.

This patch add possibility to replace whitespace in user and group names with
a specified string. With string "-", sssd will return the same result as
winbind enabled option "winbind normalize names"

Resolves:
https://fedorahosted.org/sssd/ticket/1854
---
 src/confdb/confdb.h                  |  1 +
 src/config/SSSDConfig/__init__.py.in |  1 +
 src/config/etc/sssd.api.conf         |  1 +
 src/man/sssd.conf.5.xml              | 18 +++++++++++
 src/responder/nss/nsssrv.c           |  5 +++
 src/responder/nss/nsssrv.h           |  1 +
 src/responder/nss/nsssrv_cmd.c       | 62 +++++++++++++++++++++++++++++++++++-
 7 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index ba33ea5d7123c6e799f13529b60c5938ad20e411..4ac69ebef0c03ef8f1e2b21e6aa7ec3e60d95ca4 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -99,6 +99,7 @@
 #define CONFDB_MEMCACHE_TIMEOUT "memcache_timeout"
 #define CONFDB_NSS_HOMEDIR_SUBSTRING "homedir_substring"
 #define CONFDB_DEFAULT_HOMEDIR_SUBSTRING "/home"
+#define CONFDB_NSS_OVERRIDE_DEFAULT_WHITESPACE "override_default_whitespace"
 
 /* PAM */
 #define CONFDB_PAM_CONF_ENTRY "config/pam"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 439378ff86d07311f67d51ed775e2d973cd93869..8e9ddaae69ba5bf2c6c5d9bb9f78b41bdaa58644 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -73,6 +73,7 @@ option_strings = {
     'shell_fallback' : _('If a shell stored in central directory is allowed but not available, use this fallback'),
     'default_shell': _('Shell to use if the provider does not list one'),
     'memcache_timeout': _('How long will be in-memory cache records valid'),
+    'override_default_whitespace': _('All white spaces in group or user names will be replaced with this string'),
 
     # [pam]
     'offline_credentials_expiration' : _('How long to allow cached logins between online logins (days)'),
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 5e5a9284e9ad80d822fe1db4269353aeb7925682..1db9e220700e16b0feaa106838565eefbb2a65c6 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -44,6 +44,7 @@ shell_fallback = str, None, false
 default_shell = str, None, false
 get_domains_timeout = int, None, false
 memcache_timeout = int, None, false
+override_default_whitespace = str, None, false
 
 [pam]
 # Authentication service
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 27d22f44ef4449ef9cad026757ff54dd5083672b..d567420adcde2c39b7d52c9359f3fd669ce8b9d4 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -645,6 +645,24 @@ fallback_homedir = /home/%u
                         </para>
                     </listitem>
                 </varlistentry>
+                <varlistentry>
+                    <term>override_default_whitespace (string)</term>
+                    <listitem>
+                        <para>
+                            This parameter controls whether sssd will replace
+                            whitespace in user and group names with a given
+                            string e.g. (_). For example, whether the name
+                            &quot;john doe&quot; should be replaced with
+                            the string &quot;john_doe&quot;. Frequently Unix
+                            shell scripts will have difficulty with usernames
+                            contains whitespace due to the default field
+                            separator in the shell.
+                        </para>
+                        <para>
+                            Default: not set (whitespaces will not be replaced)
+                        </para>
+                    </listitem>
+                </varlistentry>
             </variablelist>
         </refsect2>
         <refsect2 id='PAM'>
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 84a6b7fedd096a7d4159b7ac6670820c1d8fd941..cf4525a7101834f26215ac269743f614ee8cc17f 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -298,6 +298,11 @@ static int nss_get_config(struct nss_ctx *nctx,
                             &nctx->homedir_substr);
     if (ret != EOK) goto done;
 
+    ret = confdb_get_string(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
+                            CONFDB_NSS_OVERRIDE_DEFAULT_WHITESPACE, NULL,
+                            &nctx->override_default_wsp_str);
+    if (ret != EOK) goto done;
+
     ret = 0;
 done:
     return ret;
diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
index a5b946b7e4a38d7d8b35ec5df1b6644d01896470..07443027eaad4c3103aa6aaed197888e9fb22de2 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -69,6 +69,7 @@ struct nss_ctx {
     char **etc_shells;
     char *shell_fallback;
     char *default_shell;
+    char *override_default_wsp_str;
 
     struct sss_mc_ctx *pwd_mc_ctx;
     struct sss_mc_ctx *grp_mc_ctx;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index a168a3e5d6116a1f6ca2c358707650c0e6c9e514..75349085d80fd92198d811cf5c49bbe415964a43 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -371,6 +371,15 @@ static int fill_pwent(struct sss_packet *packet,
                   "sss_get_cased_name failed, skipping\n");
             continue;
         }
+
+        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
+                                         nctx->override_default_wsp_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_replace_whitespaces failed, skipping\n");
+            continue;
+        }
+
         to_sized_string(&name, tmpstr);
 
         tmpstr = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
@@ -743,6 +752,14 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(cmdctx, cmdctx->name, dom->case_sensitive);
         if (!name) return ENOMEM;
 
+        name = sss_reverse_replace_whitespaces(dctx, name,
+                                               nctx->override_default_wsp_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_whitespaces failed\n");
+            return ENOMEM;
+        }
+
         /* verify this user has not yet been negatively cached,
         * or has been permanently filtered */
         ret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
@@ -2316,7 +2333,7 @@ static int fill_members(struct sss_packet *packet,
     int memnum = *_memnum;
     size_t rzero= *_rzero;
     size_t rsize = *_rsize;
-    char *tmpstr;
+    const char *tmpstr;
     struct sized_string name;
     TALLOC_CTX *tmp_ctx = NULL;
 
@@ -2344,6 +2361,15 @@ static int fill_members(struct sss_packet *packet,
             continue;
         }
 
+        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
+                                         nctx->override_default_wsp_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_replace_whitespaces failed\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
         if (nctx->filter_users_in_groups) {
             ret = sss_ncache_check_user(nctx->ncache,
                                         nctx->neg_timeout,
@@ -2498,6 +2524,15 @@ static int fill_grent(struct sss_packet *packet,
                   "sss_get_cased_name failed, skipping\n");
             continue;
         }
+
+        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
+                                         nctx->override_default_wsp_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_replace_whitespaces failed, skipping\n");
+            continue;
+        }
+
         to_sized_string(&name, tmpstr);
 
         /* fill in gid and name and set pointer for number of members */
@@ -2692,6 +2727,14 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
         if (!name) return ENOMEM;
 
+        name = sss_reverse_replace_whitespaces(dctx, name,
+                                               nctx->override_default_wsp_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_whitespaces failed\n");
+            return ENOMEM;
+        }
+
         /* verify this group has not yet been negatively cached,
         * or has been permanently filtered */
         ret = sss_ncache_check_group(nctx->ncache, nctx->neg_timeout,
@@ -3715,6 +3758,14 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
         if (!name) return ENOMEM;
 
+        name = sss_reverse_replace_whitespaces(dctx, name,
+                                               nctx->override_default_wsp_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_whitespaces failed\n");
+            return ENOMEM;
+        }
+
         /* verify this user has not yet been negatively cached,
         * or has been permanently filtered */
         ret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
@@ -3874,6 +3925,15 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
                 goto done;
             }
 
+            name = sss_reverse_replace_whitespaces(dctx, name,
+                                               nctx->override_default_wsp_str);
+            if (name == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "sss_reverse_replace_whitespaces failed\n");
+                ret = ENOMEM;
+                goto done;
+            }
+
             /* For subdomains a fully qualified name is needed for
              * sysdb_search_user_by_name and sysdb_search_group_by_name. */
             if (IS_SUBDOMAIN(dom)) {
-- 
1.9.3



More information about the sssd-devel mailing list