<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Just a few more questions.<br>
    <br>
    <div class="moz-cite-prefix">On 07/25/2014 08:40 AM, Pavel Reichl
      wrote:<br>
    </div>
    <blockquote cite="mid:53D1FBC5.8090300@redhat.com" type="cite">
      <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
      Hello Lukas,<br>
      <br>
      just some nitpicks. Please see inline. Thanks!<br>
      <br>
      <div class="moz-cite-prefix">On 07/24/2014 11:28 AM, Lukas
        Slebodnik wrote:<br>
      </div>
      <blockquote cite="mid:20140724092856.GA32222@mail.corp.redhat.com"
        type="cite">
        <pre wrap="">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:
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="https://fedorahosted.org/sssd/ticket/1854">https://fedorahosted.org/sssd/ticket/1854</a>

patch is attached.

LS
</pre>
        <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <br>
        <pre wrap="">_______________________________________________
sssd-devel mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:sssd-devel@lists.fedorahosted.org">sssd-devel@lists.fedorahosted.org</a>
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="https://lists.fedorahosted.org/mailman/listinfo/sssd-devel">https://lists.fedorahosted.org/mailman/listinfo/sssd-devel</a>
</pre>
      </blockquote>
      <blockquote type="cite">
        <pre wrap="">---
 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       | 192 ++++++++++++++++++++++++++++++++++-
 7 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index ba33ea5d7123c6e799f13529b60c5938ad20e411..acb139adf6bc1ca2919906fe577333970ccdbfdd 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_WHITESPACES_REPLACEMENT_STRING "whitespaces_replacement_string"
 
 /* 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..910cdb4b5f0a8cca6ea3328b99722022e2f7ff24 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'),
+    'whitespaces_replacement_string': _('All white spaces will be replaced in group name 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..2b4841cec3d5a52002a618a2f38d48a8948ef261 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
+whitespaces_replacement_string = str, None, false
 
 [pam]
 # Authentication service
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 27d22f44ef4449ef9cad026757ff54dd5083672b..6f1c42b0aa3fb22e144fadc19880787e88fb860c 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -645,6 +645,24 @@ fallback_homedir = <i class="moz-txt-slash"><span class="moz-txt-tag">/</span>home<span class="moz-txt-tag">/</span></i>%u
                         &lt;/para&gt;
                     &lt;/listitem&gt;
                 &lt;/varlistentry&gt;
+                &lt;varlistentry&gt;
+                    &lt;term&gt;whitespaces_replacement_string (string)&lt;/term&gt;
+                    &lt;listitem&gt;
+                        &lt;para&gt;
+                            This parameter controls whether sssd will replace
+                            whitespace in user and group names with a given
+                            string e.g. (_). For example, whether the name
+                            &amp;quot;john doe&amp;quot; should be replaced with
+                            the string &amp;quot;john_doe&amp;quot;. Frequently Unix
+                            shell scripts will have difficulty with usernames
+                            contains whitespace due to the default field
+                             separator in the shell.
+                        &lt;/para&gt;
+                        &lt;para&gt;
+                            Default: not set (whitespaces will not be replaced)
+                        &lt;/para&gt;
+                    &lt;/listitem&gt;
+                &lt;/varlistentry&gt;
             &lt;/variablelist&gt;
         &lt;/refsect2&gt;
         &lt;refsect2 id='PAM'&gt;
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 84a6b7fedd096a7d4159b7ac6670820c1d8fd941..422dc6a05906eb2c2fbe5c32b3d0646d69b26891 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,
                             &amp;nctx-&gt;homedir_substr);
     if (ret != EOK) goto done;
 
+    ret = confdb_get_string(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
+                            CONFDB_NSS_WHITESPACES_REPLACEMENT_STRING, NULL,
+                            &amp;nctx-&gt;wsp_replacement_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..2e20b886ebbf2bc94ff7278b60b2f015f3eae74d 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 *wsp_replacement_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..ec272ea06a92730e93ca811f5bc5e8e32380e22f 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -32,6 +32,138 @@
 #include "sss_client/idmap/sss_nss_idmap.h"
 #include &lt;time.h&gt;
 
+static const char *replace_whitespaces(TALLOC_CTX *mem_ctx,
+                                       const char *orig_name,
+                                       const char *replace_string){</pre>
      </blockquote>
      missing space before {
                                                                                                

      <br>
                                     <br>
      <blockquote type="cite">
        <pre wrap="">+    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)){</pre>
      </blockquote>
      missing space<br>
      <blockquote type="cite">
        <pre wrap="">+                *p = replace_string[0];
+            }
+        }
+
+        return new_name;
+    }
+
+    tmp_ctx = talloc_new(mem_ctx);</pre>
      </blockquote>
    </blockquote>
    Is there any difference in creation of  tmp_ctx on NULL and on
    mem_ctx int this case? I guess as long as you steal result from
    tmp_ctx and then free tmp_ctx  it doesn't really matter, right? I
    guess it's just more usual to allocate on NULL in utility function.
    <br>
    <blockquote cite="mid:53D1FBC5.8090300@redhat.com" type="cite">
      <blockquote type="cite">
        <pre wrap="">
+    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)){</pre>
      </blockquote>
      missing space<br>
      <blockquote type="cite">
        <pre wrap="">+            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);</pre>
      </blockquote>
      <br>
      please consider adding new line<br>
      <blockquote type="cite">
        <pre wrap="">+done:
+    talloc_free(tmp_ctx);
+    return new_name;
+}
+
+static char *reverse_replace_withespaces(TALLOC_CTX *mem_ctx,
+                                         char *orig_name,
+                                         const char *replace_string){</pre>
      </blockquote>
      missing space<br>
      <blockquote type="cite">
        <pre wrap="">+    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(mem_ctx);
+    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;
+
+            /* append space */
+            new_name = talloc_asprintf_append(new_name, " ");</pre>
      </blockquote>
    </blockquote>
    You were interested in saving allocations - could adding space be
    part of prev talloc_asprintf_append?<br>
    <blockquote cite="mid:53D1FBC5.8090300@redhat.com" type="cite">
      <blockquote type="cite">
        <pre wrap="">
+            if (new_name == NULL) {
+                goto done;
+            }
+        } else {
+            new_name = talloc_asprintf_append(new_name, "%s", ptr);
+            if (new_name == NULL) {
+                goto done;
+            }
+            break;</pre>
      </blockquote>
    </blockquote>
    Why the break here? do-while loop would end anyway, right?<br>
    <blockquote cite="mid:53D1FBC5.8090300@redhat.com" type="cite">
      <blockquote type="cite">
        <pre wrap="">
+        }
+    } while (substr != NULL);
+
+    new_name = talloc_steal(mem_ctx, new_name);</pre>
      </blockquote>
      You might consider adding new line here. If you don't want then
      don't.<br>
      <blockquote type="cite">
        <pre wrap="">+done:
+    talloc_free(tmp_ctx);
+    return new_name;
+}
+
 static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
 {
     return sss_cmd_send_error(cmdctx-&gt;cctx, err);
@@ -371,6 +503,15 @@ static int fill_pwent(struct sss_packet *packet,
                   "sss_get_cased_name failed, skipping\n");
             continue;
         }
+
+        tmpstr = replace_whitespaces(tmp_ctx, tmpstr,
+                                     nctx-&gt;wsp_replacement_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "replace_whitespaces failed, skipping\n");
+            continue;
+        }
+
         to_sized_string(&amp;name, tmpstr);
 
         tmpstr = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
@@ -743,6 +884,14 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(cmdctx, cmdctx-&gt;name, dom-&gt;case_sensitive);
         if (!name) return ENOMEM;
 
+        name = reverse_replace_withespaces(dctx, name,
+                                           nctx-&gt;wsp_replacement_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "reverse_replace_withespaces failed, skipping\n");
+            continue;
+        }
+
         /* verify this user has not yet been negatively cached,
         * or has been permanently filtered */
         ret = sss_ncache_check_user(nctx-&gt;ncache, nctx-&gt;neg_timeout,
@@ -2316,7 +2465,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 +2493,14 @@ static int fill_members(struct sss_packet *packet,
             continue;
         }
 
+        tmpstr = replace_whitespaces(tmp_ctx, tmpstr,
+                                     nctx-&gt;wsp_replacement_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "replace_whitespaces failed, skipping\n");
+            continue;
+        }
+
         if (nctx-&gt;filter_users_in_groups) {
             ret = sss_ncache_check_user(nctx-&gt;ncache,
                                         nctx-&gt;neg_timeout,
@@ -2498,6 +2655,15 @@ static int fill_grent(struct sss_packet *packet,
                   "sss_get_cased_name failed, skipping\n");
             continue;
         }
+
+        tmpstr = replace_whitespaces(tmp_ctx, tmpstr,
+                                     nctx-&gt;wsp_replacement_str);
+        if (tmpstr == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "replace_whitespaces failed, skipping\n");
+            continue;
+        }
+
         to_sized_string(&amp;name, tmpstr);
 
         /* fill in gid and name and set pointer for number of members */
@@ -2692,6 +2858,14 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(dctx, cmdctx-&gt;name, dom-&gt;case_sensitive);
         if (!name) return ENOMEM;
 
+        name = reverse_replace_withespaces(dctx, name,
+                                           nctx-&gt;wsp_replacement_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "reverse_replace_withespaces failed, skipping\n");
+            continue;
+        }
+
         /* verify this group has not yet been negatively cached,
         * or has been permanently filtered */</pre>
      </blockquote>
      If you are changing nearby code can you add a space before *?<br>
      <blockquote type="cite">
        <pre wrap="">         ret = sss_ncache_check_group(nctx-&gt;ncache, nctx-&gt;neg_timeout,
@@ -3715,6 +3889,14 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
         name = sss_get_cased_name(dctx, cmdctx-&gt;name, dom-&gt;case_sensitive);
         if (!name) return ENOMEM;
 
+        name = reverse_replace_withespaces(dctx, name,
+                                           nctx-&gt;wsp_replacement_str);
+        if (name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "reverse_replace_withespaces failed, skipping\n");
+            continue;
+        }
+
         /* verify this user has not yet been negatively cached,
         * or has been permanently filtered */</pre>
      </blockquote>
      same as above please<br>
      <blockquote type="cite">
        <pre wrap="">         ret = sss_ncache_check_user(nctx-&gt;ncache, nctx-&gt;neg_timeout,
@@ -3874,6 +4056,14 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
                 goto done;
             }
 
+            name = reverse_replace_withespaces(dctx, name,
+                                               nctx-&gt;wsp_replacement_str);
+            if (name == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "reverse_replace_withespaces failed, skipping\n");
+                continue;
+            }
+
             /* For subdomains a fully qualified name is needed for
              * sysdb_search_user_by_name and sysdb_search_group_by_name. */
             if (IS_SUBDOMAIN(dom)) {</pre>
      </blockquote>
      <br>
      <br>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
sssd-devel mailing list
<a class="moz-txt-link-abbreviated" href="mailto:sssd-devel@lists.fedorahosted.org">sssd-devel@lists.fedorahosted.org</a>
<a class="moz-txt-link-freetext" href="https://lists.fedorahosted.org/mailman/listinfo/sssd-devel">https://lists.fedorahosted.org/mailman/listinfo/sssd-devel</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>