>From 7f23a86c1e3662c4a120fa5bdbca364f130a0bfe Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Thu, 3 Apr 2014 11:01:37 +0100
Subject: [PATCH 05/12] utils: common functions for homedir overrides

Functions used by providers to perform overrides on user's home directories.

Resolves:
https://fedorahosted.org/sssd/ticket/2205
---
 src/util/sss_homedir.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/sss_homedir.h |  13 ++++++
 2 files changed, 123 insertions(+)

diff --git a/src/util/sss_homedir.c b/src/util/sss_homedir.c
index 94c54236b011fca65f2a798b174665fc8eb5ec03..097af2b4288af9a06f94c7cb82f6f12ae3a7e0aa 100644
--- a/src/util/sss_homedir.c
+++ b/src/util/sss_homedir.c
@@ -158,3 +158,113 @@ done:
     talloc_zfree(tmp_ctx);
     return res;
 }
+
+static errno_t parse_lc_username(TALLOC_CTX *mem_ctx,
+                                 struct sss_names_ctx *snctx,
+                                 const char *fqname,
+                                 char **_lc_username)
+{
+    errno_t ret;
+    char *username;
+    char *lc_username;
+    TALLOC_CTX *tmp_ctx;
+
+    tmp_ctx = talloc_new(mem_ctx);
+    if (tmp_ctx == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sss_parse_name(tmp_ctx, snctx, fqname, NULL, &username);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse [%s] into "
+              "name-value components.\n", fqname);
+        goto done;
+    }
+
+    lc_username = sss_tc_utf8_str_tolower(tmp_ctx, username);
+    if (lc_username == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    if (_lc_username == NULL) {
+        ret = EINVAL;
+        goto done;
+    }
+    *_lc_username = talloc_steal(mem_ctx, lc_username);
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+static const char *perform_homedir_override(TALLOC_CTX *mem_ctx,
+                                            const char* homedir,
+                                            struct sss_domain_info *dom,
+                                            const char *fqname,
+                                            uint32_t uid,
+                                            enum subdomain_homedir_usage sh_use)
+{
+    char *lc_username;
+    errno_t ret;
+
+    /* To be compatible with the old winbind based user lookups and IPA
+     * clients the user name in the home directory path will be lower-case.
+     */
+    ret = parse_lc_username(mem_ctx, dom->names, fqname, &lc_username);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "Failed to parse lowercased username from %s.\n", fqname);
+        return NULL;
+    }
+
+    /* Check whether we are unconditionally overriding the server
+     * for home directory locations.
+     */
+    if (dom->override_homedir != NULL) {
+        return expand_homedir_template(mem_ctx, dom->override_homedir,
+                                       lc_username, uid, homedir, dom->name,
+                                       NULL);
+    }
+
+    if (sh_use == USE_SUBDOMAIN_HOMEDIR && dom->subdomain_homedir) {
+        return expand_homedir_template(mem_ctx, dom->subdomain_homedir,
+                                       lc_username, uid, homedir, dom->name,
+                                       dom->flat_name);
+    }
+
+    if (homedir == NULL || *homedir == '\0') {
+        /* In the case of a NULL or empty homedir, check to see if
+         * we have a fallback homedir to use.
+         */
+        if (dom->fallback_homedir != NULL) {
+            return expand_homedir_template(mem_ctx, dom->fallback_homedir,
+                                           lc_username, uid, homedir,
+                                           dom->name, NULL);
+        } else {
+            return NULL;
+        }
+    }
+
+    /* Return the value we got from the provider */
+    return talloc_strdup(mem_ctx, homedir);
+}
+
+const char *safe_homedir_override(TALLOC_CTX *mem_ctx,
+                                  const char* homedir,
+                                  struct sss_domain_info *dom,
+                                  const char *fqname,
+                                  uint32_t uid,
+                                  enum subdomain_homedir_usage sh_use)
+{
+    const char *res;
+    res = perform_homedir_override(mem_ctx, homedir, dom, fqname, uid, sh_use);
+    if (res == NULL || res[0] == '\0') {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+               "perform_homedir_override returned invalid homedir.\n");
+        return FALLBACK_HOMEDIR;
+    }
+    return res;
+}
diff --git a/src/util/sss_homedir.h b/src/util/sss_homedir.h
index 446b58e3df710085e640733797efd4f0434167ef..b14c041761037d4a7dafd840a0ab480cc7aec5ac 100644
--- a/src/util/sss_homedir.h
+++ b/src/util/sss_homedir.h
@@ -29,4 +29,17 @@ char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
                               const char *username, uint32_t uid,
                               const char *original, const char *domain,
                               const char *flatname);
+
+enum subdomain_homedir_usage {
+    USE_SUBDOMAIN_HOMEDIR,
+    DO_NOT_USE_SUBDOMAIN_HOMEDIR
+};
+
+const char *safe_homedir_override(TALLOC_CTX *mem_ctx,
+                                  const char* homedir,
+                                  struct sss_domain_info *dom,
+                                  const char *fqname,
+                                  uint32_t uid,
+                                  enum subdomain_homedir_usage sh_use);
+
 #endif
-- 
1.8.4.2

