[SSSD] [PATCH] Make the replace-space functionality usable for other responders

Jakub Hrozek jhrozek at redhat.com
Mon Aug 11 07:54:14 UTC 2014


On Mon, Aug 11, 2014 at 09:12:24AM +0200, Lukas Slebodnik wrote:
> It is your decision. You can:
>     a) fix problem in function ifp_user_get_attr_search
>     b) remove changes in IFP responder.
> 
> LS

Thanks for the quick review. I would prefer to keep the ifp changes in
-- I don't realistically expect anyone being bitten by spaces when using
InfoPipe, but it's more about being consistent. When we say we want to
replace the spaces, we should replace them everywhere..
-------------- next part --------------
>From a6ed84f6cf0db173819439cd56a3d7806e58ce02 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 5 Aug 2014 10:12:34 +0200
Subject: [PATCH 1/6] Only replace space with the specified substitution

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

- make sss_replace_whitespaces only replace space (' ') not any
  whitespace
- make sss_replace_whitespaces only replace a single char, not the whole
  string
- rename CONFDB_NSS_OVERRIDE_DEFAULT_WHITESPACE to
  CONFDB_NSS_OVERRIDE_DEFAULT_SPACE
- rename the override_default_whitespace option to override_space
- rename sss_replace_whitespaces() to sss_replace_space()
- rename sss_reverse_replace_whitespaces() to sss_reverse_replace_space()
- rename nctx->override_default_wsp_str to nctx->override_space
- make the return value of sss_replace_space non-const to avoid freeing
  the result without compilation warnings
---
 src/confdb/confdb.h                  |   2 +-
 src/config/SSSDConfig/__init__.py.in |   2 +-
 src/config/etc/sssd.api.conf         |   2 +-
 src/man/sssd.conf.5.xml              |  10 +--
 src/responder/nss/nsssrv.c           |   4 +-
 src/responder/nss/nsssrv.h           |   2 +-
 src/responder/nss/nsssrv_cmd.c       |  37 ++++------
 src/tests/cmocka/test_nss_srv.c      |   1 +
 src/tests/cmocka/test_string_utils.c | 119 +++++++++++++-----------------
 src/util/string_utils.c              | 137 +++++++----------------------------
 src/util/util.h                      |  12 +--
 11 files changed, 110 insertions(+), 218 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index b7395c1f31bfeb412d99b722e3708214c34d6c49..d5f7511d0cfe916242b5bfae506271e028a87edb 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -99,7 +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"
+#define CONFDB_NSS_OVERRIDE_SPACE "override_space"
 
 /* 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 c3482b3a4df6d0fd39b2fa93c19ee5316dde0d94..38111a86f02c12e2a6469f2ab671098ebfd84dcb 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -73,7 +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'),
+    'override_space': _('All spaces in group or user names will be replaced with this character'),
 
     # [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 1db9e220700e16b0feaa106838565eefbb2a65c6..a3398c8d5567df7d99795acc29e55563459e5733 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -44,7 +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
+override_space = str, None, false
 
 [pam]
 # Authentication service
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 2eb0b62221b966d7f16c56000fc1ebd2ec2b4f84..d2472ec78fc7e4f639fe9a002f8e81ad4fb40a58 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -646,19 +646,19 @@ fallback_homedir = /home/%u
                     </listitem>
                 </varlistentry>
                 <varlistentry>
-                    <term>override_default_whitespace (string)</term>
+                    <term>override_space (string)</term>
                     <listitem>
                         <para>
-                            This parameter will replace white spaces (space bar)
-                            with the given string for user and group names.
+                            This parameter will replace spaces (space bar)
+                            with the given character for user and group names.
                             e.g. (_). User name &quot;john doe&quot; will
                             be &quot;john_doe&quot; This feature was added to
                             help compatibility with shell scripts that have
-                            difficulty handling white spaces, due to the
+                            difficulty handling spaces, due to the
                             default field separator in the shell.
                         </para>
                         <para>
-                            Default: not set (whitespaces will not be replaced)
+                            Default: not set (spaces will not be replaced)
                         </para>
                     </listitem>
                 </varlistentry>
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index cf4525a7101834f26215ac269743f614ee8cc17f..9705878fa80d33d3bddfe7be7fcc97151b44a0f0 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -299,8 +299,8 @@ static int nss_get_config(struct nss_ctx *nctx,
     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);
+                            CONFDB_NSS_OVERRIDE_SPACE, NULL,
+                            &nctx->override_space);
     if (ret != EOK) goto done;
 
     ret = 0;
diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
index 07443027eaad4c3103aa6aaed197888e9fb22de2..f5238fb822ecc376d8dca06c00fb989276949688 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -69,7 +69,7 @@ struct nss_ctx {
     char **etc_shells;
     char *shell_fallback;
     char *default_shell;
-    char *override_default_wsp_str;
+    char *override_space;
 
     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 3e1b470e5ef9ed8db3bd96092cdad2461b3513a0..10e84e52c2f2fbcd9ab75349a625eb01ba5fa871 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -372,11 +372,10 @@ static int fill_pwent(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
-                                         nctx->override_default_wsp_str);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_replace_whitespaces failed, skipping\n");
+                  "sss_replace_space failed, skipping\n");
             continue;
         }
 
@@ -752,11 +751,11 @@ 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);
+        name = sss_reverse_replace_space(dctx, name,
+                                         nctx->override_space[0]);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_reverse_replace_whitespaces failed\n");
+                  "sss_reverse_replace_space failed\n");
             return ENOMEM;
         }
 
@@ -2361,11 +2360,10 @@ static int fill_members(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
-                                         nctx->override_default_wsp_str);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_replace_whitespaces failed\n");
+                  "sss_replace_space failed\n");
             ret = ENOMEM;
             goto done;
         }
@@ -2525,11 +2523,10 @@ static int fill_grent(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_whitespaces(tmp_ctx, tmpstr,
-                                         nctx->override_default_wsp_str);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_replace_whitespaces failed, skipping\n");
+                  "sss_replace_space failed, skipping\n");
             continue;
         }
 
@@ -2727,11 +2724,10 @@ 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);
+        name = sss_reverse_replace_space(dctx, name, nctx->override_space[0]);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_reverse_replace_whitespaces failed\n");
+                  "sss_reverse_replace_space failed\n");
             return ENOMEM;
         }
 
@@ -3758,11 +3754,10 @@ 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);
+        name = sss_reverse_replace_space(dctx, name, nctx->override_space[0]);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_reverse_replace_whitespaces failed\n");
+                  "sss_reverse_replace_space failed\n");
             return ENOMEM;
         }
 
@@ -3925,11 +3920,11 @@ 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);
+            name = sss_reverse_replace_space(dctx, name,
+                                             nctx->override_space[0]);
             if (name == NULL) {
                 DEBUG(SSSDBG_CRIT_FAILURE,
-                      "sss_reverse_replace_whitespaces failed\n");
+                      "sss_reverse_replace_space failed\n");
                 ret = ENOMEM;
                 goto done;
             }
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 808a7a1854cb80b6ffb3f84f26144083e8599bb5..dba03ddb6bddcf358e54219027b0b74de43335f5 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -74,6 +74,7 @@ mock_nctx(TALLOC_CTX *mem_ctx)
     }
     nctx->neg_timeout = 10;
     nctx->pwfield = discard_const("*");
+    nctx->override_space = discard_const("\0");
 
     err = sss_idmap_init(sss_idmap_talloc, nctx, sss_idmap_talloc_free,
                          &nctx->idmap_ctx);
diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c
index d10c3be47b83b97817e01af1e16cff987c49b2c5..93d7d716fca5bb9c72a8a5be4627338e7816a916 100644
--- a/src/tests/cmocka/test_string_utils.c
+++ b/src/tests/cmocka/test_string_utils.c
@@ -31,56 +31,40 @@ void test_replace_whitespaces(void **state)
     struct {
         const char *input;
         const char *output;
-        const char *replace_string;
+        const char replace_char;
     } 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 },
+        { "", "", '-' },
+        { " ", "-", '-' },
+        { "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", ' ' },
+        { NULL, NULL, '\0' },
     };
 
     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_space(mem_ctx, input_str, '\0');
+    assert_string_equal(res, input_str);
+    talloc_zfree(res);
 
-    res = sss_replace_whitespaces(mem_ctx, input_str, "");
-    assert_true(res == input_str);
+    res = sss_replace_space(mem_ctx, input_str, '\0');
+    assert_string_equal(res, input_str);
+    talloc_zfree(res);
 
     for (i=0; data_set[i].input != NULL; ++i) {
-        res = sss_replace_whitespaces(mem_ctx, data_set[i].input,
-                                      data_set[i].replace_string);
+        res = sss_replace_space(mem_ctx, data_set[i].input,
+                                data_set[i].replace_char);
         assert_non_null(res);
         assert_string_equal(res, data_set[i].output);
         talloc_zfree(res);
@@ -100,46 +84,43 @@ void test_reverse_replace_whitespaces(void **state)
     struct {
         const char *input;
         const char *output;
-        const char *replace_string;
+        const char replace_char;
     } 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 },
+        { "", "", '-' },
+        { "-", " ", '-' },
+        { "----", "    ", '-' },
+        { "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, '\0' },
     };
 
     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_space(mem_ctx, input_str, '\0');
+    assert_string_equal(res, input_str);
+    talloc_free(res);
 
-    res = sss_reverse_replace_whitespaces(mem_ctx, input_str, "");
-    assert_true(res == input_str);
+    res = sss_reverse_replace_space(mem_ctx, input_str, '\0');
+    assert_string_equal(res, input_str);
+    talloc_free(res);
 
     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);
+        res = sss_reverse_replace_space(mem_ctx, input_str,
+                                        data_set[i].replace_char);
         assert_non_null(res);
         assert_string_equal(res, data_set[i].output);
         talloc_zfree(res);
diff --git a/src/util/string_utils.c b/src/util/string_utils.c
index 8d878923f92060e7db57214add3280ecdea27601..ec4cc687e6652ee58e963869f7da3bd5f4cec2da 100644
--- a/src/util/string_utils.c
+++ b/src/util/string_utils.c
@@ -22,129 +22,44 @@
 
 #include "util/util.h"
 
-const char * sss_replace_whitespaces(TALLOC_CTX *mem_ctx,
-                                     const char *orig_name,
-                                     const char *replace_string)
+static char *replace_char(TALLOC_CTX *mem_ctx,
+                          const char *in,
+                          const char match,
+                          const char sub)
 {
-    char *new_name;
-    const char *ptr;
-    size_t replace_string_len;
-    TALLOC_CTX *tmp_ctx;
+    char *p;
+    char *out;
 
-    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) {
+    out = talloc_strdup(mem_ctx, in);
+    if (out == 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;;
+    for (p = out; *p != '\0'; ++p) {
+        if (*p == match) {
+            *p = sub;
         }
-
-        ++ptr;
     }
 
-    new_name = talloc_steal(mem_ctx, new_name);
-done:
-    talloc_free(tmp_ctx);
-    return new_name;
+    return out;
 }
 
-char * sss_reverse_replace_whitespaces(TALLOC_CTX *mem_ctx,
-                                       char *orig_name,
-                                       const char *replace_string)
+char * sss_replace_space(TALLOC_CTX *mem_ctx,
+                         const char *orig_name,
+                         const char subst)
 {
-    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;
+    if (subst == '\0') {
+        return talloc_strdup(mem_ctx, orig_name);
     }
+    return replace_char(mem_ctx, orig_name, ' ', subst);
+}
 
-    new_name = talloc_strdup(tmp_ctx, "");
-    if (new_name == NULL) {
-        goto done;
+char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx,
+                                 char *orig_name,
+                                 const char subst)
+{
+    if (subst == '\0') {
+        return talloc_strdup(mem_ctx, orig_name);
     }
-
-    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;
+    return replace_char(mem_ctx, orig_name, subst, ' ');
 }
diff --git a/src/util/util.h b/src/util/util.h
index b638df99aee00d8b133555ace1ee5bd290dfecf4..ca740d0163939f237dff0f80c5c8ab2ed183d07f 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -566,11 +566,11 @@ 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);
+char * sss_replace_space(TALLOC_CTX *mem_ctx,
+                         const char *orig_name,
+                         const char replace_char);
+char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx,
+                                 char *orig_name,
+                                 const char replace_char);
 
 #endif /* __SSSD_UTIL_H__ */
-- 
1.9.3

-------------- next part --------------
>From e3fdd1f70c761c3c785a32fa791f5bad61ebba2c Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sun, 10 Aug 2014 18:59:40 +0200
Subject: [PATCH 2/6] Make the space override responder-agnostic

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

In order to make the override_space option usable by other responders,
we need to move the override_space option to the generic responder
structure.
---
 src/confdb/confdb.h                     |  2 +-
 src/man/sssd.conf.5.xml                 | 34 ++++++++++++++++-----------------
 src/responder/common/responder.h        |  1 +
 src/responder/common/responder_common.c | 21 ++++++++++++++++++++
 src/responder/nss/nsssrv.c              |  5 -----
 src/responder/nss/nsssrv.h              |  1 -
 src/responder/nss/nsssrv_cmd.c          | 19 +++++++++++-------
 src/tests/cmocka/test_nss_srv.c         |  2 +-
 8 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index d5f7511d0cfe916242b5bfae506271e028a87edb..9160debd6f4b5a35ac94ec29dc863ed80a0e337e 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -68,6 +68,7 @@
 #define CONFDB_MONITOR_TRY_INOTIFY "try_inotify"
 #define CONFDB_MONITOR_KRB5_RCACHEDIR "krb5_rcache_dir"
 #define CONFDB_MONITOR_DEFAULT_DOMAIN "default_domain_suffix"
+#define CONFDB_MONITOR_OVERRIDE_SPACE "override_default_space"
 
 /* Both monitor and domains */
 #define CONFDB_NAME_REGEX   "re_expression"
@@ -99,7 +100,6 @@
 #define CONFDB_MEMCACHE_TIMEOUT "memcache_timeout"
 #define CONFDB_NSS_HOMEDIR_SUBSTRING "homedir_substring"
 #define CONFDB_DEFAULT_HOMEDIR_SUBSTRING "/home"
-#define CONFDB_NSS_OVERRIDE_SPACE "override_space"
 
 /* PAM */
 #define CONFDB_PAM_CONF_ENTRY "config/pam"
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index d2472ec78fc7e4f639fe9a002f8e81ad4fb40a58..28dc2bb70a1121027191456962f332ba9155d822 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -320,6 +320,23 @@
                             </para>
                         </listitem>
                     </varlistentry>
+                    <varlistentry>
+                        <term>override_space (string)</term>
+                        <listitem>
+                            <para>
+                                This parameter will replace spaces (space bar)
+                                with the given character for user and group names.
+                                e.g. (_). User name &quot;john doe&quot; will
+                                be &quot;john_doe&quot; This feature was added to
+                                help compatibility with shell scripts that have
+                                difficulty handling spaces, due to the
+                                default field separator in the shell.
+                            </para>
+                            <para>
+                                Default: not set (spaces will not be replaced)
+                            </para>
+                        </listitem>
+                    </varlistentry>
                 </variablelist>
             </para>
         </refsect2>
@@ -645,23 +662,6 @@ fallback_homedir = /home/%u
                         </para>
                     </listitem>
                 </varlistentry>
-                <varlistentry>
-                    <term>override_space (string)</term>
-                    <listitem>
-                        <para>
-                            This parameter will replace spaces (space bar)
-                            with the given character for user and group names.
-                            e.g. (_). User name &quot;john doe&quot; will
-                            be &quot;john_doe&quot; This feature was added to
-                            help compatibility with shell scripts that have
-                            difficulty handling spaces, due to the
-                            default field separator in the shell.
-                        </para>
-                        <para>
-                            Default: not set (spaces will not be replaced)
-                        </para>
-                    </listitem>
-                </varlistentry>
             </variablelist>
         </refsect2>
         <refsect2 id='PAM'>
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 167f45cb156a189deb996d28f8165529535607de..3674d13f2303d0ce248f765a638aaa83d0c16cf3 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -102,6 +102,7 @@ struct resp_ctx {
     uid_t *allowed_uids;
 
     char *default_domain;
+    char override_space;
 
     void *pvt_ctx;
 
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 2f9db70ce22ef224e744cad80d89639340ec1a79..a0c476e1d25f2292721cb2570e3d595909fa9511 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -781,6 +781,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
     struct resp_ctx *rctx;
     struct sss_domain_info *dom;
     int ret;
+    char *tmp = NULL;
 
     rctx = talloc_zero(mem_ctx, struct resp_ctx);
     if (!rctx) {
@@ -844,6 +845,26 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
         goto fail;
     }
 
+    ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
+                            CONFDB_MONITOR_OVERRIDE_SPACE, NULL,
+                            &tmp);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "Cannnot get the space substitution character [%d]: %s\n",
+               ret, strerror(ret));
+        goto fail;
+    }
+
+    if (tmp != NULL) {
+        if (strlen(tmp) > 1) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Option %s is longer than 1 character "
+                  "only the first character %c will be used\n",
+                  CONFDB_MONITOR_OVERRIDE_SPACE, tmp[0]);
+        }
+
+        rctx->override_space = tmp[0];
+    }
+
     ret = sss_monitor_init(rctx, rctx->ev, monitor_intf,
                            svc_name, svc_version, rctx,
                            &rctx->mon_conn);
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 9705878fa80d33d3bddfe7be7fcc97151b44a0f0..84a6b7fedd096a7d4159b7ac6670820c1d8fd941 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -298,11 +298,6 @@ 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_SPACE, NULL,
-                            &nctx->override_space);
-    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 f5238fb822ecc376d8dca06c00fb989276949688..a5b946b7e4a38d7d8b35ec5df1b6644d01896470 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -69,7 +69,6 @@ struct nss_ctx {
     char **etc_shells;
     char *shell_fallback;
     char *default_shell;
-    char *override_space;
 
     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 10e84e52c2f2fbcd9ab75349a625eb01ba5fa871..91139980ab2f46cff1c71928f9106e2bfbfa6878 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -372,7 +372,8 @@ static int fill_pwent(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr,
+                                   nctx->rctx->override_space);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_replace_space failed, skipping\n");
@@ -752,7 +753,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
         if (!name) return ENOMEM;
 
         name = sss_reverse_replace_space(dctx, name,
-                                         nctx->override_space[0]);
+                                         nctx->rctx->override_space);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_reverse_replace_space failed\n");
@@ -2360,7 +2361,8 @@ static int fill_members(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr,
+                                   nctx->rctx->override_space);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_replace_space failed\n");
@@ -2523,7 +2525,8 @@ static int fill_grent(struct sss_packet *packet,
             continue;
         }
 
-        tmpstr = sss_replace_space(tmp_ctx, tmpstr, nctx->override_space[0]);
+        tmpstr = sss_replace_space(tmp_ctx, tmpstr,
+                                   nctx->rctx->override_space);
         if (tmpstr == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_replace_space failed, skipping\n");
@@ -2724,7 +2727,8 @@ 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_space(dctx, name, nctx->override_space[0]);
+        name = sss_reverse_replace_space(dctx, name,
+                                         nctx->rctx->override_space);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_reverse_replace_space failed\n");
@@ -3754,7 +3758,8 @@ 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_space(dctx, name, nctx->override_space[0]);
+        name = sss_reverse_replace_space(dctx, name,
+                                         nctx->rctx->override_space);
         if (name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "sss_reverse_replace_space failed\n");
@@ -3921,7 +3926,7 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
             }
 
             name = sss_reverse_replace_space(dctx, name,
-                                             nctx->override_space[0]);
+                                             nctx->rctx->override_space);
             if (name == NULL) {
                 DEBUG(SSSDBG_CRIT_FAILURE,
                       "sss_reverse_replace_space failed\n");
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index dba03ddb6bddcf358e54219027b0b74de43335f5..f5d1f60ec62056b42c52789f27a38eebdf362657 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -74,7 +74,6 @@ mock_nctx(TALLOC_CTX *mem_ctx)
     }
     nctx->neg_timeout = 10;
     nctx->pwfield = discard_const("*");
-    nctx->override_space = discard_const("\0");
 
     err = sss_idmap_init(sss_idmap_talloc, nctx, sss_idmap_talloc_free,
                          &nctx->idmap_ctx);
@@ -890,6 +889,7 @@ void test_nss_setup(struct sss_test_conf_param params[],
     nss_test_ctx->rctx = mock_rctx(nss_test_ctx, nss_test_ctx->tctx->ev,
                                    nss_test_ctx->tctx->dom, nss_test_ctx->nctx);
     assert_non_null(nss_test_ctx->rctx);
+    nss_test_ctx->nctx->rctx = nss_test_ctx->rctx;
 
     /* Create client context */
     nss_test_ctx->cctx = mock_cctx(nss_test_ctx, nss_test_ctx->rctx);
-- 
1.9.3

-------------- next part --------------
>From b2ebd8dab1f844b3f795568069737e3972810c8f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 1 Aug 2014 06:49:59 +0200
Subject: [PATCH 3/6] PAM: Use the override_default_space option

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

When using the override_default_space option, this patch allows to log
in using both the original name (space user) as well as the normalized
name (space_user).
---
 src/responder/pam/pamsrv_cmd.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 140d541ad6fe9328f5d74497e59153b907abdffd..d58ef64b7d6bb5a44108daabb864a45339cc697b 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -958,6 +958,14 @@ static int pam_check_user_search(struct pam_auth_req *preq)
             return ENOMEM;
         }
 
+        name = sss_reverse_replace_space(preq, name,
+                                         pctx->rctx->override_space);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_space failed\n");
+            return ENOMEM;
+        }
+
         /* Refresh the user's cache entry on any PAM query
          * We put a timeout in the client context so that we limit
          * the number of updates within a reasonable timeout
-- 
1.9.3

-------------- next part --------------
>From fb201fd7ee2f3ccf757b7c85f6ea19d614ff3ca9 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 1 Aug 2014 07:31:39 +0200
Subject: [PATCH 4/6] IFP: Use the override_default_space option

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

The input of the InfoPipe responder substitutes the configured character
for space and the GetUserAttrs and GetUserGroups functions substitute
space for the configured character in their output.
---
 src/responder/ifp/ifpsrv_cmd.c | 53 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index 50483933188cfe9cf1a855bf3505f7e24a91b975..b75761107ead6de78714303a08bfd2d046091c54 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -174,6 +174,26 @@ static void ifp_user_get_attr_process(struct tevent_req *req)
 }
 
 static errno_t
+ifp_user_get_attr_replace_space(TALLOC_CTX *mem_ctx,
+                                struct ldb_message_element *el,
+                                const char sub)
+{
+    int i;
+
+    for (i = 0; i < el->num_values; i++) {
+        el->values[i].data = (uint8_t *) sss_replace_space(mem_ctx,
+                                             (const char *) el->values[i].data,
+                                             sub);
+        if (el->values[i].data == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "sss_replace_space failed, skipping\n");
+            return ENOMEM;
+        }
+    }
+
+    return EOK;
+}
+
+static errno_t
 ifp_user_get_attr_handle_reply(struct ifp_req *ireq,
                                const char **attrs, struct ldb_result *res)
 {
@@ -214,6 +234,18 @@ ifp_user_get_attr_handle_reply(struct ifp_req *ireq,
                 continue;
             }
 
+            /* Normalize white space in user names */
+            if (ireq->ifp_ctx->rctx->override_space != '\0' &&
+                    strcmp(attrs[ai], SYSDB_NAME) == 0) {
+                ret = ifp_user_get_attr_replace_space(ireq, el,
+                                        ireq->ifp_ctx->rctx->override_space);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_MINOR_FAILURE, "Cannot normalize %s\n",
+                          attrs[ai]);
+                    continue;
+                }
+            }
+
             ret = ifp_add_ldb_el_to_dict(&iter_dict, el);
             if (ret != EOK) {
                 DEBUG(SSSDBG_MINOR_FAILURE,
@@ -343,8 +375,17 @@ ifp_user_get_groups_reply(struct ifp_req *ireq, struct ldb_result *res)
             continue;
         }
 
-        DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", name);
-        groupnames[i] = name;
+        if (ireq->ifp_ctx->rctx->override_space != '\0') {
+            groupnames[i] = sss_replace_space(groupnames, name,
+                                          ireq->ifp_ctx->rctx->override_space);
+            if (groupnames[i] == NULL) {
+                DEBUG(SSSDBG_MINOR_FAILURE, "Cannot normalize %s\n", name);
+                continue;
+            }
+        } else {
+            groupnames[i] = name;
+        }
+        DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", groupnames[i]);
     }
 
     return infopipe_iface_GetUserGroups_finish(ireq->dbus_req,
@@ -495,6 +536,14 @@ static errno_t ifp_user_get_attr_search(struct tevent_req *req)
         name = sss_get_cased_name(state, state->name, dom->case_sensitive);
         if (!name) return ENOMEM;
 
+        state->name = sss_reverse_replace_space(state, name,
+                                         state->rctx->override_space);
+        if (state->name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_space failed\n");
+            return ENOMEM;
+        }
+
         /* verify this user has not yet been negatively cached,
          * or has been permanently filtered */
         ret = sss_ncache_check_user(state->ncache,
-- 
1.9.3

-------------- next part --------------
>From 105e8a753a97a314dca55e8b2a3be010a6ddbc55 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 1 Aug 2014 08:00:46 +0200
Subject: [PATCH 5/6] SUDO: Use the override_default_space option

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

With this path, a user whose name is "space user" would match a sudo
rule while using the override_default_space option. Please note that the
option is only a client-side override, so the sudoUser attribute must
contain the space in order to match the original name. In other words,
when substituting space ( ) for underscore (_), this attribute would match:
    sudoUser: space user
this would not:
    sudoUser: space_user
---
 src/responder/sudo/sudosrv.c               | 2 --
 src/responder/sudo/sudosrv_get_sudorules.c | 8 ++++++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
index cafe9da53f0f1833ff2b1abee0801f6197267342..8a197159b23abde45953b65121ff2e3fc3f2f67a 100644
--- a/src/responder/sudo/sudosrv.c
+++ b/src/responder/sudo/sudosrv.c
@@ -132,8 +132,6 @@ int sudo_process_init(TALLOC_CTX *mem_ctx,
                             sudo_dp_reconnect_init, iter);
     }
 
-    /* Get responder options */
-
     /* Get sudo_timed option */
     ret = confdb_get_bool(sudo_ctx->rctx->cdb,
                           CONFDB_SUDO_CONF_ENTRY, CONFDB_SUDO_TIMED,
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 4b35a1aed30a3f23ff17d205b83934f9697369e2..a23665b6575f0e2a3532f6c41529fd0b64965efc 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -108,6 +108,14 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
             goto done;
         }
 
+        name = sss_reverse_replace_space(tmp_ctx, name,
+                                         cmd_ctx->sudo_ctx->rctx->override_space);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sss_reverse_replace_whitespaces failed\n");
+            return ENOMEM;
+        }
+
         DEBUG(SSSDBG_FUNC_DATA, "Requesting info about [%s@%s]\n",
               name, dom->name);
 
-- 
1.9.3

-------------- next part --------------
>From d2947cb8919309258bc90e0612102daf5c320aca Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 7 Aug 2014 18:20:58 +0200
Subject: [PATCH 6/6] TESTS: Add unit tests for the replace-space functionality

---
 src/tests/cmocka/test_nss_srv.c | 225 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 225 insertions(+)

diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index f5d1f60ec62056b42c52789f27a38eebdf362657..e7d6540ccdba1cdc6c3d87661df86e1b60900c6f 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -568,6 +568,117 @@ void test_nss_getpwnam_fqdn(void **state)
     assert_int_equal(ret, EOK);
 }
 
+/* Check that a user with a space in his username is returned fine.
+ */
+static int test_nss_getpwnam_check_space(uint32_t status,
+                                         uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 225);
+    assert_int_equal(pwd.pw_gid, 558);
+    assert_string_equal(pwd.pw_name, "space user");
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    return EOK;
+}
+
+void test_nss_getpwnam_space(void **state)
+{
+    errno_t ret;
+
+    /* Prime the cache with a valid user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "space user", 225, 558, "space user",
+                         "/home/testuser", "/bin/sh", NULL,
+                         NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    mock_input_user_or_group("space user");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
+    mock_fill_user();
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwnam_check_space);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+
+}
+
+static int test_nss_getpwnam_check_space_sub(uint32_t status,
+                                             uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 225);
+    assert_int_equal(pwd.pw_gid, 558);
+    assert_string_equal(pwd.pw_name, "space_user");
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    return EOK;
+}
+
+void test_nss_getpwnam_space_sub(void **state)
+{
+    errno_t ret;
+
+    /* Set whitespace substitution */
+    nss_test_ctx->rctx->override_space = '_';
+
+    mock_input_user_or_group("space user");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
+    mock_fill_user();
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwnam_check_space_sub);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    nss_test_ctx->rctx->override_space = '\0';
+    assert_int_equal(ret, EOK);
+}
+
+void test_nss_getpwnam_space_sub_query(void **state)
+{
+    errno_t ret;
+
+    /* Set whitespace substitution */
+    nss_test_ctx->rctx->override_space = '_';
+
+    mock_input_user_or_group("space_user");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
+    mock_fill_user();
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwnam_check_space_sub);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    nss_test_ctx->rctx->override_space = '\0';
+    assert_int_equal(ret, EOK);
+}
+
 /*
  * Check that FQDN processing is able to handle arbitrarily sized
  * delimeter
@@ -1357,6 +1468,110 @@ void test_nss_getgrnam_mix_subdom(void **state)
     assert_int_equal(ret, EOK);
 }
 
+static int test_nss_getgrnam_space_check(uint32_t status,
+                                         uint8_t *body, size_t blen)
+{
+    int ret;
+    uint32_t nmem;
+    struct group gr;
+    struct group expected = {
+        .gr_gid = 2123,
+        .gr_name = discard_const("space group"),
+        .gr_passwd = discard_const("*"),
+        .gr_mem = NULL,
+    };
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_group_packet(body, blen, &gr, &nmem);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(nmem, 0);
+
+    ret = test_nss_getgrnam_check(&expected, &gr, nmem);
+    assert_int_equal(ret, EOK);
+
+    return EOK;
+}
+
+/* Test that requesting a valid, cached group with space in its name returns a valid
+ * group structure
+ */
+void test_nss_getgrnam_space(void **state)
+{
+    errno_t ret;
+
+    /* Prime the cache with a valid group */
+    ret = sysdb_add_group(nss_test_ctx->tctx->dom,
+                          "space group", 2123,
+                          NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    mock_input_user_or_group("space group");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
+    mock_fill_group_with_members(0);
+
+    /* Query for that group, call a callback when command finishes */
+    set_cmd_cb(test_nss_getgrnam_space_check);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+}
+
+static int test_nss_getgrnam_space_sub_check(uint32_t status,
+                                             uint8_t *body, size_t blen)
+{
+    int ret;
+    uint32_t nmem;
+    struct group gr;
+    struct group expected = {
+        .gr_gid = 2123,
+        .gr_name = discard_const("space_group"),
+        .gr_passwd = discard_const("*"),
+        .gr_mem = NULL,
+    };
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_group_packet(body, blen, &gr, &nmem);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(nmem, 0);
+
+    ret = test_nss_getgrnam_check(&expected, &gr, nmem);
+    assert_int_equal(ret, EOK);
+
+    return EOK;
+}
+
+/* Test that requesting a valid, cached group with space in its name returns a valid
+ * group structure
+ */
+void test_nss_getgrnam_space_sub(void **state)
+{
+    errno_t ret;
+
+    /* Set whitespace substitution */
+    nss_test_ctx->rctx->override_space = '_';
+
+    mock_input_user_or_group("space group");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
+    mock_fill_group_with_members(0);
+
+    /* Query for that group, call a callback when command finishes */
+    set_cmd_cb(test_nss_getgrnam_space_sub_check);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    nss_test_ctx->rctx->override_space = '\0';
+    assert_int_equal(ret, EOK);
+}
+
 static int test_nss_well_known_sid_check(uint32_t status,
                                          uint8_t *body, size_t blen)
 {
@@ -1622,6 +1837,12 @@ int main(int argc, const char *argv[])
                                  nss_fqdn_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_fqdn_fancy,
                                  nss_fqdn_fancy_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwnam_space,
+                                 nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwnam_space_sub,
+                                 nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwnam_space_sub_query,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getgrnam_no_members,
                                  nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getgrnam_members,
@@ -1636,6 +1857,10 @@ int main(int argc, const char *argv[])
                                  nss_subdom_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getgrnam_mix_subdom,
                                  nss_subdom_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getgrnam_space,
+                                 nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getgrnam_space_sub,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_well_known_getnamebysid,
                                  nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_well_known_getnamebysid_special,
-- 
1.9.3



More information about the sssd-devel mailing list