URL: https://github.com/SSSD/sssd/pull/163
Author: jhrozek
 Title: #163: Enable the files domain for all sssd configurations
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/163/head:pr163
git checkout pr163
From 47a28714c047385b9800473627f570662215670d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Tue, 21 Feb 2017 16:34:45 +0100
Subject: [PATCH 1/7] MONITOR: Enable an implicit files domain if one is not
 configured

Resolves:
    https://fedorahosted.org/sssd/ticket/3112

If SSSD is compiled with --enable-files-domain, the loading of the
domains changes such that:
    * if no domain with id_provider=files exists in the config file, an
      implicit SSSD files domain is added
    * this domain is always first in the list

The administrator is free to create a files domain in the config file
himself and either place it at the end of the list or not enable it at
all.
---
 src/conf_macros.m4    |  12 ++++
 src/confdb/confdb.c   | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/confdb/confdb.h   |   3 +
 src/monitor/monitor.c |  11 ++++
 4 files changed, 191 insertions(+)

diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index 427b0e0..bd65217 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -903,3 +903,15 @@ AC_DEFUN([WITH_SECRETS_DB_PATH],
     AC_SUBST(secdbpath)
     AC_DEFINE_UNQUOTED(SECRETS_DB_PATH, "$config_secdbpath", [Path to the SSSD Secrets databases])
   ])
+
+AC_ARG_ENABLE([files-domain],
+              [AS_HELP_STRING([--enable-files-domain],
+                              [If this feature is enabled, then SSSD always enables
+                               a domain with id_provider=files even if the domain
+                               is not specified in the config file
+                              [default=no]])],
+              [enable_files_domain=$enableval],
+              [enable_files_domain=no])
+AS_IF([test x$enable_files_domain = xyes],
+      AC_DEFINE_UNQUOTED([ADD_FILES_DOMAIN], [1],
+          [whether to build unconditionally enable files domain]))
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index c7afd68..980cabc 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1643,3 +1643,168 @@ int confdb_get_sub_sections(TALLOC_CTX *mem_ctx,
     talloc_free(tmp_ctx);
     return ret;
 }
+
+#ifdef ADD_FILES_DOMAIN
+static int confdb_has_files_domain(struct confdb_ctx *cdb)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct ldb_dn *dn = NULL;
+    struct ldb_result *res = NULL;
+    static const char *attrs[] = {CONFDB_DOMAIN_ID_PROVIDER, NULL};
+    const char *id_provider = NULL;
+    int ret;
+    unsigned int i;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    dn = ldb_dn_new(tmp_ctx, cdb->ldb, CONFDB_DOMAIN_BASEDN);
+    if (dn == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
+                     attrs, NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = EIO;
+        goto done;
+    }
+
+    for (i = 0; i < res->count; i++) {
+        id_provider = ldb_msg_find_attr_as_string(res->msgs[i],
+                                                  CONFDB_DOMAIN_ID_PROVIDER,
+                                                  NULL);
+        if (id_provider == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "The object [%s] doesn't have a id_provider\n",
+                   ldb_dn_get_linearized(res->msgs[i]->dn));
+            ret = EINVAL;
+            goto done;
+        }
+
+        if (strcasecmp(id_provider, "files") == 0) {
+            break;
+        }
+    }
+
+    ret = i < res->count ? EOK : ENOENT;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+static int create_files_domain(struct confdb_ctx *cdb,
+                               const char *name)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    errno_t ret;
+    char *cdb_path = NULL;
+    const char *val[2] = {NULL, NULL};
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
+        return ENOMEM;
+    }
+
+    cdb_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
+    if (cdb_path == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    val[0] = "files";
+    ret = confdb_add_param(cdb, true, cdb_path, "id_provider", val);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+static int activate_files_domain(struct confdb_ctx *cdb,
+                                 const char *name)
+{
+    errno_t ret;
+    TALLOC_CTX *tmp_ctx;
+    char *monitor_domlist;
+    const char *domlist[2] = { NULL, NULL };
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = confdb_get_string(cdb, tmp_ctx,
+                            CONFDB_MONITOR_CONF_ENTRY,
+                            CONFDB_MONITOR_ACTIVE_DOMAINS,
+                            NULL,
+                            &monitor_domlist);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
+        goto done;
+    }
+
+    if (monitor_domlist != NULL) {
+        domlist[0] = talloc_asprintf(tmp_ctx, "%s,%s", name, monitor_domlist);
+        if (domlist[0] == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    } else {
+        domlist[0] = name;
+    }
+
+    ret = confdb_add_param(cdb, true,
+                           CONFDB_MONITOR_CONF_ENTRY,
+                           CONFDB_MONITOR_ACTIVE_DOMAINS,
+                           domlist);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Cannot extend the domain list [%d]: %s\n",
+              ret, sss_strerror(ret));
+        return ret;
+    }
+
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+#endif /* ADD_FILES_DOMAIN */
+
+int confdb_ensure_files_domain(struct confdb_ctx *cdb,
+                               const char *implicit_files_dom_name)
+{
+#ifndef ADD_FILES_DOMAIN
+    return EOK;
+#else
+    errno_t ret;
+
+    ret = confdb_has_files_domain(cdb);
+    if (ret == EOK) {
+        DEBUG(SSSDBG_CONF_SETTINGS, "The files domain is already enabled\n");
+        return EOK;
+    } else if (ret != ENOENT) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up the files domain\n");
+        return ret;
+    }
+
+    /* ENOENT, so let's add a files domain */
+    ret = create_files_domain(cdb, implicit_files_dom_name);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add an implicit files domain\n");
+        return ret;
+    }
+
+    return activate_files_domain(cdb, implicit_files_dom_name);
+#endif  /* ADD_FILES_DOMAIN */
+}
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 353dfd0..54919f5 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -373,6 +373,9 @@ int confdb_get_domain(struct confdb_ctx *cdb,
 int confdb_get_domains(struct confdb_ctx *cdb,
                        struct sss_domain_info **domains);
 
+int confdb_ensure_files_domain(struct confdb_ctx *cdb,
+                               const char *implicit_files_dom_name);
+
 /**
  * Get a null-terminated linked-list of all domain names
  * @param[in] mem_ctx The parent memory context for the value list
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 59bf707..18a5c1b 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -90,6 +90,9 @@
                                  "that the file is accessible only by the "\
                                  "owner and owned by root.root.\n"
 
+/* SSSD domain name that is used for the auto-configured files domain */
+#define IMPLICIT_FILES_DOMAIN_NAME  "implicit_files"
+
 int cmdline_debug_level;
 int cmdline_debug_timestamps;
 int cmdline_debug_microseconds;
@@ -1053,6 +1056,14 @@ static int get_monitor_config(struct mt_ctx *ctx)
         return ret;
     }
 
+    ret = confdb_ensure_files_domain(ctx->cdb, IMPLICIT_FILES_DOMAIN_NAME);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "Cannot add the implicit files domain [%d]: %s\n",
+              ret, strerror(ret));
+        /* Not fatal */
+    }
+
     ret = confdb_get_domains(ctx->cdb, &ctx->domains);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n");

From 72df783d180faa93125686e9d52443e92f726733 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 24 Feb 2017 15:50:08 +0100
Subject: [PATCH 2/7] SQ: Add an option to disable files domain

---
 src/conf_macros.m4                   |  1 +
 src/confdb/confdb.c                  | 17 +++++++++++++++++
 src/confdb/confdb.h                  |  1 +
 src/config/SSSDConfig/__init__.py.in |  1 +
 src/config/SSSDConfigTest.py         |  3 ++-
 src/config/cfg_rules.ini             |  1 +
 src/config/etc/sssd.api.conf         |  1 +
 src/man/Makefile.am                  |  7 ++++++-
 src/man/sssd.conf.5.xml              | 17 +++++++++++++++++
 9 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index bd65217..749e769 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -915,3 +915,4 @@ AC_ARG_ENABLE([files-domain],
 AS_IF([test x$enable_files_domain = xyes],
       AC_DEFINE_UNQUOTED([ADD_FILES_DOMAIN], [1],
           [whether to build unconditionally enable files domain]))
+AM_CONDITIONAL([ADD_FILES_DOMAIN], [test x$enable_files_domain = xyes])
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index 980cabc..5b2fef5 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1788,6 +1788,23 @@ int confdb_ensure_files_domain(struct confdb_ctx *cdb,
     return EOK;
 #else
     errno_t ret;
+    bool enable_files;
+
+    ret = confdb_get_bool(cdb,
+                          CONFDB_MONITOR_CONF_ENTRY,
+                          CONFDB_MONITOR_ENABLE_FILES_DOM,
+                          true, &enable_files);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "Cannot get the value of %s assuming true\n",
+              CONFDB_MONITOR_ENABLE_FILES_DOM);
+        return ret;
+    }
+
+    if (enable_files == false) {
+        DEBUG(SSSDBG_CONF_SETTINGS, "The implicit files domain is disabled\n");
+        return EOK;
+    }
 
     ret = confdb_has_files_domain(cdb);
     if (ret == EOK) {
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 54919f5..89b89bf 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -73,6 +73,7 @@
 #define CONFDB_MONITOR_USER_RUNAS "user"
 #define CONFDB_MONITOR_CERT_VERIFICATION "certificate_verification"
 #define CONFDB_MONITOR_DISABLE_NETLINK "disable_netlink"
+#define CONFDB_MONITOR_ENABLE_FILES_DOM "enable_files_domain"
 
 /* Both monitor and domains */
 #define CONFDB_NAME_REGEX   "re_expression"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 8c23fd2..44fb777 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -64,6 +64,7 @@ option_strings = {
     'certificate_verification' : _('Tune certificate verification'),
     'override_space': _('All spaces in group or user names will be replaced with this character'),
     'disable_netlink' : _('Tune sssd to honor or ignore netlink state changes'),
+    'enable_files_domain' : _('Enable or disable the implicit files domain'),
 
     # [nss]
     'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 0da5d63..8cb03ad 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -312,7 +312,8 @@ def testListOptions(self):
             'description',
             'certificate_verification',
             'override_space',
-            'disable_netlink']
+            'disable_netlink',
+            'enable_files_domain']
 
         self.assertTrue(type(options) == dict,
                         "Options should be a dictionary")
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index 51981c3..dd0f04b 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -41,6 +41,7 @@ option = certificate_verification
 option = override_space
 option = config_file_version
 option = disable_netlink
+option = enable_files_domain
 
 [rule/allowed_nss_options]
 validator = ini_allowed_options
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 5654006..7d21d6b 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -30,6 +30,7 @@ default_domain_suffix = str, None, false
 certificate_verification = str, None, false
 override_space = str, None, false
 disable_netlink = bool, None, false
+enable_files_domain = str, None, false
 
 [nss]
 # Name service
diff --git a/src/man/Makefile.am b/src/man/Makefile.am
index 760bb78..215ce69 100644
--- a/src/man/Makefile.am
+++ b/src/man/Makefile.am
@@ -35,7 +35,12 @@ endif
 if HAVE_SYSTEMD_UNIT
 SYSTEMD_CONDS = ;have_systemd
 endif
-CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SEC_CONDS)$(SYSTEMD_CONDS)
+if ADD_FILES_DOMAIN
+FILES_CONDS = ;enable_files_domain
+else
+FILES_CONDS = ;no_enable_files_domain
+endif
+CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SEC_CONDS)$(SYSTEMD_CONDS)$(FILES_CONDS)
 
 
 #Special Rules:
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 782aef7..2a2ef69 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -525,6 +525,23 @@
                             </para>
                         </listitem>
                     </varlistentry>
+                    <varlistentry>
+                        <term>enable_files_domain (boolean)</term>
+                        <listitem>
+                            <para>
+                                When this option is enabled, SSSD
+                                prepends an implicit domain with
+                                <quote>id_provider=files</quote> before
+                                any explicitly configured domains.
+                            </para>
+                            <para condition="no_enable_files_domain">
+                                Default: false
+                            </para>
+                            <para condition="enable_files_domain">
+                                Default: true
+                            </para>
+                        </listitem>
+                    </varlistentry>
                 </variablelist>
             </para>
         </refsect2>

From e080171cc2eea798fca4f161c20219c5f619494d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Tue, 21 Feb 2017 21:05:25 +0100
Subject: [PATCH 3/7] TESTS: Enable the files domain for all integration tests

This is done to make sure that enabling the files domain doesn't break
existing functionality as well as making it possible to even that the
implicit domain, since all integration tests use the same configuration.
---
 Makefile.am                        |  1 +
 src/tests/intg/test_enumeration.py | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index e676e18..30ee5e5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3239,6 +3239,7 @@ intgcheck-prepare:
 	    --with-ldb-lib-dir="$$prefix"/lib/ldb \
 	    --enable-intgcheck-reqs \
 	    --without-semanage \
+	    --enable-files-domain \
 	    $(INTGCHECK_CONFIGURE_FLAGS); \
 	$(MAKE) $(AM_MAKEFLAGS); \
 	: Force single-thread install to workaround concurrency issues; \
diff --git a/src/tests/intg/test_enumeration.py b/src/tests/intg/test_enumeration.py
index 5cb6c3e..47772de 100644
--- a/src/tests/intg/test_enumeration.py
+++ b/src/tests/intg/test_enumeration.py
@@ -98,7 +98,12 @@ def create_ldap_fixture(request, ldap_conn, ent_list=None):
 
 
 def format_basic_conf(ldap_conn, schema):
-    """Format a basic SSSD configuration"""
+    """
+    Format a basic SSSD configuration
+
+    The files domain is defined but not enabled in order to avoid enumerating
+    users from the files domain that would otherwise by implicitly enabled
+    """
     schema_conf = "ldap_schema         = " + schema + "\n"
     if schema == SCHEMA_RFC2307_BIS:
         schema_conf += "ldap_group_object_class = groupOfNames\n"
@@ -115,6 +120,9 @@ def format_basic_conf(ldap_conn, schema):
         [pam]
         debug_level         = 0xffff
 
+        [domain/files]
+        id_provider         = files
+
         [domain/LDAP]
         ldap_auth_disable_tls_never_use_in_production = true
         debug_level         = 0xffff

From b4663213e20c92509cc3bb281fddb54d1114f260 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Tue, 21 Feb 2017 21:04:29 +0100
Subject: [PATCH 4/7] TESTS: Test the files domain autoconfiguration

Adds unit tests that exercise the implicit files domain.
---
 src/tests/intg/test_files_provider.py | 52 +++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py
index 528b5e5..755353c 100644
--- a/src/tests/intg/test_files_provider.py
+++ b/src/tests/intg/test_files_provider.py
@@ -125,6 +125,32 @@ def files_domain_only(request):
     return None
 
 
+@pytest.fixture
+def no_sssd_domain(request):
+    conf = unindent("""\
+        [sssd]
+        services            = nss
+    """).format(**locals())
+    create_conf_fixture(request, conf)
+    create_sssd_fixture(request)
+    return None
+
+
+@pytest.fixture
+def no_files_domain(request):
+    conf = unindent("""\
+        [sssd]
+        domains             = local
+        services            = nss
+
+        [domain/local]
+        id_provider = local
+    """).format(**locals())
+    create_conf_fixture(request, conf)
+    create_sssd_fixture(request)
+    return None
+
+
 def setup_pw_with_list(request, user_list):
     pwd_ops = passwd_ops_setup(request)
     for user in user_list:
@@ -754,3 +780,29 @@ def test_realloc_groups(setup_gr_with_canary, files_domain_only):
     check for off-by-one errors.
     """
     realloc_groups(setup_gr_with_canary, FILES_REALLOC_CHUNK*3)
+
+
+# Files domain autoconfiguration tests
+def test_no_sssd_domain(add_user_with_canary, no_sssd_domain):
+    """
+    Test that if no sssd domain is configured, sssd will add the implicit one
+    """
+    res, user = sssd_getpwnam_sync(USER1["name"])
+    assert res == NssReturnCode.SUCCESS
+    assert user == USER1
+
+
+def test_no_files_domain(add_user_with_canary, no_files_domain):
+    """
+    Test that if no files domain is configured, sssd will add the implicit one
+    before any explicitly configured domains
+    """
+    # Add a user with a different UID than the one in files
+    subprocess.check_call(
+        ["sss_useradd", "-u", "10009", "-M", USER1["name"]])
+
+    # Even though the local domain is the only one configured,
+    # files will be resolved first
+    res, user = sssd_getpwnam_sync(USER1["name"])
+    assert res == NssReturnCode.SUCCESS
+    assert user == USER1

From 4b0335f7a784f1a4464b769fb979b2544a9f9c4d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 24 Feb 2017 15:49:56 +0100
Subject: [PATCH 5/7] SQ: Add an option to disable files domain

---
 src/tests/intg/test_files_provider.py | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py
index 755353c..abf836b 100644
--- a/src/tests/intg/test_files_provider.py
+++ b/src/tests/intg/test_files_provider.py
@@ -151,6 +151,22 @@ def no_files_domain(request):
     return None
 
 
+@pytest.fixture
+def disabled_files_domain(request):
+    conf = unindent("""\
+        [sssd]
+        domains             = local
+        services            = nss
+        enable_files_domain = false
+
+        [domain/local]
+        id_provider = local
+    """).format(**locals())
+    create_conf_fixture(request, conf)
+    create_sssd_fixture(request)
+    return None
+
+
 def setup_pw_with_list(request, user_list):
     pwd_ops = passwd_ops_setup(request)
     for user in user_list:
@@ -806,3 +822,13 @@ def test_no_files_domain(add_user_with_canary, no_files_domain):
     res, user = sssd_getpwnam_sync(USER1["name"])
     assert res == NssReturnCode.SUCCESS
     assert user == USER1
+
+
+def test_disable_files_domain(add_user_with_canary, disabled_files_domain):
+    """
+    Test that if no files domain is configured, sssd will add the implicit one
+    before any explicitly configured domains
+    """
+    # The local user will not be resolvable through nss_sss now
+    res, user = sssd_getpwnam_sync(USER1["name"])
+    assert res != NssReturnCode.SUCCESS

From 84a4a005496e6c5c040a04cfdcf26c11d9a83a10 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Thu, 23 Feb 2017 12:02:06 +0100
Subject: [PATCH 6/7] CONFDB: Refactor reading the config file

This is in preparation for creating a fallback configuration
---
 src/confdb/confdb_setup.c | 149 +++++++++++++++++++++++++++-------------------
 1 file changed, 89 insertions(+), 60 deletions(-)

diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c
index a71d9dd..a5de196 100644
--- a/src/confdb/confdb_setup.c
+++ b/src/confdb/confdb_setup.c
@@ -126,69 +126,39 @@ static int confdb_create_base(struct confdb_ctx *cdb)
     return EOK;
 }
 
-static int confdb_init_db(const char *config_file, const char *config_dir,
-                          struct confdb_ctx *cdb)
+static int confdb_ldif_from_ini_file(TALLOC_CTX *mem_ctx,
+                                     const char *config_file,
+                                     const char *config_dir,
+                                     struct sss_ini_initdata *init_data,
+                                     const char **_timestr,
+                                     const char **_ldif)
 {
-    TALLOC_CTX *tmp_ctx;
-    int ret;
-    int sret = EOK;
-    int version;
+    errno_t ret;
     char timestr[21];
-    bool in_transaction = false;
-    const char *config_ldif;
-    const char *vals[2] = { timestr, NULL };
-    struct ldb_ldif *ldif;
-    struct sss_ini_initdata *init_data;
-
-    tmp_ctx = talloc_new(cdb);
-    if (tmp_ctx == NULL) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
-        return ENOMEM;
-    }
-
-    init_data = sss_ini_initdata_init(tmp_ctx);
-    if (!init_data) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
-    /* Open config file */
-    ret = sss_ini_config_file_open(init_data, config_file);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_TRACE_FUNC,
-              "sss_ini_config_file_open failed: %s [%d]\n", strerror(ret),
-               ret);
-        if (ret == ENOENT) {
-            /* sss specific error denoting missing configuration file */
-            ret = ERR_MISSING_CONF;
-        }
-        goto done;
-    }
+    int version;
 
     ret = sss_ini_config_access_check(init_data);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Permission check on config file failed.\n");
-        ret = EPERM;
-        goto done;
+        return EPERM;
     }
 
     ret = sss_ini_get_stat(init_data);
     if (ret != EOK) {
+        ret = errno;
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Status check on config file failed.\n");
-        ret = errno;
-        goto done;
+        return ret;
     }
 
     errno = 0;
-
     ret = sss_ini_get_mtime(init_data, sizeof(timestr), timestr);
     if (ret <= 0 || ret >= (int)sizeof(timestr)) {
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Failed to convert time_t to string ??\n");
         ret = errno ? errno : EFAULT;
+        return ret;
     }
 
     /* FIXME: Determine if the conf file or any snippet has changed
@@ -199,7 +169,7 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
     ret = sss_ini_get_config(init_data, config_file, config_dir);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load configuration\n");
-        goto done;
+        return ret;
     }
 
     ret = sss_ini_call_validators(init_data,
@@ -214,7 +184,7 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Internal error determining config_file_version\n");
-        goto done;
+        return ret;
     }
 
     ret = sss_ini_check_config_obj(init_data);
@@ -230,21 +200,87 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
         if (ret != EOK) {
             DEBUG(SSSDBG_FATAL_FAILURE,
                   "Config file version could not be determined\n");
-            goto done;
+            return ret;
         } else if (version < CONFDB_VERSION_INT) {
             DEBUG(SSSDBG_FATAL_FAILURE,
                   "Config file is an old version. "
                   "Please run configuration upgrade script.\n");
-            ret = EINVAL;
-            goto done;
+            return EINVAL;
         } else if (version > CONFDB_VERSION_INT) {
             DEBUG(SSSDBG_FATAL_FAILURE,
                   "Config file version is newer than confdb\n");
-            ret = EINVAL;
-            goto done;
+            return EINVAL;
+        }
+    }
+
+    ret = sss_confdb_create_ldif(mem_ctx, init_data, _ldif);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Could not create LDIF for confdb\n");
+        return ret;
+    }
+
+    *_timestr = talloc_strdup(mem_ctx, timestr);
+    if (*_timestr == NULL) {
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
+static int confdb_init_db(const char *config_file, const char *config_dir,
+                          struct confdb_ctx *cdb)
+{
+    TALLOC_CTX *tmp_ctx;
+    int ret;
+    int sret = EOK;
+    bool in_transaction = false;
+    const char *timestr;
+    const char *config_ldif;
+    const char *vals[2] = { NULL, NULL };
+    struct ldb_ldif *ldif;
+    struct sss_ini_initdata *init_data;
+
+    tmp_ctx = talloc_new(cdb);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
+        return ENOMEM;
+    }
+
+    init_data = sss_ini_initdata_init(tmp_ctx);
+    if (!init_data) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* Open config file */
+    ret = sss_ini_config_file_open(init_data, config_file);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CONF_SETTINGS,
+              "sss_ini_config_file_open failed: %s [%d]\n", strerror(ret),
+               ret);
+        if (ret == ENOENT) {
+            /* sss specific error denoting missing configuration file */
+            ret = ERR_MISSING_CONF;
         }
+        goto done;
     }
 
+    ret = confdb_ldif_from_ini_file(tmp_ctx,
+                                    config_file,
+                                    config_dir,
+                                    init_data,
+                                    &timestr,
+                                    &config_ldif);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Cannot convert INI to LDIF [%d]: [%s]\n",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+    DEBUG(SSSDBG_CONF_SETTINGS, "LDIF file to import: \n%s\n", config_ldif);
+
+
     /* Set up a transaction to replace the configuration */
     ret = ldb_transaction_start(cdb->ldb);
     if (ret != LDB_SUCCESS) {
@@ -264,20 +300,12 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
         goto done;
     }
 
-    ret = sss_confdb_create_ldif(tmp_ctx, init_data, &config_ldif);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Could not create LDIF for confdb\n");
-        goto done;
-    }
-
-    DEBUG(SSSDBG_TRACE_LIBS, "LDIF file to import: \n%s\n", config_ldif);
-
     while ((ldif = ldb_ldif_read_string(cdb->ldb, &config_ldif))) {
         ret = ldb_add(cdb->ldb, ldif->msg);
         if (ret != LDB_SUCCESS) {
             DEBUG(SSSDBG_FATAL_FAILURE,
-                    "Failed to initialize DB (%d,[%s]), aborting!\n",
-                     ret, ldb_errstring(cdb->ldb));
+                  "Failed to initialize DB (%d,[%s]), aborting!\n",
+                  ret, ldb_errstring(cdb->ldb));
             ret = EIO;
             goto done;
         }
@@ -287,10 +315,11 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
     /* now store the lastUpdate time so that we do not re-init if nothing
      * changed on restart */
 
+    vals[0] = timestr;
     ret = confdb_add_param(cdb, true, "config", "lastUpdate", vals);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
-                "Failed to set last update time on db!\n");
+              "Failed to set last update time on db!\n");
         goto done;
     }
 

From a068ec7b2a6d1ee8fc2e2cda5124b80125355e57 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Thu, 23 Feb 2017 12:22:49 +0100
Subject: [PATCH 7/7] CONFDB: If no configuration file is provided, create a
 fallback configuration

Resolves:
    https://fedorahosted.org/sssd/ticket/2229

This functionality is only enabled in case SSSD is configured with with
--enable-files-domain. If not, the behaviour is as it used to -- SSSD
returns an error, instructing the admin to create a configuration file.

If the option is enabled, a very minimal confdb that only enables the
NSS responder is created. The confdb later adds the implicit files
domain.
---
 src/confdb/confdb_setup.c             | 66 +++++++++++++++++++++++++----------
 src/tests/intg/test_files_provider.py | 16 +++++++++
 2 files changed, 64 insertions(+), 18 deletions(-)

diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c
index a5de196..1c5dba9 100644
--- a/src/confdb/confdb_setup.c
+++ b/src/confdb/confdb_setup.c
@@ -28,6 +28,14 @@
 #include "confdb_setup.h"
 #include "util/sss_ini.h"
 
+#ifndef SSSD_FALLBACK_CONFIG_LDIF
+#define SSSD_FALLBACK_CONFIG_LDIF \
+"dn: cn=config\n" \
+"version: 2\n\n" \
+"dn: cn=sssd,cn=config\n" \
+"cn: sssd\n" \
+"services: nss\n\n"
+#endif /* SSSD_FALLBACK_CONFIG_LDIF */
 
 static int confdb_test(struct confdb_ctx *cdb)
 {
@@ -227,6 +235,23 @@ static int confdb_ldif_from_ini_file(TALLOC_CTX *mem_ctx,
     return EOK;
 }
 
+static int confdb_fallback_ldif(TALLOC_CTX *mem_ctx,
+                                const char **_timestr,
+                                const char **_ldif)
+{
+#ifndef ADD_FILES_DOMAIN
+    return ERR_MISSING_CONF;
+#else
+    *_timestr = talloc_strdup(mem_ctx, "1");
+    *_ldif = talloc_strdup(mem_ctx, SSSD_FALLBACK_CONFIG_LDIF);
+    if (*_timestr == NULL || *_ldif == NULL) {
+        return ENOMEM;
+    }
+
+    return EOK;
+#endif
+}
+
 static int confdb_init_db(const char *config_file, const char *config_dir,
                           struct confdb_ctx *cdb)
 {
@@ -255,29 +280,34 @@ static int confdb_init_db(const char *config_file, const char *config_dir,
 
     /* Open config file */
     ret = sss_ini_config_file_open(init_data, config_file);
-    if (ret != EOK) {
+    if (ret == EOK) {
+        ret = confdb_ldif_from_ini_file(tmp_ctx,
+                                        config_file,
+                                        config_dir,
+                                        init_data,
+                                        &timestr,
+                                        &config_ldif);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Cannot convert INI to LDIF [%d]: [%s]\n",
+                  ret, sss_strerror(ret));
+            goto done;
+        }
+    } else if (ret == ENOENT) {
+        ret = confdb_fallback_ldif(tmp_ctx, &timestr, &config_ldif);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Cannot create a fallback configuration [%d]: [%s]\n",
+                  ret, sss_strerror(ret));
+            goto done;
+        }
+    } else {
         DEBUG(SSSDBG_CONF_SETTINGS,
-              "sss_ini_config_file_open failed: %s [%d]\n", strerror(ret),
+              "sss_ini_config_file_open failed: %s [%d]\n", sss_strerror(ret),
                ret);
-        if (ret == ENOENT) {
-            /* sss specific error denoting missing configuration file */
-            ret = ERR_MISSING_CONF;
-        }
         goto done;
     }
 
-    ret = confdb_ldif_from_ini_file(tmp_ctx,
-                                    config_file,
-                                    config_dir,
-                                    init_data,
-                                    &timestr,
-                                    &config_ldif);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Cannot convert INI to LDIF [%d]: [%s]\n",
-              ret, sss_strerror(ret));
-        goto done;
-    }
     DEBUG(SSSDBG_CONF_SETTINGS, "LDIF file to import: \n%s\n", config_ldif);
 
 
diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py
index abf836b..8748ac1 100644
--- a/src/tests/intg/test_files_provider.py
+++ b/src/tests/intg/test_files_provider.py
@@ -167,6 +167,12 @@ def disabled_files_domain(request):
     return None
 
 
+@pytest.fixture
+def no_sssd_conf(request):
+    create_sssd_fixture(request)
+    return None
+
+
 def setup_pw_with_list(request, user_list):
     pwd_ops = passwd_ops_setup(request)
     for user in user_list:
@@ -832,3 +838,13 @@ def test_disable_files_domain(add_user_with_canary, disabled_files_domain):
     # The local user will not be resolvable through nss_sss now
     res, user = sssd_getpwnam_sync(USER1["name"])
     assert res != NssReturnCode.SUCCESS
+
+
+def test_no_sssd_conf(add_user_with_canary, no_sssd_conf):
+    """
+    Test that running without sssd.conf implicitly configures one with
+    id_provider=files
+    """
+    res, user = sssd_getpwnam_sync(USER1["name"])
+    assert res == NssReturnCode.SUCCESS
+    assert user == USER1
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to