From d010768a94e39082f75e81efdb3e791843c0ef03 Mon Sep 17 00:00:00 2001
From: Ondrej Kos <okos@redhat.com>
Date: Mon, 13 May 2013 15:52:00 +0200
Subject: [PATCH] Check NSCD configuration file

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

nscd.conf file is now checked for the presence of caching settings for
databases controlled by SSSD. Syslog warning is now written only if NSCD
is running with interfering configuration or if configuration file
couldn't be loaded.

New configure option added to support non-standard locations
--with-nscd-conf=PATH (defaultly set to /etc/nscd.conf)
---
 configure.ac          |  4 +++
 src/conf_macros.m4    | 12 ++++++++
 src/monitor/monitor.c | 29 ++++++++++++++----
 src/util/util.c       | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/util.h       |  2 ++
 5 files changed, 122 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index f90d7fee3632df74c843d0aaeb03e59eea3c2fee..435e3d613431e4dae89b4866e041e3f3b11bdff9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -166,6 +166,10 @@ fi
 
 WITH_LIBNL
 
+if test x$have_nscd; then
+    WITH_NSCD_CONF
+fi
+
 WITH_INITSCRIPT
 if test x$initscript = xsystemd; then
     WITH_SYSTEMD_UNIT_DIR
diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index 26eb4acccc4895e961ecc50d490a3cdd5716d085..1315fc9da8761a62402692ae6f272236955c2d1c 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -352,6 +352,18 @@ AC_DEFUN([WITH_NSCD],
     AC_DEFINE_UNQUOTED(HAVE_NSCD, $NSCD_PATH, [flush nscd cache after local domain operations])
   ])
 
+AC_DEFUN([WITH_NSCD_CONF],
+  [ AC_ARG_WITH([nscd_conf],
+                [AC_HELP_STRING([--with-nscd-conf=PATH],
+                                [Path to nscd.conf file [/etc/nscd.conf]])])
+    NSCD_CONF_PATH="/etc/nscd.conf"
+    if test x"$with_nscd_conf" != x; then
+        NSCD_CONF_PATH=$with_nscd_conf
+        AC_SUBST(NSCD_CONF_PATH)
+    fi
+    AC_DEFINE_UNQUOTED([NSCD_CONF_PATH], ["$NSCD_CONF_PATH"], [NSCD configuration file])
+  ])
+
 AC_DEFUN([WITH_SEMANAGE],
   [ AC_ARG_WITH([semanage],
                 [AC_HELP_STRING([--with-semanage],
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index bd22a951d3b48d0ea367e36f628b07e2783d469a..6a69a76fe49a4d6d19561b5d4ae5bed97932b396 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -2754,12 +2754,29 @@ int main(int argc, const char *argv[])
     /* Warn if nscd seems to be running */
     ret = check_file(NSCD_SOCKET_PATH, -1, -1, -1, CHECK_SOCK, NULL, false);
     if (ret == EOK) {
-        sss_log(SSS_LOG_NOTICE,
-                "nscd socket was detected.  Nscd caching capabilities "
-                "may conflict with SSSD for users and groups. It is "
-                "recommended not to run nscd in parallel with SSSD, unless "
-                "nscd is configured not to cache the passwd, group and "
-                "netgroup nsswitch maps.");
+        ret = sss_nscd_parse_conf();
+
+        switch (ret) {
+            case ENOENT:
+                sss_log(SSS_LOG_NOTICE,
+                        "NSCD socket was detected, but NSCD configuration "
+                        "file was not found in the specified path [%s] to "
+                        "perform  check of its caching settings.",
+                        NSCD_CONF_PATH);
+                break;
+            case EINVAL:
+                sss_log(SSS_LOG_NOTICE,
+                        "NSCD socket was detected and seems to be configured "
+                        "to cache some of the databases cached by "
+                        "SSSD [passwd,group,netgroup,services]. It is "
+                        "recommended not to run NSCD in parallel with SSSD,"
+                        "unless nscd is configured not to cache these.");
+                break;
+            case EOK:
+                DEBUG(SSSDBG_TRACE_FUNC, ("NSCD is running and it seems to "
+                            "be configured not to interfere with SSSD's "
+                            "caching capabilities\n"));
+        }
     }
 
     /* Parse config file, fail if cannot be done */
diff --git a/src/util/util.c b/src/util/util.c
index ba85e0da2a2e03784c5bb9abbbd038ddaeb3455c..8034ee63c632538af74ff7a3238f69cf914a6895 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -688,3 +688,84 @@ void safezero(void *data, size_t size)
         *p++ = 0;
     }
 }
+
+/* NSCD config file parse and check */
+
+#define NSCD_LINE_BUFF 120
+
+enum nscd_service_type {
+    NSCD_PASSWD = 0,
+    NSCD_GROUP,
+    NSCD_NETGROUP,
+    NSCD_SERVICES
+};
+
+unsigned int nscd_service_flag[4] = {
+    0x0001, /* passwd   */
+    0x0010, /* group    */
+    0x0100, /* netgroup */
+    0x1000  /* service  */
+};
+
+const char *svc_type_name[] = {
+    "passwd",
+    "group",
+    "netgroup",
+    "services"
+};
+
+unsigned int sss_nscd_check_service(char* svc_name)
+{
+    int i;
+
+    unsigned int ret = 0;
+
+    for (i = NSCD_PASSWD; i <= NSCD_SERVICES; i++) {
+        if (!strcmp(svc_type_name[i], svc_name)) {
+
+            ret |= nscd_service_flag[i];
+            break;
+        }
+    }
+
+    return ret;
+}
+
+errno_t sss_nscd_parse_conf(void)
+{
+    FILE *fp;
+    unsigned int occured = 0;
+    char line[NSCD_LINE_BUFF];
+    char part1[40], part2[40], part3[40];
+
+    fp = fopen(NSCD_CONF_PATH, "r");
+
+    if (fp == NULL) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Couldn't open NSCD configuration "
+                    "file [%s]\n", NSCD_CONF_PATH));
+        return ENOENT;
+    }
+
+    while (fgets(line, NSCD_LINE_BUFF, fp) != NULL) {
+
+        if (line[0] != '#') {
+
+            sscanf(line, "%s %s %s", part1, part2, part3);
+
+            if (!strcmp(part1, "enable-cache") &&
+                !strcmp(part3, "yes")) {
+
+                occured |= sss_nscd_check_service(part2);
+            }
+
+        }
+    }
+
+    fclose(fp);
+
+    if (occured != 0) {
+        return EINVAL;
+    }
+
+    return EOK;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 49dc850c36cedd83755034367357fab41bd32ec6..e28574d12c47e0e07bab15c10ffa4abf01b614ea 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -542,6 +542,8 @@ errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string,
 
 bool string_in_list(const char *string, char **list, bool case_sensitive);
 
+errno_t sss_nscd_parse_conf(void);
+
 /**
  * @brief Safely zero a segment of memory,
  *        prevents the compiler from optimizing out
-- 
1.8.1.4

