From 0c19acefc4d2bb56cf5469cd304c000528a11674 Mon Sep 17 00:00:00 2001
From: Ondrej Kos <okos@redhat.com>
Date: Thu, 28 Mar 2013 15:35:03 +0100
Subject: [PATCH] DB: Switch to new libini_config API

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

Since we need to support the old interface as well, the configure scritp
is modified and correct ini interface is chosen.
---
 src/confdb/confdb_setup.c           | 219 ++++++++++++++++++++++++++++++------
 src/external/libini_config.m4       |  26 +++--
 src/monitor/monitor.c               |   2 +
 src/responder/nss/nsssrv_netgroup.c |   3 +
 src/responder/nss/nsssrv_services.c |   4 +-
 5 files changed, 209 insertions(+), 45 deletions(-)

diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c
index 6c68461faf1e14270a03dc979c4b9c21c0374af2..faa5e4c151a2a2644d763487db8e1191318f4263 100644
--- a/src/confdb/confdb_setup.c
+++ b/src/confdb/confdb_setup.c
@@ -26,10 +26,39 @@
 #include "confdb.h"
 #include "confdb_private.h"
 #include "confdb_setup.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V1
+#include "ini_configobj.h"
+#endif
+#include "ini_config.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V0
 #include "collection.h"
 #include "collection_tools.h"
-#include "ini_config.h"
+#endif
 
+#ifdef HAVE_LIBINI_CONFIG_V1
+
+#define iniw_get_sec_list                   ini_get_section_list
+#define iniw_get_attr_list                  ini_get_attribute_list
+#define iniw_get_const_string_config_value  ini_get_const_string_config_value
+#define iniw_get_int_config_value           ini_get_int_config_value
+#define iniw_close();
+#define iniw_config_destroy(cfg);           ini_config_destroy(cfg);
+#define iniw_get_config_obj                 ini_get_config_valueobj
+
+#elif HAVE_LIBINI_CONFIG_V0
+
+#define iniw_get_sec_list                   get_section_list
+#define iniw_get_attr_list                  get_attribute_list
+#define iniw_get_const_string_config_value  get_const_string_config_value
+#define iniw_get_int_config_value           get_int_config_value
+#define iniw_close();                       close(fd);
+#define iniw_config_destroy(cfg);
+#define iniw_get_config_obj(secs,attrs,cfg,flag,attr) \
+    get_config_item(secs,attrs,cfg,attr)
+
+#endif
 
 int confdb_test(struct confdb_ctx *cdb)
 {
@@ -126,9 +155,15 @@ int confdb_create_base(struct confdb_ctx *cdb)
     return EOK;
 }
 
+#ifdef HAVE_LIBINI_CONFIG_V1
+static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
+                              struct ini_cfgobj *sssd_config,
+                              const char **config_ldif)
+#elif HAVE_LIBINI_CONFIG_V0
 static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
                               struct collection_item *sssd_config,
                               const char **config_ldif)
+#endif
 {
     int ret, i, j;
     char *ldif;
@@ -141,11 +176,15 @@ static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
     char **attrs;
     int attr_count;
     char *ldif_attr;
-    struct collection_item *attr;
     TALLOC_CTX *tmp_ctx;
     size_t dn_size;
     size_t ldif_len;
     size_t attr_len;
+#ifdef HAVE_LIBINI_CONFIG_V1
+    struct value_obj *obj = NULL;
+#elif HAVE_LIBINI_CONFIG_V0
+    struct collection_item *obj = NULL;
+#endif
 
     ldif_len = strlen(CONFDB_INTERNAL_LDIF);
     ldif = talloc_array(mem_ctx, char, ldif_len+1);
@@ -161,7 +200,7 @@ static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
 
     /* Read in the collection and convert it to an LDIF */
     /* Get the list of sections */
-    sections = get_section_list(sssd_config, &section_count, &ret);
+    sections = iniw_get_sec_list(sssd_config, &section_count, &ret);
     if (ret != EOK) {
         goto error;
     }
@@ -186,7 +225,7 @@ static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
         dn_size = strlen(dn);
 
         /* Get all of the attributes and their values as LDIF */
-        attrs = get_attribute_list(sssd_config, sections[i],
+        attrs = iniw_get_attr_list(sssd_config, sections[i],
                                    &attr_count, &ret);
         if (ret != EOK) {
             free_section_list(sections);
@@ -195,11 +234,11 @@ static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
 
         for(j = 0; j < attr_count; j++) {
             DEBUG(6, ("Processing attribute [%s]\n", attrs[j]));
-            ret = get_config_item(sections[i], attrs[j], sssd_config,
-                                   &attr);
+            ret = iniw_get_config_obj(sections[i], attrs[j], sssd_config,
+                                      INI_GET_FIRST_VALUE, &obj);
             if (ret != EOK) goto error;
 
-            const char *value = get_const_string_config_value(attr, &ret);
+            const char *value = iniw_get_const_string_config_value(obj, &ret);
             if (ret != EOK) goto error;
             if (value && value[0] == '\0') {
                 DEBUG(1, ("Attribute '%s' has empty value, ignoring\n", attrs[j]));
@@ -272,20 +311,113 @@ error:
 int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
 {
     int ret;
-    int fd = -1;
-    struct collection_item *sssd_config = NULL;
-    struct collection_item *error_list = NULL;
-    struct collection_item *item = NULL;
     const char *config_ldif;
     struct ldb_ldif *ldif;
     TALLOC_CTX *tmp_ctx;
-    char *lasttimestr, timestr[21];
+    char timestr[21];
     const char *vals[2] = { timestr, NULL };
-    struct stat cstat;
     int version;
+#ifdef HAVE_LIBINI_CONFIG_V1
+    char **error_list = NULL;
+    struct ini_cfgobj *sssd_config = NULL;
+    struct value_obj *obj = NULL;
+    const struct stat *cstat;
+    struct ini_cfgfile *file_ctx = NULL;
+#elif HAVE_LIBINI_CONFIG_V0
+    struct collection_item *error_list = NULL;
+    struct collection_item *sssd_config = NULL;
+    struct collection_item *obj = NULL;
+    struct stat cstat;
+    char *lasttimestr;
+    int fd = -1;
+#endif
 
     tmp_ctx = talloc_new(cdb);
-    if (tmp_ctx == NULL) return ENOMEM;
+    if (tmp_ctx == NULL) {
+        DEBUG(0, ("Out of memory.\n"));
+        return ENOMEM;
+    }
+
+#ifdef HAVE_LIBINI_CONFIG_V1
+
+    /* Open config file */
+    ret = ini_config_file_open(config_file,
+                               INI_META_STATS,
+                               &file_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to open configuration file.\n"));
+        return EIO;
+    }
+
+    /* Check permissions */
+    ret = ini_config_access_check(file_ctx,
+                                  INI_ACCESS_CHECK_MODE |
+                                  INI_ACCESS_CHECK_UID |
+                                  INI_ACCESS_CHECK_GID,
+                                  0, /* owned by root */
+                                  0, /* owned by root */
+                                  (S_IRUSR|S_IWUSR), /* rw------- */
+                                  0); /* check all there parts */
+    if (ret != EOK) {
+        DEBUG(1, ("Permission check on config file failed.\n"));
+        ini_config_file_destroy(file_ctx);
+        return EPERM;
+    }
+
+    /* Determine if the conf file has changed since we last updated
+     * the confdb
+     */
+    cstat = ini_config_get_stat(file_ctx);
+    if (!cstat) {
+        DEBUG(0, ("No stat data though stat collection wasrequested.\n"));
+        ini_config_file_destroy(file_ctx);
+        return errno;
+    }
+
+    errno = 0;
+    ret = snprintf(timestr, 21, "%llu", (long long unsigned)cstat->st_mtime);
+    if (ret <= 0 || ret >= 21) {
+        DEBUG(0, ("Failed to convert time_t to string ??\n"));
+        ini_config_file_destroy(file_ctx);
+        return errno ? errno : EFAULT;
+    }
+
+    /* Create config object */
+    ret = ini_config_create(&sssd_config);
+    if (ret != EOK) {
+        DEBUG(0, ("Failed to create config object. Error %d.\n", ret));
+        ini_config_file_destroy(file_ctx);
+        talloc_zfree(tmp_ctx);
+        return ret;
+    }
+
+    /* Parse file */
+    ret = ini_config_parse(file_ctx,
+                           INI_STOP_ON_ANY,
+                           0, /* <- check that you really want this */
+                           0,
+                           sssd_config);
+
+    if (ret != EOK) {
+        DEBUG(0, ("Failed to parse configuration. Error %d.\n", ret));
+
+        if (ini_config_error_count(sssd_config)) {
+            DEBUG(0, ("Errors detected while parsing: %s\n",
+                      ini_config_get_filename(file_ctx));
+            ini_config_get_errors(sssd_config, &error_list);
+            ini_config_print_errors(stderr, error_list));
+            ini_config_free_errors(error_list);
+        }
+        ini_config_file_destroy(file_ctx);
+        ini_config_destroy(sssd_config);
+        talloc_zfree(tmp_ctx);
+        return ret;
+    }
+
+    /* We do not need file context any more */
+    ini_config_file_destroy(file_ctx);
+
+#elif HAVE_LIBINI_CONFIG_V0
 
     ret = check_and_open_readonly(config_file, &fd, 0, 0, (S_IRUSR|S_IWUSR),
                                   CHECK_REG);
@@ -306,6 +438,7 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
         talloc_zfree(tmp_ctx);
         return errno;
     }
+
     ret = snprintf(timestr, 21, "%llu", (long long unsigned)cstat.st_mtime);
     if (ret <= 0 || ret >= 21) {
         DEBUG(0, ("Failed to convert time_t to string ??\n"));
@@ -315,32 +448,19 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
     }
 
     /* check if we need to re-init the db */
-    ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate", NULL, &lasttimestr);
-    if (ret == EOK && lasttimestr != NULL) {
+    ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate",
+                            NULL, &lasttimestr);
+    if (ret == EOK) {
 
         /* now check if we lastUpdate and last file modification change differ*/
-        if (strcmp(lasttimestr, timestr) == 0) {
+        if ((lasttimestr != NULL) && (strcmp(lasttimestr, timestr) == 0)) {
             /* not changed, get out, nothing more to do */
             close(fd);
             talloc_zfree(tmp_ctx);
             return EOK;
         }
-    }
-
-    /* Set up a transaction to replace the configuration */
-    ret = ldb_transaction_start(cdb->ldb);
-    if (ret != LDB_SUCCESS) {
-        DEBUG(0, ("Failed to start a transaction for updating the configuration\n"));
-        talloc_zfree(tmp_ctx);
-        close(fd);
-        return sysdb_error_to_errno(ret);
-    }
-
-    /* Purge existing database */
-    ret = confdb_purge(cdb);
-    if (ret != EOK) {
-        DEBUG(0, ("Could not purge existing configuration\n"));
-        close(fd);
+    } else {
+        DEBUG(0, ("Failed to get lastUpdate attribute.\n"));
         goto done;
     }
 
@@ -357,37 +477,62 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
         goto done;
     }
 
+#endif
+
     /* Make sure that the config file version matches the confdb version */
-    ret = get_config_item("sssd", "config_file_version",
-                          sssd_config, &item);
+    ret = iniw_get_config_obj("sssd", "config_file_version",
+                              sssd_config, INI_GET_FIRST_VALUE, &obj);
     if (ret != EOK) {
         DEBUG(0, ("Internal error determining config_file_version\n"));
         goto done;
     }
-    if (item == NULL) {
+    if (obj == NULL) {
         /* No known version. Assumed to be version 1 */
         DEBUG(0, ("Config file is an old version. "
                   "Please run configuration upgrade script.\n"));
         ret = EINVAL;
         goto done;
     }
-    version = get_int_config_value(item, 1, -1, &ret);
+
+    version = iniw_get_int_config_value(obj, 1, -1, &ret);
     if (ret != EOK) {
         DEBUG(0, ("Config file version could not be determined\n"));
+        iniw_config_destroy(sssd_config);
         goto done;
     } else if (version < CONFDB_VERSION_INT) {
         DEBUG(0, ("Config file is an old version. "
                   "Please run configuration upgrade script.\n"));
+        iniw_config_destroy(sssd_config);
         ret = EINVAL;
         goto done;
     } else if (version > CONFDB_VERSION_INT) {
         DEBUG(0, ("Config file version is newer than confdb\n"));
+        iniw_config_destroy(sssd_config);
         ret = EINVAL;
         goto done;
     }
 
+    /* Set up a transaction to replace the configuration */
+    ret = ldb_transaction_start(cdb->ldb);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(0, ("Failed to start a transaction for updating the configuration\n"));
+        talloc_zfree(tmp_ctx);
+        iniw_close();
+        return sysdb_error_to_errno(ret);
+    }
+
+    /* Purge existing database */
+    ret = confdb_purge(cdb);
+    if (ret != EOK) {
+        DEBUG(0, ("Could not purge existing configuration\n"));
+        iniw_close();
+        goto done;
+    }
+
     ret = confdb_create_ldif(tmp_ctx, sssd_config, &config_ldif);
+#ifdef HAVE_LIBINI_CONFIG_V0
     free_ini_config(sssd_config);
+#endif
     if (ret != EOK) {
         DEBUG(0, ("Could not create LDIF for confdb\n"));
         goto done;
diff --git a/src/external/libini_config.m4 b/src/external/libini_config.m4
index f41f31917d1cf12dda49ec2e1f2411e39dbcc759..fc2c2a4456e05b7fb1354eb96fe124192f411d85 100644
--- a/src/external/libini_config.m4
+++ b/src/external/libini_config.m4
@@ -1,10 +1,22 @@
+PKG_CHECK_MODULES(INI_CONFIG, [
+    ini_config >= 1.0.0], [
+
+        HAVE_LIBINI_CONFIG_V1=1
+        AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V1, 1, [libini_config version greater than 1.0.0])
+    ], [
+        AC_MSG_WARN([libini_config-devel >= 1.0.0 not available, trying older version])
+        PKG_CHECK_MODULES(INI_CONFIG, [
+            ini_config >= 0.6.1], [
+
+                HAVE_LIBINI_CONFIG_V0=1
+                AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V0, 1, [libini_config version lesser than 1.0.0])
+            ], [
+                AC_MSG_ERROR([Please install libini_config-devel])
+            ]
+        )
+    ]
+)
+
 AC_SUBST(INI_CONFIG_OBJ)
 AC_SUBST(INI_CONFIG_CFLAGS)
 AC_SUBST(INI_CONFIG_LIBS)
-
-PKG_CHECK_MODULES(INI_CONFIG,
-    ini_config >= 0.6.1,
-    ,
-    AC_MSG_ERROR("Please install libini_config-devel")
-    )
-
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index c7d6d3e1f41ec42699b3a6225c16efeceac0b452..869df43a0a21885e8a27b0c9b45d94c979fa528b 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -44,8 +44,10 @@
 #include "tevent.h"
 #include "confdb/confdb.h"
 #include "confdb/confdb_setup.h"
+#ifdef HAVE_LIBINI_CONFIG_V0
 #include "collection.h"
 #include "ini_config.h"
+#endif
 #include "db/sysdb.h"
 #include "monitor/monitor.h"
 #include "dbus/dbus.h"
diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c
index 30459beaa9f9b98aab5d29c81fbc9a195e071bff..edda47587d0155407ab79c74f54acf06753ebff5 100644
--- a/src/responder/nss/nsssrv_netgroup.c
+++ b/src/responder/nss/nsssrv_netgroup.c
@@ -22,7 +22,10 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#ifdef HAVE_LIBINI_CONFIG_V0
 #include <collection.h>
+#endif
+
 #include "util/util.h"
 #include "responder/nss/nsssrv.h"
 #include "responder/nss/nsssrv_private.h"
diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c
index 7b76cad86e28a7f091833295659836289e351099..c9a33875e9a7349f9eed50e8ce3d13a03a3e5723 100644
--- a/src/responder/nss/nsssrv_services.c
+++ b/src/responder/nss/nsssrv_services.c
@@ -20,8 +20,10 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-
+#ifdef HAVE_LIBINI_CONFIG_V0
 #include <collection.h>
+#endif
+
 #include <arpa/inet.h>
 #include "util/util.h"
 #include "responder/nss/nsssrv.h"
-- 
1.8.1.4

