Blame SOURCES/0065-sss_override-support-import-and-export.patch

6cf099
From ee8f6d929ab3a047e05b4522cb0d61273293e2c4 Mon Sep 17 00:00:00 2001
6cf099
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
6cf099
Date: Wed, 19 Aug 2015 12:35:12 +0200
6cf099
Subject: [PATCH 65/66] sss_override: support import and export
6cf099
6cf099
Resolves:
6cf099
https://fedorahosted.org/sssd/ticket/2737
6cf099
6cf099
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
6cf099
---
6cf099
 Makefile.am                |   2 +
6cf099
 src/man/sss_override.8.xml |  88 +++++++
6cf099
 src/tools/sss_override.c   | 588 ++++++++++++++++++++++++++++++++++++++++++++-
6cf099
 3 files changed, 675 insertions(+), 3 deletions(-)
6cf099
6cf099
diff --git a/Makefile.am b/Makefile.am
6cf099
index 7dc4875c9cb05bf146505c0dc0dab543fb326bd3..e1102333b019e32c516c59c5fa969c970b688737 100644
6cf099
--- a/Makefile.am
6cf099
+++ b/Makefile.am
6cf099
@@ -651,6 +651,7 @@ dist_noinst_HEADERS = \
6cf099
     src/lib/sifp/sss_sifp_private.h \
6cf099
     src/tests/cmocka/test_utils.h \
6cf099
     src/tools/common/sss_tools.h \
6cf099
+    src/tools/common/sss_colondb.h \
6cf099
     $(NULL)
6cf099
 
6cf099
 
6cf099
@@ -1331,6 +1332,7 @@ sss_signal_LDADD = \
6cf099
 
6cf099
 sss_override_SOURCES = \
6cf099
     src/tools/sss_override.c \
6cf099
+    src/tools/common/sss_colondb.c \
6cf099
     $(SSSD_TOOLS_OBJ) \
6cf099
     $(NULL)
6cf099
 sss_override_LDADD = \
6cf099
diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml
6cf099
index ec9a7bb75c13f4f18ece7f5f84baede14a8a1e2e..d289f5b7dfa7fbd328831b4c71d45b4c555225cf 100644
6cf099
--- a/src/man/sss_override.8.xml
6cf099
+++ b/src/man/sss_override.8.xml
6cf099
@@ -77,6 +77,50 @@
6cf099
             </varlistentry>
6cf099
             <varlistentry>
6cf099
                 <term>
6cf099
+                    <option>user-import</option>
6cf099
+                    <emphasis>FILE</emphasis>
6cf099
+                </term>
6cf099
+                <listitem>
6cf099
+                    <para>
6cf099
+                        Import user overrides from <emphasis>FILE</emphasis>.
6cf099
+                        Data format is similar to standard passwd file.
6cf099
+                        The format is:
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        original_name:name:uid:gid:gecos:home:shell
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        where original_name is original name of the user whose
6cf099
+                        attributes should be overridden. The rest of fields
6cf099
+                        correspond to new values. You can omit a value simply
6cf099
+                        by leaving corresponding field empty.
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        Examples:
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        ckent:superman::::::
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        ckent@krypton.com::501:501:Superman:/home/earth:/bin/bash
6cf099
+                    </para>
6cf099
+                </listitem>
6cf099
+            </varlistentry>
6cf099
+            <varlistentry>
6cf099
+                <term>
6cf099
+                    <option>user-export</option>
6cf099
+                    <emphasis>FILE</emphasis>
6cf099
+                </term>
6cf099
+                <listitem>
6cf099
+                    <para>
6cf099
+                        Export all overridden attributes and store them in
6cf099
+                        <emphasis>FILE</emphasis>. See
6cf099
+                        <emphasis>user-import</emphasis> for data format.
6cf099
+                    </para>
6cf099
+                </listitem>
6cf099
+            </varlistentry>
6cf099
+            <varlistentry>
6cf099
+                <term>
6cf099
                     <option>group-add</option>
6cf099
                     <emphasis>NAME</emphasis>
6cf099
                     <optional><option>-n,--name</option> NAME</optional>
6cf099
@@ -99,6 +143,50 @@
6cf099
                     </para>
6cf099
                 </listitem>
6cf099
             </varlistentry>
6cf099
+            <varlistentry>
6cf099
+                <term>
6cf099
+                    <option>group-import</option>
6cf099
+                    <emphasis>FILE</emphasis>
6cf099
+                </term>
6cf099
+                <listitem>
6cf099
+                    <para>
6cf099
+                        Import group overrides from <emphasis>FILE</emphasis>.
6cf099
+                        Data format is similar to standard group file.
6cf099
+                        The format is:
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        original_name:name:gid
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        where original_name is original name of the group whose
6cf099
+                        attributes should be overridden. The rest of fields
6cf099
+                        correspond to new values. You can omit a value simply
6cf099
+                        by leaving corresponding field empty.
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        Examples:
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        admins:administrators:
6cf099
+                    </para>
6cf099
+                    <para>
6cf099
+                        Domain Users:Users:501
6cf099
+                    </para>
6cf099
+                </listitem>
6cf099
+            </varlistentry>
6cf099
+            <varlistentry>
6cf099
+                <term>
6cf099
+                    <option>group-export</option>
6cf099
+                    <emphasis>FILE</emphasis>
6cf099
+                </term>
6cf099
+                <listitem>
6cf099
+                    <para>
6cf099
+                        Export all overridden attributes and store them in
6cf099
+                        <emphasis>FILE</emphasis>. See
6cf099
+                        <emphasis>group-import</emphasis> for data format.
6cf099
+                    </para>
6cf099
+                </listitem>
6cf099
+            </varlistentry>
6cf099
         </variablelist>
6cf099
     </refsect1>
6cf099
 
6cf099
diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
6cf099
index 9e2ce3325c0bfa33fadb970f725098d7d12ac432..ee8351ea97e5efe0d449dc646c6136b32ceec2c6 100644
6cf099
--- a/src/tools/sss_override.c
6cf099
+++ b/src/tools/sss_override.c
6cf099
@@ -23,8 +23,10 @@
6cf099
 #include "util/util.h"
6cf099
 #include "db/sysdb.h"
6cf099
 #include "tools/common/sss_tools.h"
6cf099
+#include "tools/common/sss_colondb.h"
6cf099
 
6cf099
 #define LOCALVIEW SYSDB_LOCAL_VIEW_NAME
6cf099
+#define ORIGNAME "originalName"
6cf099
 
6cf099
 struct override_user {
6cf099
     const char *input_name;
6cf099
@@ -135,6 +137,40 @@ static int parse_cmdline_group_del(struct sss_cmdline *cmdline,
6cf099
                          &group->orig_name, &group->domain);
6cf099
 }
6cf099
 
6cf099
+static int parse_cmdline_import(struct sss_cmdline *cmdline,
6cf099
+                                struct sss_tool_ctx *tool_ctx,
6cf099
+                                const char **_file)
6cf099
+{
6cf099
+    int ret;
6cf099
+
6cf099
+    ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
6cf099
+                           NULL, NULL, "FILE", "File to import the data from.",
6cf099
+                           _file);
6cf099
+    if (ret != EXIT_SUCCESS) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
6cf099
+        return ret;
6cf099
+    }
6cf099
+
6cf099
+    return EXIT_SUCCESS;
6cf099
+}
6cf099
+
6cf099
+static int parse_cmdline_export(struct sss_cmdline *cmdline,
6cf099
+                                struct sss_tool_ctx *tool_ctx,
6cf099
+                                const char **_file)
6cf099
+{
6cf099
+    int ret;
6cf099
+
6cf099
+    ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
6cf099
+                           NULL, NULL, "FILE", "File to export the data to.",
6cf099
+                           _file);
6cf099
+    if (ret != EXIT_SUCCESS) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
6cf099
+        return ret;
6cf099
+    }
6cf099
+
6cf099
+    return EXIT_SUCCESS;
6cf099
+}
6cf099
+
6cf099
 static errno_t prepare_view(struct sss_domain_info *domain)
6cf099
 {
6cf099
     char *viewname = NULL;
6cf099
@@ -293,8 +329,8 @@ static char *get_fqname(TALLOC_CTX *mem_ctx,
6cf099
                         const char *name)
6cf099
 {
6cf099
     char *fqname;
6cf099
-    size_t fqlen;
6cf099
-    size_t check;
6cf099
+    int fqlen;
6cf099
+    int check;
6cf099
 
6cf099
     if (domain == NULL) {
6cf099
         return NULL;
6cf099
@@ -315,7 +351,7 @@ static char *get_fqname(TALLOC_CTX *mem_ctx,
6cf099
     }
6cf099
 
6cf099
     check = sss_fqname(fqname, fqlen, domain->names, domain, name);
6cf099
-    if (check != fqlen - 1) {
6cf099
+    if (check < 0 || check != fqlen - 1) {
6cf099
         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name "
6cf099
               "for user [%s] in [%s]! Skipping user.\n", name, domain->name);
6cf099
         talloc_free(fqname);
6cf099
@@ -724,6 +760,246 @@ done:
6cf099
     return ret;
6cf099
 }
6cf099
 
6cf099
+static errno_t append_name(struct sss_domain_info *domain,
6cf099
+                           struct ldb_message *override)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
6cf099
+    struct ldb_dn *dn;
6cf099
+    struct ldb_message **msgs;
6cf099
+    const char *attrs[] = {SYSDB_NAME, NULL};
6cf099
+    const char *name;
6cf099
+    const char *fqname;
6cf099
+    size_t count;
6cf099
+    errno_t ret;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return ENOMEM;
6cf099
+    }
6cf099
+
6cf099
+    dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, override,
6cf099
+                                 SYSDB_OVERRIDE_OBJECT_DN);
6cf099
+    if (dn == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Missing overrideObjectDN?\n");
6cf099
+        ret = ERR_INTERNAL;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE,
6cf099
+                             NULL, attrs, &count, &msgs);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
6cf099
+              ret, sss_strerror(ret));
6cf099
+        goto done;
6cf099
+    } else if (count != 1) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "More than one user found?\n");
6cf099
+        ret = ERR_INTERNAL;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
6cf099
+    if (name == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Object with no name?\n");
6cf099
+        ret = ERR_INTERNAL;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    fqname = get_fqname(tmp_ctx, domain, name);
6cf099
+    if (fqname == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get fqname\n");
6cf099
+        ret = ENOMEM;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    ret = ldb_msg_add_string(override, ORIGNAME, fqname);
6cf099
+    if (ret != LDB_SUCCESS) {
6cf099
+        ret = sysdb_error_to_errno(ret);
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute to msg\n");
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    talloc_steal(override, fqname);
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+
6cf099
+    return ret;
6cf099
+}
6cf099
+
6cf099
+static errno_t list_overrides(TALLOC_CTX *mem_ctx,
6cf099
+                              const char *filter,
6cf099
+                              const char **attrs,
6cf099
+                              struct sss_domain_info *domain,
6cf099
+                              size_t *_count,
6cf099
+                              struct ldb_message ***_msgs)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct ldb_dn *dn;
6cf099
+    struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
6cf099
+    size_t count;
6cf099
+    struct ldb_message **msgs;
6cf099
+    size_t i;
6cf099
+    int ret;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return ENOMEM;
6cf099
+    }
6cf099
+
6cf099
+    /* Acquire list of override objects. */
6cf099
+    dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_VIEW_SEARCH_BASE, LOCALVIEW);
6cf099
+    if (dn == NULL) {
6cf099
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt() failed.\n");
6cf099
+        ret = EIO;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_SUBTREE,
6cf099
+                             filter, attrs, &count, &msgs);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
6cf099
+              ret, sss_strerror(ret));
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    /* Amend messages with original name. */
6cf099
+    for (i = 0; i < count; i++) {
6cf099
+        ret = append_name(domain, msgs[i]);
6cf099
+        if (ret != EOK) {
6cf099
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to append name [%d]: %s\n",
6cf099
+                  ret, sss_strerror(ret));
6cf099
+            goto done;
6cf099
+        }
6cf099
+    }
6cf099
+
6cf099
+    *_msgs = talloc_steal(mem_ctx, msgs);
6cf099
+    *_count = count;
6cf099
+
6cf099
+    ret = EOK;
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+
6cf099
+    return ret;
6cf099
+}
6cf099
+
6cf099
+static struct override_user *
6cf099
+list_user_overrides(TALLOC_CTX *mem_ctx,
6cf099
+                    struct sss_domain_info *domain)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct override_user *objs;
6cf099
+    struct ldb_message **msgs;
6cf099
+    size_t count;
6cf099
+    size_t i;
6cf099
+    errno_t ret;
6cf099
+    const char *attrs[] = SYSDB_PW_ATTRS;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return NULL;
6cf099
+    }
6cf099
+
6cf099
+    ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_USER_CLASS ")",
6cf099
+                         attrs, domain, &count, &msgs);
6cf099
+    if (ret != EOK) {
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    objs = talloc_zero_array(tmp_ctx, struct override_user, count + 1);
6cf099
+    if (objs == NULL) {
6cf099
+        ret = ENOMEM;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    for (i = 0; i < count; i++) {
6cf099
+        objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
6cf099
+                                                        NULL);
6cf099
+        if (objs[i].orig_name == NULL) {
6cf099
+            DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
6cf099
+            ret = ERR_INTERNAL;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
6cf099
+        objs[i].uid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_UIDNUM, 0);
6cf099
+        objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
6cf099
+        objs[i].home = ldb_msg_find_attr_as_string(msgs[i], SYSDB_HOMEDIR, NULL);
6cf099
+        objs[i].shell = ldb_msg_find_attr_as_string(msgs[i], SYSDB_SHELL, NULL);
6cf099
+        objs[i].gecos = ldb_msg_find_attr_as_string(msgs[i], SYSDB_GECOS, NULL);
6cf099
+    }
6cf099
+
6cf099
+    talloc_steal(mem_ctx, objs);
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+
6cf099
+    if (ret != EOK) {
6cf099
+        return NULL;
6cf099
+    }
6cf099
+
6cf099
+    return objs;
6cf099
+}
6cf099
+
6cf099
+static struct override_group *
6cf099
+list_group_overrides(TALLOC_CTX *mem_ctx,
6cf099
+                     struct sss_domain_info *domain)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct override_group *objs;
6cf099
+    struct ldb_message **msgs;
6cf099
+    size_t count;
6cf099
+    size_t i;
6cf099
+    errno_t ret;
6cf099
+    const char *attrs[] = SYSDB_GRSRC_ATTRS;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return NULL;
6cf099
+    }
6cf099
+
6cf099
+    ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_GROUP_CLASS ")",
6cf099
+                         attrs, domain, &count, &msgs);
6cf099
+    if (ret != EOK) {
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    objs = talloc_zero_array(tmp_ctx, struct override_group, count + 1);
6cf099
+    if (objs == NULL) {
6cf099
+        ret = ENOMEM;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    for (i = 0; i < count; i++) {
6cf099
+        objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
6cf099
+                                                        NULL);
6cf099
+        if (objs[i].orig_name == NULL) {
6cf099
+            DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
6cf099
+            ret = ERR_INTERNAL;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
6cf099
+        objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
6cf099
+    }
6cf099
+
6cf099
+    talloc_steal(mem_ctx, objs);
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+
6cf099
+    if (ret != EOK) {
6cf099
+        return NULL;
6cf099
+    }
6cf099
+
6cf099
+    return objs;
6cf099
+}
6cf099
+
6cf099
 static int override_user_add(struct sss_cmdline *cmdline,
6cf099
                              struct sss_tool_ctx *tool_ctx,
6cf099
                              void *pvt)
6cf099
@@ -777,6 +1053,161 @@ static int override_user_del(struct sss_cmdline *cmdline,
6cf099
     return EXIT_SUCCESS;
6cf099
 }
6cf099
 
6cf099
+static int override_user_import(struct sss_cmdline *cmdline,
6cf099
+                                struct sss_tool_ctx *tool_ctx,
6cf099
+                                void *pvt)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct sss_colondb *db;
6cf099
+    const char *filename;
6cf099
+    struct override_user obj;
6cf099
+    int linenum = 1;
6cf099
+    errno_t ret;
6cf099
+    int exit;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return EXIT_FAILURE;
6cf099
+    }
6cf099
+
6cf099
+    /**
6cf099
+     * Format: orig_name:name:uid:gid:gecos:home:shell
6cf099
+     */
6cf099
+    struct sss_colondb_read_field table[] = {
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.input_name}},
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.name}},
6cf099
+        {SSS_COLONDB_UINT32, {.uint32 = &obj.uid}},
6cf099
+        {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.gecos}},
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.home}},
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.shell}},
6cf099
+        {SSS_COLONDB_SENTINEL, {0}}
6cf099
+    };
6cf099
+
6cf099
+    ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
6cf099
+    if (db == NULL) {
6cf099
+        fprintf(stderr, _("Unable to open %s.\n"), filename);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
6cf099
+        linenum++;
6cf099
+
6cf099
+        ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
6cf099
+                                  &obj.orig_name, &obj.domain);
6cf099
+        if (ret != EOK) {
6cf099
+            fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        ret = get_user_domain_msg(tool_ctx, &obj);
6cf099
+        if (ret != EOK) {
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        ret = override_user(tool_ctx, &obj);
6cf099
+        if (ret != EOK) {
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        talloc_free_children(tmp_ctx);
6cf099
+    }
6cf099
+
6cf099
+    if (ret != EOF) {
6cf099
+        fprintf(stderr, _("Invalid format on line %d. "
6cf099
+                "Use --debug option for more information.\n"), linenum);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    exit = EXIT_SUCCESS;
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+    return exit;
6cf099
+}
6cf099
+
6cf099
+static int override_user_export(struct sss_cmdline *cmdline,
6cf099
+                                struct sss_tool_ctx *tool_ctx,
6cf099
+                                void *pvt)
6cf099
+{
6cf099
+    struct sss_colondb *db;
6cf099
+    const char *filename;
6cf099
+    struct override_user *objs;
6cf099
+    struct sss_domain_info *dom;
6cf099
+    errno_t ret;
6cf099
+    int exit;
6cf099
+    int i;
6cf099
+
6cf099
+    ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
6cf099
+    if (db == NULL) {
6cf099
+        fprintf(stderr, _("Unable to open %s.\n"), filename);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    dom = tool_ctx->domains;
6cf099
+    do {
6cf099
+        objs = list_user_overrides(tool_ctx, tool_ctx->domains);
6cf099
+        if (objs == NULL) {
6cf099
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        for (i = 0; objs[i].orig_name != NULL; i++) {
6cf099
+            /**
6cf099
+             * Format: orig_name:name:uid:gid:gecos:home:shell
6cf099
+             */
6cf099
+            struct sss_colondb_write_field table[] = {
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].name}},
6cf099
+                {SSS_COLONDB_UINT32, {.uint32 = objs[i].uid}},
6cf099
+                {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].gecos}},
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].home}},
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].shell}},
6cf099
+                {SSS_COLONDB_SENTINEL, {0}}
6cf099
+            };
6cf099
+
6cf099
+            ret = sss_colondb_writeline(db, table);
6cf099
+            if (ret != EOK) {
6cf099
+                DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
6cf099
+                exit = EXIT_FAILURE;
6cf099
+                goto done;
6cf099
+            }
6cf099
+        }
6cf099
+
6cf099
+        /* All overrides are under the same subtree, so we don't want to
6cf099
+         * descent into subdomains. */
6cf099
+        dom = get_next_domain(dom, false);
6cf099
+    } while (dom != NULL);
6cf099
+
6cf099
+    exit = EXIT_SUCCESS;
6cf099
+
6cf099
+done:
6cf099
+    return exit;
6cf099
+}
6cf099
+
6cf099
 static int override_group_add(struct sss_cmdline *cmdline,
6cf099
                               struct sss_tool_ctx *tool_ctx,
6cf099
                               void *pvt)
6cf099
@@ -831,13 +1262,164 @@ static int override_group_del(struct sss_cmdline *cmdline,
6cf099
     return EXIT_SUCCESS;
6cf099
 }
6cf099
 
6cf099
+static int override_group_import(struct sss_cmdline *cmdline,
6cf099
+                                 struct sss_tool_ctx *tool_ctx,
6cf099
+                                 void *pvt)
6cf099
+{
6cf099
+    TALLOC_CTX *tmp_ctx;
6cf099
+    struct sss_colondb *db;
6cf099
+    const char *filename;
6cf099
+    struct override_group obj;
6cf099
+    int linenum = 1;
6cf099
+    errno_t ret;
6cf099
+    int exit;
6cf099
+
6cf099
+    tmp_ctx = talloc_new(NULL);
6cf099
+    if (tmp_ctx == NULL) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
6cf099
+        return EXIT_FAILURE;
6cf099
+    }
6cf099
+
6cf099
+    /**
6cf099
+     * Format: orig_name:name:gid
6cf099
+     */
6cf099
+    struct sss_colondb_read_field table[] = {
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.input_name}},
6cf099
+        {SSS_COLONDB_STRING, {.str = &obj.name}},
6cf099
+        {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
6cf099
+        {SSS_COLONDB_SENTINEL, {0}}
6cf099
+    };
6cf099
+
6cf099
+    ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
6cf099
+    if (db == NULL) {
6cf099
+        fprintf(stderr, _("Unable to open %s.\n"), filename);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
6cf099
+        linenum++;
6cf099
+
6cf099
+        ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
6cf099
+                                  &obj.orig_name, &obj.domain);
6cf099
+        if (ret != EOK) {
6cf099
+            fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        ret = get_group_domain_msg(tool_ctx, &obj);
6cf099
+        if (ret != EOK) {
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        ret = override_group(tool_ctx, &obj);
6cf099
+        if (ret != EOK) {
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        talloc_free_children(tmp_ctx);
6cf099
+    }
6cf099
+
6cf099
+    if (ret != EOF) {
6cf099
+        fprintf(stderr, _("Invalid format on line %d. "
6cf099
+                "Use --debug option for more information.\n"), linenum);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    exit = EXIT_SUCCESS;
6cf099
+
6cf099
+done:
6cf099
+    talloc_free(tmp_ctx);
6cf099
+    return exit;
6cf099
+}
6cf099
+
6cf099
+static int override_group_export(struct sss_cmdline *cmdline,
6cf099
+                                 struct sss_tool_ctx *tool_ctx,
6cf099
+                                 void *pvt)
6cf099
+{
6cf099
+    struct sss_colondb *db;
6cf099
+    const char *filename;
6cf099
+    struct override_group *objs;
6cf099
+    struct sss_domain_info *dom;
6cf099
+    errno_t ret;
6cf099
+    int exit;
6cf099
+    int i;
6cf099
+
6cf099
+    ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
6cf099
+    if (ret != EOK) {
6cf099
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
6cf099
+    if (db == NULL) {
6cf099
+        fprintf(stderr, _("Unable to open %s.\n"), filename);
6cf099
+        exit = EXIT_FAILURE;
6cf099
+        goto done;
6cf099
+    }
6cf099
+
6cf099
+    dom = tool_ctx->domains;
6cf099
+    do {
6cf099
+        objs = list_group_overrides(tool_ctx, tool_ctx->domains);
6cf099
+        if (objs == NULL) {
6cf099
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
6cf099
+            exit = EXIT_FAILURE;
6cf099
+            goto done;
6cf099
+        }
6cf099
+
6cf099
+        for (i = 0; objs[i].orig_name != NULL; i++) {
6cf099
+            /**
6cf099
+             * Format: orig_name:name:uid:gid:gecos:home:shell
6cf099
+             */
6cf099
+            struct sss_colondb_write_field table[] = {
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
6cf099
+                {SSS_COLONDB_STRING, {.str = objs[i].name}},
6cf099
+                {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
6cf099
+                {SSS_COLONDB_SENTINEL, {0}}
6cf099
+            };
6cf099
+
6cf099
+            ret = sss_colondb_writeline(db, table);
6cf099
+            if (ret != EOK) {
6cf099
+                DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
6cf099
+                exit = EXIT_FAILURE;
6cf099
+                goto done;
6cf099
+            }
6cf099
+        }
6cf099
+
6cf099
+        /* All overrides are under the same subtree, so we don't want to
6cf099
+         * descent into subdomains. */
6cf099
+        dom = get_next_domain(dom, false);
6cf099
+    } while (dom != NULL);
6cf099
+
6cf099
+    exit = EXIT_SUCCESS;
6cf099
+
6cf099
+done:
6cf099
+    return exit;
6cf099
+}
6cf099
+
6cf099
 int main(int argc, const char **argv)
6cf099
 {
6cf099
     struct sss_route_cmd commands[] = {
6cf099
         {"user-add", override_user_add},
6cf099
         {"user-del", override_user_del},
6cf099
+        {"user-import", override_user_import},
6cf099
+        {"user-export", override_user_export},
6cf099
         {"group-add", override_group_add},
6cf099
         {"group-del", override_group_del},
6cf099
+        {"group-import", override_group_import},
6cf099
+        {"group-export", override_group_export},
6cf099
         {NULL, NULL}
6cf099
     };
6cf099
 
6cf099
-- 
6cf099
2.4.3
6cf099