[SSSD] [PATCHES] Initial refactoring for #1747

Jakub Hrozek jhrozek at redhat.com
Sun Jan 13 22:30:16 UTC 2013


On Fri, Jan 11, 2013 at 10:46:57AM -0500, Simo Sorce wrote:
> New rebase pushed

Thank you, this patchset compiles and all tests pass. I don't think it is
realistic to review every codepath in every patch, it's too big. I reviewed
the domain initialization carefully, but then many patches "just" add the
domain parameter to a sysdb function and adjust the callers. So I used gcov
to see code coverage of the changed functions and read the code, but not
that carefully as when reviewing a regular patch, if the code was covered.

I attached the gcov output after my review of the first part of this
patchset and some more unit tests. Please squash the unit tests into the
approproate patches or simply include them on top, whatever suits you
better.

tl;dr version - it's mostly good. I only have some suggestions, nothing
blocking the push. Given the sheer size of the patchset, I'd say that we
should push the patchset and fix the remaining issues in separate
tickets/patches to spare us from rebasing the whole thing when the whole
patchset is reviewed.

Patch 0001: The Big sysdb/domain split-up!
Ack

Patch 0002: Refactor sysdb initialization
Ack with a suggestion:

The sysdb initialization looks cleaner to me now. I tested
sysdb clean initialization and upgrade and both look fine to me. While
you are touching the sysdb init, what about removing the "alt_db_path"
parameter of sysdb_init? It is not used anywhere and I can't think of a
meaningful way to use it.

Patch 0003: Refactor single domain initialization
Ack. This matches the intent of the refactoring.

Patch 0004: Remove the sysdb_ctx_get_domain() function.
Ack.

Patches 0005-0011: Make sysdb_*_dn() require a domain explictly
Ack. sysdb_netgroup_base_dn() was not covered with unit test, so I wrote
one,

Patch 0012: Move range objects into their own top-level tree.
Ack from my point of view, but Sumit would be a better authority on the
subdomains design.

Patch 0013: Pass domain to sysdb_get<pw/gr>nam() functions
This one is bigger and more involved than the rest of refactoring
patches. I think it would be nice to have a separate macro like
"domain_has_subdomain" that would be more self-explanatory than
"if (domain->parent && domain->fqnames)".

I think the ENOMEM part is wrong (a leftover probably):
+    if (domain->parent && domain->fqnames) {
+        ret = ENOMEM;
+        src_name = talloc_asprintf(tmp_ctx, domain->names->fq_fmt,
+                                   name, domain->name);
+    } else {

One thing that surprised me is dom->fqnames being set to true now. I think
I would expect it to be true even before the patches? I know it's
mentioned in the commit message, I'm just wondering if the code worked
by accident until now?

Other than that, retrieving users and groups by name worked for me for
both native and trusted users and groups.

Patches 0014-0015: Pass domain to sysdb_get<pwu/grg><id() functions
Ack. Code looks fine, is covered by tests and getting both trusted and
native users and groups by ID works fine.
Enumeration also works fine.

Patch 0016: Add domain option to sysdb_get/netgr/attrs() fns
Ack. Code is covered, looks sane, retrieving and updating netgroups works fine.

Patch 0017: Add domain argument to sysdb_initgroups()
Ack. Code is covered, looks sane, user login works fine. I was suprised that
sysdb_initgroups, in spite of being one of the most important sysdb
functions doesn't have a unit test, so I wrote one.

Patch 0018: Add domain argument to sysdb_get_user_attr()
Ack. Code is covered, looks sane and authentication still works and sets the
lastOnlineAuth correctly.

Patch 0019-0022: Add domain to sysdb_search_user/group_by_name/uid/gid
Ack. Code is covered. I tested the basic ID operations (get{pw,gr}{uid,nam}),
and also some basic HBAC and SELinux sanity tests.

Patch 0023: Add domain arg to sysdb_search_netgroup_by_name
Ack. Netgroups still seem to work, code is covered and looks sane

Patch 0024-0027: Add domain argument to sysdb_set_user/group/netgroup_attr()
The last patch is misnamed, it should say "netgroup", not "group".
Otherwise Ack, code is covered, looks sane.

Patch 0028: Add domain argument to sysdb_get_new_id()
Ack. Local domain tools still work OK. I added a sanity test to the test
suite to cover the code.

Patch 0029-0031: Add domain argument to sysdb_add{,_basic}_user()
Ack. Retrieving users and groups still works, the code is mostly covered.

Patch 0032: Add domain arguments to sysdb_add_inetgroup fns
Ack, apart from typo in the commit message. Code is covered and
netgroups still seem to work (both LDAP and IPA).

Patch 0033-0034: Add domain argument to sysdb_store_user/group
Ack. Saving users and groups still work, code looks OK and is covered.

Patch 0035: Add domain arg to sysdb group member functions.
Ack. There's some room for improving the code coverage, but adding both
users and groups as members works.

Patch 0036-0037: Add domain argument to sysdb_cache_passwd/auth
Ack. Code is covered and cached auth still works.

Patch 0038-0040: Add domain argument to sysdb_store/search/delete_custom
Ack. Code is covered and functionality that uses the custom tree, such
as HBAC, still works.

That leaves less than 20 patches to go. I'll review them tomorrow.
-------------- next part --------------
>From 0d044e0f7589787090311f4fcc697954acffb8c2 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sun, 13 Jan 2013 19:56:12 +0100
Subject: [PATCH 1/3] tests: add a unit test for sysdb_netgroup_base_dn

---
 src/tests/sysdb-tests.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index f68ef24951d1b10350c4009a84c4f7058a4c6bb4..958018fd4e71c78a9a56a2029b4778e311693f3b 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -3706,6 +3706,27 @@ START_TEST (test_sysdb_get_netgroup_attr)
 }
 END_TEST
 
+START_TEST (test_netgroup_base_dn)
+{
+    errno_t ret;
+    struct sysdb_test_ctx *test_ctx;
+    struct ldb_dn *base_dn;
+    const char *strdn;
+
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Could not set up the test");
+
+    base_dn = sysdb_netgroup_base_dn(test_ctx->sysdb, test_ctx, test_ctx->domain);
+    fail_if(base_dn == NULL, "Could not get netgroup base DN");
+
+    strdn = ldb_dn_get_linearized(base_dn);
+    fail_if(strdn == NULL, "Could not get string netgroup base DN");
+
+    fail_if(strstr(strdn, SYSDB_NETGROUP_CONTAINER) != strdn,
+            "Malformed netgroup baseDN");
+}
+END_TEST
+
 START_TEST(test_odd_characters)
 {
     errno_t ret;
@@ -4872,6 +4893,8 @@ Suite *create_sysdb_suite(void)
     /* Remove the other half by DN */
     tcase_add_loop_test(tc_sysdb, test_sysdb_remove_netgroup_entry, 27005, 27010);
 
+    tcase_add_test(tc_sysdb, test_netgroup_base_dn);
+
 /* ===== SERVICE TESTS ===== */
 
     /* Create a new service */
-- 
1.8.0.2

-------------- next part --------------
>From 7aba544033b3da4fda010dd533c9767c5bb661c8 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sun, 13 Jan 2013 22:00:50 +0100
Subject: [PATCH 2/3] tests: test sysdb_initgroups

---
 src/tests/sysdb-tests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 958018fd4e71c78a9a56a2029b4778e311693f3b..d05b31f3ebe32cb8c2c65f91ea6dc79fb1bbb4fa 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -1194,6 +1194,51 @@ START_TEST (test_sysdb_add_group_member)
 }
 END_TEST
 
+START_TEST (test_sysdb_initgroups)
+{
+    struct sysdb_test_ctx *test_ctx;
+    int ret;
+    const char *username;
+    struct ldb_result *res;
+    struct ldb_message *user;
+    struct ldb_message *group;
+    gid_t gid;
+    uid_t uid;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    if (ret != EOK) {
+        fail("Could not set up the test");
+        return;
+    }
+
+    username = talloc_asprintf(test_ctx, "testuser%d", _i);
+
+    ret = sysdb_initgroups(test_ctx,
+                           test_ctx->sysdb,
+                           test_ctx->domain,
+                           username, &res);
+    fail_if(ret != EOK, "sysdb_initgroups failed\n");
+
+    /* result should contain 2 messages - user and his group */
+    fail_if(res->count != 2, "expected 2 groups, got %d\n", res->count);
+
+    /* check if it's the expected user and expected group */
+    user = res->msgs[0];
+    group = res->msgs[1];
+
+    uid = ldb_msg_find_attr_as_uint(user, SYSDB_UIDNUM, 0);
+    fail_unless(uid == _i,
+                "Did not find the expected UID (found %d expected %d)",
+                uid, _i);
+
+    gid = ldb_msg_find_attr_as_uint(group, SYSDB_GIDNUM, 0);
+    fail_unless(gid == _i + 1000,
+                "Did not find the expected GID (found %d expected %d)",
+                gid, _i);
+}
+END_TEST
+
 START_TEST (test_sysdb_remove_group_member)
 {
     struct sysdb_test_ctx *test_ctx;
@@ -4807,6 +4852,9 @@ Suite *create_sysdb_suite(void)
     /* Add some members to the groups */
     tcase_add_loop_test(tc_sysdb, test_sysdb_add_group_member, 28010, 28020);
 
+    /* Test that sysdb_initgroups() works */
+    tcase_add_loop_test(tc_sysdb, test_sysdb_initgroups, 27010, 27020);
+
     /* Authenticate with missing cached password */
     tcase_add_loop_test(tc_sysdb, test_sysdb_cached_authentication_missing_password,
                         27010, 27011);
-- 
1.8.0.2

-------------- next part --------------
>From 72e30b80ebea001c1da653ff67816a77517f2529 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sun, 13 Jan 2013 22:54:33 +0100
Subject: [PATCH 3/3] tests: add unit test for sysdb_get_new_id

---
 src/tests/sysdb-tests.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index d05b31f3ebe32cb8c2c65f91ea6dc79fb1bbb4fa..c42f287cf0ecb4101bd65047908f4dedbaee1535 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -1314,6 +1314,22 @@ START_TEST (test_sysdb_remove_nonexistent_group)
 }
 END_TEST
 
+START_TEST (test_sysdb_get_new_id)
+{
+    struct sysdb_test_ctx *test_ctx;
+    int ret;
+    uint32_t id;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Cannot setup sysdb tests\n");
+
+    ret = sysdb_get_new_id(test_ctx->sysdb, test_ctx->domain, &id);
+    fail_if(ret != EOK, "Cannot get new ID\n");
+    fail_if(id != test_ctx->domain->id_min);
+}
+END_TEST
+
 START_TEST (test_sysdb_store_custom)
 {
     struct sysdb_test_ctx *test_ctx;
@@ -4507,7 +4523,7 @@ START_TEST(test_sysdb_subdomain_user_ops)
 
     ret = sysdb_search_user_by_name(test_ctx, subdomain->sysdb, subdomain,
                                     "subdomuser", NULL, &msg);
-    fail_unless(ret == EOK, "sysdb_search_domuser_by_name failed with [%d][%s].",
+    fail_unless(ret == EOK, "sysdb_search_user_by_name failed with [%d][%s].",
                             ret, strerror(ret));
     fail_unless(ldb_dn_compare(msg->dn, check_dn) == 0,
                 "Unexpedted DN returned");
@@ -4790,6 +4806,9 @@ Suite *create_sysdb_suite(void)
 
     TCase *tc_sysdb = tcase_create("SYSDB Tests");
 
+    /* test getting next id works */
+    tcase_add_test(tc_sysdb, test_sysdb_get_new_id);
+
     /* Create a new user */
     tcase_add_loop_test(tc_sysdb, test_sysdb_add_user,27000,27010);
 
-- 
1.8.0.2

-------------- next part --------------
        -:    0:Source:src/db/sysdb.c
        -:    0:Graph:src/db/sysdb_tests-sysdb.gcno
        -:    0:Data:src/db/sysdb_tests-sysdb.gcda
        -:    0:Runs:2
        -:    0:Programs:2
        -:    1:/*
        -:    2:   SSSD
        -:    3:
        -:    4:   System Database
        -:    5:
        -:    6:   Copyright (C) 2008-2011 Simo Sorce <ssorce at redhat.com>
        -:    7:   Copyright (C) 2008-2011 Stephen Gallagher <ssorce at redhat.com>
        -:    8:
        -:    9:   This program is free software; you can redistribute it and/or modify
        -:   10:   it under the terms of the GNU General Public License as published by
        -:   11:   the Free Software Foundation; either version 3 of the License, or
        -:   12:   (at your option) any later version.
        -:   13:
        -:   14:   This program is distributed in the hope that it will be useful,
        -:   15:   but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   16:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   17:   GNU General Public License for more details.
        -:   18:
        -:   19:   You should have received a copy of the GNU General Public License
        -:   20:   along with this program.  If not, see <http://www.gnu.org/licenses/>.
        -:   21:*/
        -:   22:
        -:   23:#include "util/util.h"
        -:   24:#include "util/strtonum.h"
        -:   25:#include "util/sss_utf8.h"
        -:   26:#include "db/sysdb_private.h"
        -:   27:#include "confdb/confdb.h"
        -:   28:#include <time.h>
        -:   29:
        -:   30:#define LDB_MODULES_PATH "LDB_MODULES_PATH"
        -:   31:
     1529:   32:errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename,
        -:   33:                          struct ldb_context **_ldb)
        -:   34:{
        -:   35:    int ret;
        -:   36:    struct ldb_context *ldb;
        -:   37:    const char *mod_path;
        -:   38:
     1529:   39:    if (_ldb == NULL) {
    #####:   40:        return EINVAL;
        -:   41:    }
        -:   42:
     1529:   43:    ldb = ldb_init(mem_ctx, NULL);
     1529:   44:    if (!ldb) {
    #####:   45:        return EIO;
        -:   46:    }
        -:   47:
     1529:   48:    ret = ldb_set_debug(ldb, ldb_debug_messages, NULL);
     1529:   49:    if (ret != LDB_SUCCESS) {
    #####:   50:        return EIO;
        -:   51:    }
        -:   52:
     1529:   53:    mod_path = getenv(LDB_MODULES_PATH);
     1529:   54:    if (mod_path != NULL) {
    #####:   55:        DEBUG(9, ("Setting ldb module path to [%s].\n", mod_path));
    #####:   56:        ldb_set_modules_dir(ldb, mod_path);
        -:   57:    }
        -:   58:
     1529:   59:    ret = ldb_connect(ldb, filename, 0, NULL);
     1529:   60:    if (ret != LDB_SUCCESS) {
    #####:   61:        return EIO;
        -:   62:    }
        -:   63:
     1529:   64:    *_ldb = ldb;
        -:   65:
     1529:   66:    return EOK;
        -:   67:}
        -:   68:
     2626:   69:errno_t sysdb_dn_sanitize(TALLOC_CTX *mem_ctx, const char *input,
        -:   70:                          char **sanitized)
        -:   71:{
        -:   72:    struct ldb_val val;
     2626:   73:    errno_t ret = EOK;
        -:   74:
     2626:   75:    val.data = (uint8_t *)talloc_strdup(mem_ctx, input);
     2626:   76:    if (!val.data) {
    #####:   77:        return ENOMEM;
        -:   78:    }
        -:   79:
        -:   80:    /* We can't include the trailing NULL because it would
        -:   81:     * be escaped and result in an unterminated string
        -:   82:     */
     2626:   83:    val.length = strlen(input);
        -:   84:
     2626:   85:    *sanitized = ldb_dn_escape_value(mem_ctx, val);
     2626:   86:    if (!*sanitized) {
    #####:   87:        ret = ENOMEM;
        -:   88:    }
        -:   89:
     2626:   90:    talloc_free(val.data);
     2626:   91:    return ret;
        -:   92:}
        -:   93:
       42:   94:struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *sysdb,
        -:   95:                                       TALLOC_CTX *mem_ctx,
        -:   96:                                       struct sss_domain_info *dom,
        -:   97:                                       const char *subtree_name)
        -:   98:{
        -:   99:    errno_t ret;
        -:  100:    char *clean_subtree;
       42:  101:    struct ldb_dn *dn = NULL;
        -:  102:    TALLOC_CTX *tmp_ctx;
        -:  103:
       42:  104:    tmp_ctx = talloc_new(NULL);
       42:  105:    if (!tmp_ctx) return NULL;
        -:  106:
       42:  107:    ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
       42:  108:    if (ret != EOK) {
    #####:  109:        talloc_free(tmp_ctx);
    #####:  110:        return NULL;
        -:  111:    }
        -:  112:
       42:  113:    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
        -:  114:                        clean_subtree, dom->name);
       42:  115:    if (dn) {
       42:  116:        talloc_steal(mem_ctx, dn);
        -:  117:    }
       42:  118:    talloc_free(tmp_ctx);
        -:  119:
       42:  120:    return dn;
        -:  121:}
        -:  122:
      130:  123:struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  124:                               struct sss_domain_info *dom,
        -:  125:                               const char *object_name,
        -:  126:                               const char *subtree_name)
        -:  127:{
        -:  128:    errno_t ret;
        -:  129:    TALLOC_CTX *tmp_ctx;
        -:  130:    char *clean_name;
        -:  131:    char *clean_subtree;
      130:  132:    struct ldb_dn *dn = NULL;
        -:  133:
      130:  134:    tmp_ctx = talloc_new(NULL);
      130:  135:    if (!tmp_ctx) {
    #####:  136:        return NULL;
        -:  137:    }
        -:  138:
      130:  139:    ret = sysdb_dn_sanitize(tmp_ctx, object_name, &clean_name);
      130:  140:    if (ret != EOK) {
    #####:  141:        goto done;
        -:  142:    }
        -:  143:
      130:  144:    ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
      130:  145:    if (ret != EOK) {
    #####:  146:        goto done;
        -:  147:    }
        -:  148:
      130:  149:    dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM, clean_name,
        -:  150:                        clean_subtree, dom->name);
        -:  151:
        -:  152:done:
      130:  153:    talloc_free(tmp_ctx);
      130:  154:    return dn;
        -:  155:}
        -:  156:
      776:  157:struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  158:                             struct sss_domain_info *dom, const char *name)
        -:  159:{
        -:  160:    errno_t ret;
        -:  161:    char *clean_name;
        -:  162:    struct ldb_dn *dn;
        -:  163:
      776:  164:    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
      776:  165:    if (ret != EOK) {
    #####:  166:        return NULL;
        -:  167:    }
        -:  168:
      776:  169:    dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_USER,
        -:  170:                        clean_name, dom->name);
      776:  171:    talloc_free(clean_name);
        -:  172:
      776:  173:    return dn;
        -:  174:}
        -:  175:
      992:  176:struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  177:                              struct sss_domain_info *dom, const char *name)
        -:  178:{
        -:  179:    errno_t ret;
        -:  180:    char *clean_name;
        -:  181:    struct ldb_dn *dn;
        -:  182:
      992:  183:    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
      992:  184:    if (ret != EOK) {
    #####:  185:        return NULL;
        -:  186:    }
        -:  187:
      992:  188:    dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_GROUP,
        -:  189:                        clean_name, dom->name);
      992:  190:    talloc_free(clean_name);
        -:  191:
      992:  192:    return dn;
        -:  193:}
        -:  194:
      104:  195:struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  196:                                 struct sss_domain_info *dom, const char *name)
        -:  197:{
        -:  198:    errno_t ret;
        -:  199:    char *clean_name;
        -:  200:    struct ldb_dn *dn;
        -:  201:
      104:  202:    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
      104:  203:    if (ret != EOK) {
    #####:  204:        return NULL;
        -:  205:    }
        -:  206:
      104:  207:    dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_NETGROUP,
        -:  208:                        clean_name, dom->name);
      104:  209:    talloc_free(clean_name);
        -:  210:
      104:  211:    return dn;
        -:  212:}
        -:  213:
        1:  214:struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *sysdb,
        -:  215:                                      TALLOC_CTX *mem_ctx,
        -:  216:                                      struct sss_domain_info *dom)
        -:  217:{
        1:  218:    return ldb_dn_new_fmt(mem_ctx, sysdb->ldb,
        -:  219:                          SYSDB_TMPL_NETGROUP_BASE, dom->name);
        -:  220:}
        -:  221:
       20:  222:errno_t sysdb_get_rdn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  223:                      const char *_dn, char **_name, char **_val)
        -:  224:{
        -:  225:    errno_t ret;
        -:  226:    struct ldb_dn *dn;
       20:  227:    const char *attr_name = NULL;
        -:  228:    const struct ldb_val *val;
        -:  229:    TALLOC_CTX *tmp_ctx;
        -:  230:
        -:  231:    /* We have to create a tmp_ctx here because
        -:  232:     * ldb_dn_new_fmt() fails if mem_ctx is NULL
        -:  233:     */
       20:  234:    tmp_ctx = talloc_new(NULL);
       20:  235:    if (!tmp_ctx) {
    #####:  236:        return ENOMEM;
        -:  237:    }
        -:  238:
       20:  239:    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, "%s", _dn);
       20:  240:    if (dn == NULL) {
    #####:  241:        ret = ENOMEM;
    #####:  242:        goto done;
        -:  243:    }
        -:  244:
       20:  245:    if (_name) {
    #####:  246:        attr_name = ldb_dn_get_rdn_name(dn);
    #####:  247:        if (attr_name == NULL) {
    #####:  248:            ret = EINVAL;
    #####:  249:            goto done;
        -:  250:        }
        -:  251:
    #####:  252:        *_name = talloc_strdup(mem_ctx, attr_name);
    #####:  253:        if (!*_name) {
    #####:  254:            ret = ENOMEM;
    #####:  255:            goto done;
        -:  256:        }
        -:  257:    }
        -:  258:
       20:  259:    val = ldb_dn_get_rdn_val(dn);
       20:  260:    if (val == NULL) {
    #####:  261:        ret = EINVAL;
    #####:  262:        if (_name) talloc_free(*_name);
    #####:  263:        goto done;
        -:  264:    }
        -:  265:
       20:  266:    *_val = talloc_strndup(mem_ctx, (char *) val->data, val->length);
       20:  267:    if (!*_val) {
    #####:  268:        ret = ENOMEM;
    #####:  269:        if (_name) talloc_free(*_name);
    #####:  270:        goto done;
        -:  271:    }
        -:  272:
       20:  273:    ret = EOK;
        -:  274:
        -:  275:done:
       20:  276:    talloc_zfree(tmp_ctx);
       20:  277:    return ret;
        -:  278:}
        -:  279:
       20:  280:errno_t sysdb_group_dn_name(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  281:                            const char *_dn, char **_name)
        -:  282:{
       20:  283:    return sysdb_get_rdn(sysdb, mem_ctx, _dn, NULL, _name);
        -:  284:}
        -:  285:
        2:  286:struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
        -:  287:                               struct sss_domain_info *dom)
        -:  288:{
        2:  289:    return ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_DOM_BASE, dom->name);
        -:  290:}
        -:  291:
    #####:  292:struct ldb_dn *sysdb_base_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx)
        -:  293:{
    #####:  294:    return ldb_dn_new(mem_ctx, sysdb->ldb, SYSDB_BASE);
        -:  295:}
        -:  296:
    #####:  297:struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *sysdb)
        -:  298:{
    #####:  299:    return sysdb->ldb;
        -:  300:}
        -:  301:
      784:  302:struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *mem_ctx)
        -:  303:{
      784:  304:    return talloc_zero(mem_ctx, struct sysdb_attrs);
        -:  305:}
        -:  306:
     2956:  307:int sysdb_attrs_get_el_ext(struct sysdb_attrs *attrs, const char *name,
        -:  308:                           bool alloc, struct ldb_message_element **el)
        -:  309:{
     2956:  310:    struct ldb_message_element *e = NULL;
        -:  311:    int i;
        -:  312:
     7436:  313:    for (i = 0; i < attrs->num; i++) {
     4480:  314:        if (strcasecmp(name, attrs->a[i].name) == 0)
       94:  315:            e = &(attrs->a[i]);
        -:  316:    }
        -:  317:
     2956:  318:    if (!e && alloc) {
     2656:  319:        e = talloc_realloc(attrs, attrs->a,
        -:  320:                           struct ldb_message_element, attrs->num+1);
     2656:  321:        if (!e) return ENOMEM;
     2656:  322:        attrs->a = e;
        -:  323:
     2656:  324:        e[attrs->num].name = talloc_strdup(e, name);
     2656:  325:        if (!e[attrs->num].name) return ENOMEM;
        -:  326:
     2656:  327:        e[attrs->num].num_values = 0;
     2656:  328:        e[attrs->num].values = NULL;
     2656:  329:        e[attrs->num].flags = 0;
        -:  330:
     2656:  331:        e = &(attrs->a[attrs->num]);
     2656:  332:        attrs->num++;
        -:  333:    }
        -:  334:
     2956:  335:    if (!e) {
      206:  336:        return ENOENT;
        -:  337:    }
        -:  338:
     2750:  339:    *el = e;
        -:  340:
     2750:  341:    return EOK;
        -:  342:}
        -:  343:
     2750:  344:int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name,
        -:  345:                       struct ldb_message_element **el)
        -:  346:{
     2750:  347:    return sysdb_attrs_get_el_ext(attrs, name, true, el);
        -:  348:}
        -:  349:
    #####:  350:int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name,
        -:  351:                           const char **string)
        -:  352:{
        -:  353:    struct ldb_message_element *el;
        -:  354:    int ret;
        -:  355:
    #####:  356:    ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
    #####:  357:    if (ret) {
    #####:  358:        return ret;
        -:  359:    }
        -:  360:
    #####:  361:    if (el->num_values != 1) {
    #####:  362:        return ERANGE;
        -:  363:    }
        -:  364:
    #####:  365:    *string = (const char *)el->values[0].data;
    #####:  366:    return EOK;
        -:  367:}
        -:  368:
    #####:  369:int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,
        -:  370:                             uint32_t *value)
        -:  371:{
        -:  372:    struct ldb_message_element *el;
        -:  373:    int ret;
        -:  374:    char *endptr;
        -:  375:    uint32_t val;
        -:  376:
    #####:  377:    ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
    #####:  378:    if (ret) {
    #####:  379:        return ret;
        -:  380:    }
        -:  381:
    #####:  382:    if (el->num_values != 1) {
    #####:  383:        return ERANGE;
        -:  384:    }
        -:  385:
    #####:  386:    errno = 0;
    #####:  387:    val = strtouint32((const char *) el->values[0].data, &endptr, 10);
    #####:  388:    if (errno != 0) return errno;
    #####:  389:    if (*endptr) return EINVAL;
        -:  390:
    #####:  391:    *value = val;
    #####:  392:    return EOK;
        -:  393:}
        -:  394:
    #####:  395:int sysdb_attrs_get_uint16_t(struct sysdb_attrs *attrs, const char *name,
        -:  396:                             uint16_t *value)
        -:  397:{
        -:  398:    struct ldb_message_element *el;
        -:  399:    int ret;
        -:  400:    char *endptr;
        -:  401:    uint16_t val;
        -:  402:
    #####:  403:    ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
    #####:  404:    if (ret) {
    #####:  405:        return ret;
        -:  406:    }
        -:  407:
    #####:  408:    if (el->num_values != 1) {
    #####:  409:        return ERANGE;
        -:  410:    }
        -:  411:
    #####:  412:    errno = 0;
    #####:  413:    val = strtouint16((const char *) el->values[0].data, &endptr, 10);
    #####:  414:    if (errno != 0) return errno;
    #####:  415:    if (*endptr) return EINVAL;
        -:  416:
    #####:  417:    *value = val;
    #####:  418:    return EOK;
        -:  419:}
        -:  420:
      206:  421:errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name,
        -:  422:                             bool *value)
        -:  423:{
        -:  424:    struct ldb_message_element *el;
        -:  425:    int ret;
        -:  426:
      206:  427:    ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
      206:  428:    if (ret) {
      206:  429:        return ret;
        -:  430:    }
        -:  431:
    #####:  432:    if (el->num_values != 1) {
    #####:  433:        return ERANGE;
        -:  434:    }
        -:  435:
    #####:  436:    if (strcmp((const char *)el->values[0].data, "TRUE") == 0)
    #####:  437:        *value = true;
        -:  438:    else
    #####:  439:        *value = false;
    #####:  440:    return EOK;
        -:  441:}
        -:  442:
    #####:  443:int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name,
        -:  444:                                 TALLOC_CTX *mem_ctx, const char ***string)
        -:  445:{
        -:  446:    struct ldb_message_element *el;
        -:  447:    int ret;
        -:  448:    unsigned int u;
        -:  449:    const char **a;
        -:  450:
    #####:  451:    ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
    #####:  452:    if (ret) {
    #####:  453:        return ret;
        -:  454:    }
        -:  455:
    #####:  456:    a = talloc_array(mem_ctx, const char *, el->num_values + 1);
    #####:  457:    if (a == NULL) {
    #####:  458:        return ENOMEM;
        -:  459:    }
        -:  460:
    #####:  461:    memset(a, 0, sizeof(const char *) * (el->num_values + 1));
        -:  462:
    #####:  463:    for(u = 0; u < el->num_values; u++) {
    #####:  464:        a[u] = talloc_strndup(a, (const char *)el->values[u].data,
    #####:  465:                              el->values[u].length);
    #####:  466:        if (a[u] == NULL) {
    #####:  467:            talloc_free(a);
    #####:  468:            return ENOMEM;
        -:  469:        }
        -:  470:    }
        -:  471:
    #####:  472:    *string = a;
    #####:  473:    return EOK;
        -:  474:}
        -:  475:
     2246:  476:int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
        -:  477:                        const char *name, const struct ldb_val *val)
        -:  478:{
     2246:  479:    struct ldb_message_element *el = NULL;
        -:  480:    struct ldb_val *vals;
        -:  481:    int ret;
        -:  482:
     2246:  483:    ret = sysdb_attrs_get_el(attrs, name, &el);
     2246:  484:    if (ret != EOK) {
    #####:  485:        return ret;
        -:  486:    }
        -:  487:
     2246:  488:    vals = talloc_realloc(attrs->a, el->values,
        -:  489:                          struct ldb_val, el->num_values+1);
     2246:  490:    if (!vals) return ENOMEM;
        -:  491:
     2246:  492:    vals[el->num_values] = ldb_val_dup(vals, val);
     2246:  493:    if (vals[el->num_values].data == NULL &&
    #####:  494:        vals[el->num_values].length != 0) {
    #####:  495:        return ENOMEM;
        -:  496:    }
        -:  497:
     2246:  498:    el->values = vals;
     2246:  499:    el->num_values++;
        -:  500:
     2246:  501:    return EOK;
        -:  502:}
        -:  503:
     1374:  504:int sysdb_attrs_add_string(struct sysdb_attrs *attrs,
        -:  505:                           const char *name, const char *str)
        -:  506:{
        -:  507:    struct ldb_val v;
        -:  508:
     1374:  509:    v.data = (uint8_t *)discard_const(str);
     1374:  510:    v.length = strlen(str);
        -:  511:
     1374:  512:    return sysdb_attrs_add_val(attrs, name, &v);
        -:  513:}
        -:  514:
      232:  515:int sysdb_attrs_add_bool(struct sysdb_attrs *attrs,
        -:  516:                         const char *name, bool value)
        -:  517:{
      232:  518:    if(value) {
      232:  519:        return sysdb_attrs_add_string(attrs, name, "TRUE");
        -:  520:    }
        -:  521:
    #####:  522:    return sysdb_attrs_add_string(attrs, name, "FALSE");
        -:  523:}
        -:  524:
      422:  525:int sysdb_attrs_steal_string(struct sysdb_attrs *attrs,
        -:  526:                             const char *name, char *str)
        -:  527:{
      422:  528:    struct ldb_message_element *el = NULL;
        -:  529:    struct ldb_val *vals;
        -:  530:    int ret;
        -:  531:
      422:  532:    ret = sysdb_attrs_get_el(attrs, name, &el);
      422:  533:    if (ret != EOK) {
    #####:  534:        return ret;
        -:  535:    }
        -:  536:
      422:  537:    vals = talloc_realloc(attrs->a, el->values,
        -:  538:                          struct ldb_val, el->num_values+1);
      422:  539:    if (!vals) return ENOMEM;
      422:  540:    el->values = vals;
        -:  541:
        -:  542:    /* now steal and assign the string */
      422:  543:    talloc_steal(el->values, str);
        -:  544:
      422:  545:    el->values[el->num_values].data = (uint8_t *)str;
      422:  546:    el->values[el->num_values].length = strlen(str);
      422:  547:    el->num_values++;
        -:  548:
      422:  549:    return EOK;
        -:  550:}
        -:  551:
        2:  552:int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
        -:  553:                         const char *name, long value)
        -:  554:{
        -:  555:    struct ldb_val v;
        -:  556:    char *str;
        -:  557:    int ret;
        -:  558:
        2:  559:    str = talloc_asprintf(attrs, "%ld", value);
        2:  560:    if (!str) return ENOMEM;
        -:  561:
        2:  562:    v.data = (uint8_t *)str;
        2:  563:    v.length = strlen(str);
        -:  564:
        2:  565:    ret = sysdb_attrs_add_val(attrs, name, &v);
        2:  566:    talloc_free(str);
        -:  567:
        2:  568:    return ret;
        -:  569:}
        -:  570:
       92:  571:int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
        -:  572:                           const char *name, uint32_t value)
        -:  573:{
       92:  574:    unsigned long val = value;
        -:  575:    struct ldb_val v;
        -:  576:    char *str;
        -:  577:    int ret;
        -:  578:
       92:  579:    str = talloc_asprintf(attrs, "%lu", val);
       92:  580:    if (!str) return ENOMEM;
        -:  581:
       92:  582:    v.data = (uint8_t *)str;
       92:  583:    v.length = strlen(str);
        -:  584:
       92:  585:    ret = sysdb_attrs_add_val(attrs, name, &v);
       92:  586:    talloc_free(str);
        -:  587:
       92:  588:    return ret;
        -:  589:}
        -:  590:
      778:  591:int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
        -:  592:                           const char *name, time_t value)
        -:  593:{
      778:  594:    long long val = value;
        -:  595:    struct ldb_val v;
        -:  596:    char *str;
        -:  597:    int ret;
        -:  598:
      778:  599:    str = talloc_asprintf(attrs, "%lld", val);
      778:  600:    if (!str) return ENOMEM;
        -:  601:
      778:  602:    v.data = (uint8_t *)str;
      778:  603:    v.length = strlen(str);
        -:  604:
      778:  605:    ret = sysdb_attrs_add_val(attrs, name, &v);
      778:  606:    talloc_free(str);
        -:  607:
      778:  608:    return ret;
        -:  609:}
        -:  610:
    #####:  611:int sysdb_attrs_copy_values(struct sysdb_attrs *src,
        -:  612:                            struct sysdb_attrs *dst,
        -:  613:                            const char *name)
        -:  614:{
    #####:  615:    int ret = EOK;
        -:  616:    int i;
        -:  617:    struct ldb_message_element *src_el;
        -:  618:
    #####:  619:    ret = sysdb_attrs_get_el(src, name, &src_el);
    #####:  620:    if (ret != EOK) {
    #####:  621:        goto done;
        -:  622:    }
        -:  623:
    #####:  624:    for (i = 0; i < src_el->num_values; i++) {
    #####:  625:        ret = sysdb_attrs_add_val(dst, name, &src_el->values[i]);
    #####:  626:        if (ret != EOK) {
    #####:  627:            goto done;
        -:  628:        }
        -:  629:    }
        -:  630:
        -:  631:done:
    #####:  632:    return ret;
        -:  633:}
        -:  634:
    #####:  635:int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs,
        -:  636:                                    const char *attr_name,
        -:  637:                                    const char *domain,
        -:  638:                                    const char *const *list)
        -:  639:{
    #####:  640:    struct ldb_message_element *el = NULL;
        -:  641:    struct ldb_val *vals;
        -:  642:    int i, j, num;
        -:  643:    char *member;
        -:  644:    int ret;
        -:  645:
    #####:  646:    ret = sysdb_attrs_get_el(attrs, attr_name, &el);
    #####:  647:    if (ret) {
    #####:  648:        return ret;
        -:  649:    }
        -:  650:
    #####:  651:    for (num = 0; list[num]; num++) /* count */ ;
        -:  652:
    #####:  653:    vals = talloc_realloc(attrs->a, el->values,
        -:  654:                          struct ldb_val, el->num_values + num);
    #####:  655:    if (!vals) {
    #####:  656:        return ENOMEM;
        -:  657:    }
    #####:  658:    el->values = vals;
        -:  659:
    #####:  660:    DEBUG(9, ("Adding %d members to existing %d ones\n",
        -:  661:              num, el->num_values));
        -:  662:
    #####:  663:    for (i = 0, j = el->num_values; i < num; i++) {
        -:  664:
    #####:  665:        member = sysdb_user_strdn(el->values, domain, list[i]);
    #####:  666:        if (!member) {
    #####:  667:            DEBUG(4, ("Failed to get user dn for [%s]\n", list[i]));
    #####:  668:            continue;
        -:  669:        }
    #####:  670:        el->values[j].data = (uint8_t *)member;
    #####:  671:        el->values[j].length = strlen(member);
    #####:  672:        j++;
        -:  673:
    #####:  674:        DEBUG(7, ("    member #%d: [%s]\n", i, member));
        -:  675:    }
    #####:  676:    el->num_values = j;
        -:  677:
    #####:  678:    return EOK;
        -:  679:}
        -:  680:
      136:  681:static char *build_dom_dn_str_escape(TALLOC_CTX *mem_ctx, const char *template,
        -:  682:                                     const char *domain, const char *name)
        -:  683:{
        -:  684:    char *ret;
        -:  685:    int l;
        -:  686:
      136:  687:    l = strcspn(name, ",=\n+<>#;\\\"");
      136:  688:    if (name[l] != '\0') {
        -:  689:        struct ldb_val v;
        -:  690:        char *tmp;
        -:  691:
    #####:  692:        v.data = discard_const_p(uint8_t, name);
    #####:  693:        v.length = strlen(name);
        -:  694:
    #####:  695:        tmp = ldb_dn_escape_value(mem_ctx, v);
    #####:  696:        if (!tmp) {
    #####:  697:            return NULL;
        -:  698:        }
        -:  699:
    #####:  700:        ret = talloc_asprintf(mem_ctx, template, tmp, domain);
    #####:  701:        talloc_zfree(tmp);
    #####:  702:        if (!ret) {
    #####:  703:            return NULL;
        -:  704:        }
        -:  705:
    #####:  706:        return ret;
        -:  707:    }
        -:  708:
      136:  709:    ret = talloc_asprintf(mem_ctx, template, name, domain);
      136:  710:    if (!ret) {
    #####:  711:        return NULL;
        -:  712:    }
        -:  713:
      136:  714:    return ret;
        -:  715:}
        -:  716:
    #####:  717:char *sysdb_user_strdn(TALLOC_CTX *mem_ctx,
        -:  718:                       const char *domain, const char *name)
        -:  719:{
    #####:  720:    return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_USER, domain, name);
        -:  721:}
        -:  722:
      136:  723:char *sysdb_group_strdn(TALLOC_CTX *mem_ctx,
        -:  724:                        const char *domain, const char *name)
        -:  725:{
      136:  726:    return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_GROUP, domain, name);
        -:  727:}
        -:  728:
        -:  729:/* TODO: make a more complete and precise mapping */
     1882:  730:int sysdb_error_to_errno(int ldberr)
        -:  731:{
     1882:  732:    switch (ldberr) {
        -:  733:    case LDB_SUCCESS:
     1882:  734:        return EOK;
        -:  735:    case LDB_ERR_OPERATIONS_ERROR:
    #####:  736:        return EIO;
        -:  737:    case LDB_ERR_NO_SUCH_OBJECT:
    #####:  738:        return ENOENT;
        -:  739:    case LDB_ERR_BUSY:
    #####:  740:        return EBUSY;
        -:  741:    case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
        -:  742:    case LDB_ERR_ENTRY_ALREADY_EXISTS:
    #####:  743:        return EEXIST;
        -:  744:    case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
    #####:  745:        return EINVAL;
        -:  746:    default:
    #####:  747:        DEBUG(SSSDBG_CRIT_FAILURE,
        -:  748:              ("LDB returned unexpected error: [%s]\n",
        -:  749:               ldb_strerror(ldberr)));
    #####:  750:        return EFAULT;
        -:  751:    }
        -:  752:}
        -:  753:
        -:  754:/* =Transactions========================================================== */
        -:  755:
      136:  756:int sysdb_transaction_start(struct sysdb_ctx *sysdb)
        -:  757:{
        -:  758:    int ret;
        -:  759:
      136:  760:    ret = ldb_transaction_start(sysdb->ldb);
      136:  761:    if (ret != LDB_SUCCESS) {
    #####:  762:        DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
        -:  763:    }
      136:  764:    return sysdb_error_to_errno(ret);
        -:  765:}
        -:  766:
      136:  767:int sysdb_transaction_commit(struct sysdb_ctx *sysdb)
        -:  768:{
        -:  769:    int ret;
        -:  770:
      136:  771:    ret = ldb_transaction_commit(sysdb->ldb);
      136:  772:    if (ret != LDB_SUCCESS) {
    #####:  773:        DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
        -:  774:    }
      136:  775:    return sysdb_error_to_errno(ret);
        -:  776:}
        -:  777:
    #####:  778:int sysdb_transaction_cancel(struct sysdb_ctx *sysdb)
        -:  779:{
        -:  780:    int ret;
        -:  781:
    #####:  782:    ret = ldb_transaction_cancel(sysdb->ldb);
    #####:  783:    if (ret != LDB_SUCCESS) {
    #####:  784:        DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
        -:  785:    }
    #####:  786:    return sysdb_error_to_errno(ret);
        -:  787:}
        -:  788:
        -:  789:/* =Initialization======================================================== */
        -:  790:
     1527:  791:int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
        -:  792:                      const char *provider, const char *name,
        -:  793:                      const char *base_path, char **_ldb_file)
        -:  794:{
        -:  795:    char *ldb_file;
        -:  796:
        -:  797:    /* special case for the local domain */
     1527:  798:    if (strcasecmp(provider, "local") == 0) {
     1527:  799:        ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE,
        -:  800:                                   base_path);
        -:  801:    } else {
    #####:  802:        ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
        -:  803:                                   base_path, name);
        -:  804:    }
     1527:  805:    if (!ldb_file) {
    #####:  806:        return ENOMEM;
        -:  807:    }
        -:  808:
     1527:  809:    *_ldb_file = ldb_file;
     1527:  810:    return EOK;
        -:  811:}
        -:  812:
        8:  813:errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name)
        -:  814:{
        -:  815:    struct ldb_message *msg;
        -:  816:    TALLOC_CTX *tmp_ctx;
        -:  817:    int ret;
        -:  818:
        8:  819:    tmp_ctx = talloc_new(NULL);
        8:  820:    if (tmp_ctx == NULL) {
    #####:  821:        ret = ENOMEM;
    #####:  822:        goto done;
        -:  823:    }
        -:  824:
        -:  825:    /* == create base domain object == */
        -:  826:
        8:  827:    msg = ldb_msg_new(tmp_ctx);
        8:  828:    if (!msg) {
    #####:  829:        ret = ENOMEM;
    #####:  830:        goto done;
        -:  831:    }
        8:  832:    msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, SYSDB_DOM_BASE, domain_name);
        8:  833:    if (!msg->dn) {
    #####:  834:        ret = ENOMEM;
    #####:  835:        goto done;
        -:  836:    }
        8:  837:    ret = ldb_msg_add_string(msg, "cn", domain_name);
        8:  838:    if (ret != LDB_SUCCESS) {
    #####:  839:        ret = EIO;
    #####:  840:        goto done;
        -:  841:    }
        -:  842:    /* do a synchronous add */
        8:  843:    ret = ldb_add(sysdb->ldb, msg);
        8:  844:    if (ret != LDB_SUCCESS) {
    #####:  845:        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) "
        -:  846:                                     "for domain %s!\n",
        -:  847:                                     ret, ldb_errstring(sysdb->ldb),
        -:  848:                                     domain_name));
    #####:  849:        ret = EIO;
    #####:  850:        goto done;
        -:  851:    }
        8:  852:    talloc_zfree(msg);
        -:  853:
        -:  854:    /* == create Users tree == */
        -:  855:
        8:  856:    msg = ldb_msg_new(tmp_ctx);
        8:  857:    if (!msg) {
    #####:  858:        ret = ENOMEM;
    #####:  859:        goto done;
        -:  860:    }
        8:  861:    msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
        -:  862:                             SYSDB_TMPL_USER_BASE, domain_name);
        8:  863:    if (!msg->dn) {
    #####:  864:        ret = ENOMEM;
    #####:  865:        goto done;
        -:  866:    }
        8:  867:    ret = ldb_msg_add_string(msg, "cn", "Users");
        8:  868:    if (ret != LDB_SUCCESS) {
    #####:  869:        ret = EIO;
    #####:  870:        goto done;
        -:  871:    }
        -:  872:    /* do a synchronous add */
        8:  873:    ret = ldb_add(sysdb->ldb, msg);
        8:  874:    if (ret != LDB_SUCCESS) {
    #####:  875:        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) "
        -:  876:                                     "for domain %s!\n",
        -:  877:                                     ret, ldb_errstring(sysdb->ldb),
        -:  878:                                     domain_name));
    #####:  879:        ret = EIO;
    #####:  880:        goto done;
        -:  881:    }
        8:  882:    talloc_zfree(msg);
        -:  883:
        -:  884:    /* == create Groups tree == */
        -:  885:
        8:  886:    msg = ldb_msg_new(tmp_ctx);
        8:  887:    if (!msg) {
    #####:  888:        ret = ENOMEM;
    #####:  889:        goto done;
        -:  890:    }
        8:  891:    msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
        -:  892:                             SYSDB_TMPL_GROUP_BASE, domain_name);
        8:  893:    if (!msg->dn) {
    #####:  894:        ret = ENOMEM;
    #####:  895:        goto done;
        -:  896:    }
        8:  897:    ret = ldb_msg_add_string(msg, "cn", "Groups");
        8:  898:    if (ret != LDB_SUCCESS) {
    #####:  899:        ret = EIO;
    #####:  900:        goto done;
        -:  901:    }
        -:  902:    /* do a synchronous add */
        8:  903:    ret = ldb_add(sysdb->ldb, msg);
        8:  904:    if (ret != LDB_SUCCESS) {
    #####:  905:        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to initialize DB (%d, [%s]) for "
        -:  906:                                     "domain %s!\n",
        -:  907:                                     ret, ldb_errstring(sysdb->ldb),
        -:  908:                                     domain_name));
    #####:  909:        ret = EIO;
    #####:  910:        goto done;
        -:  911:    }
        8:  912:    talloc_zfree(msg);
        -:  913:
        8:  914:    ret = EOK;
        -:  915:
        -:  916:done:
        8:  917:    talloc_zfree(tmp_ctx);
        8:  918:    return ret;
        -:  919:}
        -:  920:
        -:  921:/* Compare versions of sysdb, returns ERRNO accordingly */
        -:  922:static errno_t
    #####:  923:sysdb_version_check(const char *expected,
        -:  924:                    const char *received)
        -:  925:{
        -:  926:    int ret;
        -:  927:    unsigned int exp_major, exp_minor, recv_major, recv_minor;
        -:  928:
    #####:  929:    ret = sscanf(expected, "%u.%u", &exp_major, &exp_minor);
    #####:  930:    if (ret != 2) {
    #####:  931:        return EINVAL;
        -:  932:    }
    #####:  933:    ret = sscanf(received, "%u.%u", &recv_major, &recv_minor);
    #####:  934:    if (ret != 2) {
    #####:  935:        return EINVAL;
        -:  936:    }
        -:  937:
    #####:  938:    if (recv_major > exp_major) {
    #####:  939:        return EUCLEAN;
    #####:  940:    } else if (recv_major < exp_major) {
    #####:  941:        return EMEDIUMTYPE;
        -:  942:    }
        -:  943:
    #####:  944:    if (recv_minor > exp_minor) {
    #####:  945:        return EUCLEAN;
    #####:  946:    } else if (recv_minor < exp_minor) {
    #####:  947:        return EMEDIUMTYPE;
        -:  948:    }
        -:  949:
    #####:  950:    return EOK;
        -:  951:}
        -:  952:
     1527:  953:int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
        -:  954:                               struct sss_domain_info *domain,
        -:  955:                               const char *db_path,
        -:  956:                               bool allow_upgrade,
        -:  957:                               struct sysdb_ctx **_ctx)
        -:  958:{
     1527:  959:    TALLOC_CTX *tmp_ctx = NULL;
        -:  960:    struct sysdb_ctx *sysdb;
        -:  961:    const char *base_ldif;
        -:  962:    struct ldb_ldif *ldif;
        -:  963:    struct ldb_message_element *el;
        -:  964:    struct ldb_result *res;
        -:  965:    struct ldb_dn *verdn;
     1527:  966:    const char *version = NULL;
        -:  967:    int ret;
        -:  968:
     1527:  969:    sysdb = talloc_zero(mem_ctx, struct sysdb_ctx);
     1527:  970:    if (!sysdb) {
    #####:  971:        return ENOMEM;
        -:  972:    }
        -:  973:
     3054:  974:    ret = sysdb_get_db_file(sysdb, domain->provider,
     1527:  975:                            domain->name, db_path,
        -:  976:                            &sysdb->ldb_file);
     1527:  977:    if (ret != EOK) {
    #####:  978:        goto done;
        -:  979:    }
     1527:  980:    DEBUG(5, ("DB File for %s: %s\n", domain->name, sysdb->ldb_file));
        -:  981:
     1527:  982:    ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
     1527:  983:    if (ret != EOK) {
    #####:  984:        DEBUG(1, ("sysdb_ldb_connect failed.\n"));
    #####:  985:        goto done;
        -:  986:    }
        -:  987:
     1527:  988:    tmp_ctx = talloc_new(NULL);
     1527:  989:    if (!tmp_ctx) {
    #####:  990:        ret = ENOMEM;
    #####:  991:        goto done;
        -:  992:    }
        -:  993:
     1527:  994:    verdn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
     1527:  995:    if (!verdn) {
    #####:  996:        ret = EIO;
    #####:  997:        goto done;
        -:  998:    }
        -:  999:
     1527: 1000:    ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
        -: 1001:                     verdn, LDB_SCOPE_BASE,
        -: 1002:                     NULL, NULL);
     1527: 1003:    if (ret != LDB_SUCCESS) {
    #####: 1004:        ret = EIO;
    #####: 1005:        goto done;
        -: 1006:    }
     1527: 1007:    if (res->count > 1) {
    #####: 1008:        ret = EIO;
    #####: 1009:        goto done;
        -: 1010:    }
        -: 1011:
     1527: 1012:    if (res->count == 1) {
     1525: 1013:        el = ldb_msg_find_element(res->msgs[0], "version");
     1525: 1014:        if (!el) {
    #####: 1015:            ret = EIO;
    #####: 1016:            goto done;
        -: 1017:        }
        -: 1018:
     1525: 1019:        if (el->num_values != 1) {
    #####: 1020:            ret = EINVAL;
    #####: 1021:            goto done;
        -: 1022:        }
     3050: 1023:        version = talloc_strndup(tmp_ctx,
     1525: 1024:                                 (char *)(el->values[0].data),
     1525: 1025:                                 el->values[0].length);
     1525: 1026:        if (!version) {
    #####: 1027:            ret = ENOMEM;
    #####: 1028:            goto done;
        -: 1029:        }
        -: 1030:
     1525: 1031:        if (strcmp(version, SYSDB_VERSION) == 0) {
        -: 1032:            /* all fine, return */
     1525: 1033:            ret = EOK;
     1525: 1034:            goto done;
        -: 1035:        }
        -: 1036:
    #####: 1037:        if (!allow_upgrade) {
    #####: 1038:            DEBUG(SSSDBG_FATAL_FAILURE,
        -: 1039:                  ("Wrong DB version (got %s expected %s)\n",
        -: 1040:                   version, SYSDB_VERSION));
    #####: 1041:            ret = sysdb_version_check(SYSDB_VERSION, version);
    #####: 1042:            goto done;
        -: 1043:        }
        -: 1044:
    #####: 1045:        DEBUG(SSSDBG_CONF_SETTINGS, ("Upgrading DB [%s] from version: %s\n",
        -: 1046:                  domain->name, version));
        -: 1047:
    #####: 1048:        if (strcmp(version, SYSDB_VERSION_0_3) == 0) {
    #####: 1049:            ret = sysdb_upgrade_03(sysdb, &version);
    #####: 1050:            if (ret != EOK) {
    #####: 1051:                goto done;
        -: 1052:            }
        -: 1053:        }
        -: 1054:
    #####: 1055:        if (strcmp(version, SYSDB_VERSION_0_4) == 0) {
    #####: 1056:            ret = sysdb_upgrade_04(sysdb, &version);
    #####: 1057:            if (ret != EOK) {
    #####: 1058:                goto done;
        -: 1059:            }
        -: 1060:        }
        -: 1061:
    #####: 1062:        if (strcmp(version, SYSDB_VERSION_0_5) == 0) {
    #####: 1063:            ret = sysdb_upgrade_05(sysdb, &version);
    #####: 1064:            if (ret != EOK) {
    #####: 1065:                goto done;
        -: 1066:            }
        -: 1067:        }
        -: 1068:
    #####: 1069:        if (strcmp(version, SYSDB_VERSION_0_6) == 0) {
    #####: 1070:            ret = sysdb_upgrade_06(sysdb, &version);
    #####: 1071:            if (ret != EOK) {
    #####: 1072:                goto done;
        -: 1073:            }
        -: 1074:        }
        -: 1075:
    #####: 1076:        if (strcmp(version, SYSDB_VERSION_0_7) == 0) {
    #####: 1077:            ret = sysdb_upgrade_07(sysdb, &version);
    #####: 1078:            if (ret != EOK) {
    #####: 1079:                goto done;
        -: 1080:            }
        -: 1081:        }
        -: 1082:
    #####: 1083:        if (strcmp(version, SYSDB_VERSION_0_8) == 0) {
    #####: 1084:            ret = sysdb_upgrade_08(sysdb, &version);
    #####: 1085:            if (ret != EOK) {
    #####: 1086:                goto done;
        -: 1087:            }
        -: 1088:        }
        -: 1089:
    #####: 1090:        if (strcmp(version, SYSDB_VERSION_0_9) == 0) {
    #####: 1091:            ret = sysdb_upgrade_09(sysdb, &version);
    #####: 1092:            if (ret != EOK) {
    #####: 1093:                goto done;
        -: 1094:            }
        -: 1095:        }
        -: 1096:
    #####: 1097:        if (strcmp(version, SYSDB_VERSION_0_10) == 0) {
    #####: 1098:            ret = sysdb_upgrade_10(sysdb, domain, &version);
    #####: 1099:            if (ret != EOK) {
    #####: 1100:                goto done;
        -: 1101:            }
        -: 1102:        }
        -: 1103:
    #####: 1104:        if (strcmp(version, SYSDB_VERSION_0_11) == 0) {
    #####: 1105:            ret = sysdb_upgrade_11(sysdb, domain, &version);
    #####: 1106:            if (ret != EOK) {
    #####: 1107:                goto done;
        -: 1108:            }
        -: 1109:        }
        -: 1110:
    #####: 1111:        if (strcmp(version, SYSDB_VERSION_0_12) == 0) {
    #####: 1112:            ret = sysdb_upgrade_12(sysdb, &version);
    #####: 1113:            if (ret != EOK) {
    #####: 1114:                goto done;
        -: 1115:            }
        -: 1116:        }
        -: 1117:
    #####: 1118:        if (strcmp(version, SYSDB_VERSION_0_13) == 0) {
    #####: 1119:            ret = sysdb_upgrade_13(sysdb, &version);
    #####: 1120:            if (ret != EOK) {
    #####: 1121:                goto done;
        -: 1122:            }
        -: 1123:        }
        -: 1124:
    #####: 1125:        if (strcmp(version, SYSDB_VERSION_0_14) == 0) {
    #####: 1126:            ret = sysdb_upgrade_14(sysdb, &version);
    #####: 1127:            if (ret != EOK) {
    #####: 1128:                goto done;
        -: 1129:            }
        -: 1130:        }
        -: 1131:
        -: 1132:        /* The version should now match SYSDB_VERSION.
        -: 1133:         * If not, it means we didn't match any of the
        -: 1134:         * known older versions. The DB might be
        -: 1135:         * corrupt or generated by a newer version of
        -: 1136:         * SSSD.
        -: 1137:         */
    #####: 1138:        if (strcmp(version, SYSDB_VERSION) == 0) {
        -: 1139:            /* The cache has been upgraded.
        -: 1140:             * We need to reopen the LDB to ensure that
        -: 1141:             * any changes made above take effect.
        -: 1142:             */
    #####: 1143:            talloc_zfree(sysdb->ldb);
    #####: 1144:            ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
    #####: 1145:            if (ret != EOK) {
    #####: 1146:                DEBUG(SSSDBG_CRIT_FAILURE, ("sysdb_ldb_connect failed.\n"));
        -: 1147:            }
    #####: 1148:            goto done;
        -: 1149:        }
        -: 1150:
    #####: 1151:        DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n",
        -: 1152:                 version?version:"not found", SYSDB_VERSION, domain->name));
    #####: 1153:        ret = sysdb_version_check(SYSDB_VERSION, version);
    #####: 1154:        goto done;
        -: 1155:    }
        -: 1156:
        -: 1157:    /* SYSDB_BASE does not exists, means db is empty, populate */
        -: 1158:
        2: 1159:    base_ldif = SYSDB_BASE_LDIF;
       14: 1160:    while ((ldif = ldb_ldif_read_string(sysdb->ldb, &base_ldif))) {
       10: 1161:        ret = ldb_add(sysdb->ldb, ldif->msg);
       10: 1162:        if (ret != LDB_SUCCESS) {
    #####: 1163:            DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
        -: 1164:                      ret, ldb_errstring(sysdb->ldb), domain->name));
    #####: 1165:            ret = EIO;
    #####: 1166:            goto done;
        -: 1167:        }
       10: 1168:        ldb_ldif_read_free(sysdb->ldb, ldif);
        -: 1169:    }
        -: 1170:
        2: 1171:    ret = sysdb_domain_create(sysdb, domain->name);
        2: 1172:    if (ret != EOK) {
    #####: 1173:        goto done;
        -: 1174:    }
        -: 1175:
        -: 1176:    /* The cache has been newly created.
        -: 1177:     * We need to reopen the LDB to ensure that
        -: 1178:     * all of the special values take effect
        -: 1179:     * (such as enabling the memberOf plugin and
        -: 1180:     * the various indexes).
        -: 1181:     */
        2: 1182:    talloc_zfree(sysdb->ldb);
        2: 1183:    ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
        2: 1184:    if (ret != EOK) {
    #####: 1185:        DEBUG(1, ("sysdb_ldb_connect failed.\n"));
        -: 1186:    }
        -: 1187:
        -: 1188:done:
     1527: 1189:    talloc_free(tmp_ctx);
     1527: 1190:    if (ret == EOK) {
     1527: 1191:        *_ctx = sysdb;
        -: 1192:    } else {
    #####: 1193:        talloc_free(sysdb);
        -: 1194:    }
     1527: 1195:    return ret;
        -: 1196:}
        -: 1197:
    #####: 1198:int sysdb_init(TALLOC_CTX *mem_ctx,
        -: 1199:               struct sss_domain_info *domains,
        -: 1200:               const char *alt_db_path,
        -: 1201:               bool allow_upgrade)
        -: 1202:{
        -: 1203:    struct sss_domain_info *dom;
        -: 1204:    struct sysdb_ctx *sysdb;
        -: 1205:    const char *db_path;
        -: 1206:    int ret;
        -: 1207:
    #####: 1208:    if (alt_db_path) {
    #####: 1209:        db_path = alt_db_path;
        -: 1210:    } else {
    #####: 1211:        db_path = DB_PATH;
        -: 1212:    }
        -: 1213:
    #####: 1214:    if (allow_upgrade) {
        -: 1215:        /* check if we have an old sssd.ldb to upgrade */
    #####: 1216:        ret = sysdb_check_upgrade_02(domains, db_path);
    #####: 1217:        if (ret != EOK) {
    #####: 1218:            return ret;
        -: 1219:        }
        -: 1220:    }
        -: 1221:
        -: 1222:    /* open a db for each domain */
    #####: 1223:    for (dom = domains; dom; dom = dom->next) {
        -: 1224:
    #####: 1225:        ret = sysdb_domain_init_internal(mem_ctx, dom, db_path,
        -: 1226:                                         allow_upgrade, &sysdb);
    #####: 1227:        if (ret != EOK) {
    #####: 1228:            return ret;
        -: 1229:        }
        -: 1230:
    #####: 1231:        dom->sysdb = talloc_move(dom, &sysdb);
        -: 1232:    }
        -: 1233:
    #####: 1234:    return EOK;
        -: 1235:}
        -: 1236:
     1527: 1237:int sysdb_domain_init(TALLOC_CTX *mem_ctx,
        -: 1238:                      struct sss_domain_info *domain,
        -: 1239:                      const char *db_path,
        -: 1240:                      struct sysdb_ctx **_ctx)
        -: 1241:{
     1527: 1242:    return sysdb_domain_init_internal(mem_ctx, domain,
        -: 1243:                                      db_path, false, _ctx);
        -: 1244:}
        -: 1245:
       70: 1246:int compare_ldb_dn_comp_num(const void *m1, const void *m2)
        -: 1247:{
       70: 1248:    struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1),
        -: 1249:                                               struct ldb_message);
       70: 1250:    struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2),
        -: 1251:                                               struct ldb_message);
        -: 1252:
       70: 1253:    return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn);
        -: 1254:}
        -: 1255:
        4: 1256:int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,
        -: 1257:                             const char *newname)
        -: 1258:{
        4: 1259:    struct ldb_message_element *e = NULL;
        -: 1260:    int i;
        -: 1261:    const char *dummy;
        -: 1262:
        4: 1263:    if (attrs == NULL || oldname == NULL || newname == NULL) return EINVAL;
        -: 1264:
       14: 1265:    for (i = 0; i < attrs->num; i++) {
       12: 1266:        if (strcasecmp(oldname, attrs->a[i].name) == 0) {
        4: 1267:            e = &(attrs->a[i]);
        -: 1268:        }
       12: 1269:        if (strcasecmp(newname, attrs->a[i].name) == 0) {
        2: 1270:            DEBUG(3, ("New attribute name [%s] already exists.\n", newname));
        2: 1271:            return EEXIST;
        -: 1272:        }
        -: 1273:    }
        -: 1274:
        2: 1275:    if (e != NULL) {
        2: 1276:        dummy = talloc_strdup(attrs, newname);
        2: 1277:        if (dummy == NULL) {
    #####: 1278:            DEBUG(1, ("talloc_strdup failed.\n"));
    #####: 1279:            return ENOMEM;
        -: 1280:        }
        -: 1281:
        2: 1282:        talloc_free(discard_const(e->name));
        2: 1283:        e->name = dummy;
        -: 1284:    }
        -: 1285:
        2: 1286:    return EOK;
        -: 1287:}
        -: 1288:
        -: 1289:/* Search for all incidences of attr_name in a list of
        -: 1290: * sysdb_attrs and add their value to a list
        -: 1291: *
        -: 1292: * TODO: Currently only works for single-valued
        -: 1293: * attributes. Multi-valued attributes will return
        -: 1294: * only the first entry
        -: 1295: */
        2: 1296:errno_t sysdb_attrs_to_list(TALLOC_CTX *mem_ctx,
        -: 1297:                            struct sysdb_attrs **attrs,
        -: 1298:                            int attr_count,
        -: 1299:                            const char *attr_name,
        -: 1300:                            char ***_list)
        -: 1301:{
        -: 1302:    int attr_idx;
        -: 1303:    int i;
        -: 1304:    char **list;
        -: 1305:    char **tmp_list;
        -: 1306:    int list_idx;
        -: 1307:
        2: 1308:    *_list = NULL;
        -: 1309:
        -: 1310:    /* Assume that every attrs entry contains the attr_name
        -: 1311:     * This may waste a little memory if some entries don't
        -: 1312:     * have the attribute, but it will save us the trouble
        -: 1313:     * of continuously resizing the array.
        -: 1314:     */
        2: 1315:    list = talloc_array(mem_ctx, char *, attr_count+1);
        2: 1316:    if (!list) {
    #####: 1317:        return ENOMEM;
        -: 1318:    }
        -: 1319:
        2: 1320:    list_idx = 0;
        -: 1321:    /* Loop through all entries in attrs */
        8: 1322:    for (attr_idx = 0; attr_idx < attr_count; attr_idx++) {
        -: 1323:        /* Examine each attribute within the entry */
        8: 1324:        for (i = 0; i < attrs[attr_idx]->num; i++) {
        6: 1325:            if (strcasecmp(attrs[attr_idx]->a[i].name, attr_name) == 0) {
        -: 1326:                /* Attribute name matches the requested name
        -: 1327:                 * Copy it to the output list
        -: 1328:                 */
        8: 1329:                list[list_idx] = talloc_strdup(
        -: 1330:                        list,
        4: 1331:                        (const char *)attrs[attr_idx]->a[i].values[0].data);
        4: 1332:                if (!list[list_idx]) {
    #####: 1333:                    talloc_free(list);
    #####: 1334:                    return ENOMEM;
        -: 1335:                }
        4: 1336:                list_idx++;
        -: 1337:
        -: 1338:                /* We only support single-valued attributes
        -: 1339:                 * Break here and go on to the next entry
        -: 1340:                 */
        4: 1341:                break;
        -: 1342:            }
        -: 1343:        }
        -: 1344:    }
        -: 1345:
        2: 1346:    list[list_idx] = NULL;
        -: 1347:
        -: 1348:    /* if list_idx < attr_count, do a realloc to
        -: 1349:     * reclaim unused memory
        -: 1350:     */
        2: 1351:    if (list_idx < attr_count) {
        2: 1352:        tmp_list = talloc_realloc(mem_ctx, list, char *, list_idx+1);
        2: 1353:        if (!tmp_list) {
    #####: 1354:            talloc_zfree(list);
    #####: 1355:            return ENOMEM;
        -: 1356:        }
        2: 1357:        list = tmp_list;
        -: 1358:    }
        -: 1359:
        2: 1360:    *_list = list;
        2: 1361:    return EOK;
        -: 1362:}
        -: 1363:
        4: 1364:errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
        -: 1365:                       struct ldb_dn *dn,
        -: 1366:                       const char *attr_name,
        -: 1367:                       bool *value)
        -: 1368:{
        -: 1369:    TALLOC_CTX *tmp_ctx;
        -: 1370:    struct ldb_result *res;
        -: 1371:    errno_t ret;
        -: 1372:    int lret;
        4: 1373:    const char *attrs[2] = {attr_name, NULL};
        -: 1374:
        4: 1375:    tmp_ctx = talloc_new(NULL);
        4: 1376:    if (tmp_ctx == NULL) {
    #####: 1377:        return ENOMEM;
        -: 1378:    }
        -: 1379:
        4: 1380:    lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
        -: 1381:                      attrs, NULL);
        4: 1382:    if (lret != LDB_SUCCESS) {
    #####: 1383:        ret = sysdb_error_to_errno(lret);
    #####: 1384:        goto done;
        -: 1385:    }
        -: 1386:
        4: 1387:    if (res->count == 0) {
        -: 1388:        /* This entry has not been populated in LDB
        -: 1389:         * This is a common case, as unlike LDAP,
        -: 1390:         * LDB does not need to have all of its parent
        -: 1391:         * objects actually exist.
        -: 1392:         * This object in the sysdb exists mostly just
        -: 1393:         * to contain this attribute.
        -: 1394:         */
        2: 1395:        *value = false;
        2: 1396:        ret = EOK;
        2: 1397:        goto done;
        2: 1398:    } else if (res->count != 1) {
    #####: 1399:        DEBUG(SSSDBG_CRIT_FAILURE,
        -: 1400:              ("Got more than one reply for base search!\n"));
    #####: 1401:        ret = EIO;
    #####: 1402:        goto done;
        -: 1403:    }
        -: 1404:
        2: 1405:    *value = ldb_msg_find_attr_as_bool(res->msgs[0], attr_name, false);
        -: 1406:
        2: 1407:    ret = EOK;
        -: 1408:
        -: 1409:done:
        4: 1410:    talloc_free(tmp_ctx);
        4: 1411:    return ret;
        -: 1412:}
        -: 1413:
        2: 1414:errno_t sysdb_set_bool(struct sysdb_ctx *sysdb,
        -: 1415:                       struct ldb_dn *dn,
        -: 1416:                       const char *cn_value,
        -: 1417:                       const char *attr_name,
        -: 1418:                       bool value)
        -: 1419:{
        2: 1420:    TALLOC_CTX *tmp_ctx = NULL;
        2: 1421:    struct ldb_message *msg = NULL;
        2: 1422:    struct ldb_result *res = NULL;
        -: 1423:    errno_t ret;
        -: 1424:    int lret;
        -: 1425:
        2: 1426:    if (dn == NULL || cn_value == NULL || attr_name == NULL) {
    #####: 1427:        return EINVAL;
        -: 1428:    }
        -: 1429:
        2: 1430:    tmp_ctx = talloc_new(NULL);
        2: 1431:    if (tmp_ctx == NULL) {
    #####: 1432:        return ENOMEM;
        -: 1433:    }
        -: 1434:
        2: 1435:    lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
        -: 1436:                      NULL, NULL);
        2: 1437:    if (lret != LDB_SUCCESS) {
    #####: 1438:        ret = sysdb_error_to_errno(lret);
    #####: 1439:        goto done;
        -: 1440:    }
        -: 1441:
        2: 1442:    msg = ldb_msg_new(tmp_ctx);
        2: 1443:    if (msg == NULL) {
    #####: 1444:        ret = ENOMEM;
    #####: 1445:        goto done;
        -: 1446:    }
        2: 1447:    msg->dn = dn;
        -: 1448:
        2: 1449:    if (res->count == 0) {
        2: 1450:        lret = ldb_msg_add_string(msg, "cn", cn_value);
        2: 1451:        if (lret != LDB_SUCCESS) {
    #####: 1452:            ret = sysdb_error_to_errno(lret);
    #####: 1453:            goto done;
        -: 1454:        }
    #####: 1455:    } else if (res->count != 1) {
    #####: 1456:        DEBUG(SSSDBG_CRIT_FAILURE,
        -: 1457:              ("Got more than one reply for base search!\n"));
    #####: 1458:        ret = EIO;
    #####: 1459:        goto done;
        -: 1460:    } else {
    #####: 1461:        lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
    #####: 1462:        if (lret != LDB_SUCCESS) {
    #####: 1463:            ret = sysdb_error_to_errno(lret);
    #####: 1464:            goto done;
        -: 1465:        }
        -: 1466:    }
        -: 1467:
        2: 1468:    lret = ldb_msg_add_string(msg, attr_name, value ? "TRUE" : "FALSE");
        2: 1469:    if (lret != LDB_SUCCESS) {
    #####: 1470:        ret = sysdb_error_to_errno(lret);
    #####: 1471:        goto done;
        -: 1472:    }
        -: 1473:
        2: 1474:    if (res->count) {
    #####: 1475:        lret = ldb_modify(sysdb->ldb, msg);
        -: 1476:    } else {
        2: 1477:        lret = ldb_add(sysdb->ldb, msg);
        -: 1478:    }
        -: 1479:
        2: 1480:    ret = sysdb_error_to_errno(lret);
        -: 1481:
        -: 1482:done:
        2: 1483:    talloc_free(tmp_ctx);
        2: 1484:    return ret;
        -: 1485:}
        -: 1486:
        4: 1487:errno_t sysdb_has_enumerated(struct sysdb_ctx *sysdb,
        -: 1488:                             struct sss_domain_info *domain,
        -: 1489:                             bool *has_enumerated)
        -: 1490:{
        -: 1491:    errno_t ret;
        -: 1492:    struct ldb_dn *dn;
        -: 1493:    TALLOC_CTX *tmp_ctx;
        -: 1494:
        -: 1495:
        4: 1496:    tmp_ctx = talloc_new(NULL);
        4: 1497:    if (!tmp_ctx) {
    #####: 1498:        ret = ENOMEM;
    #####: 1499:        goto done;
        -: 1500:    }
        -: 1501:
        4: 1502:    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain->name);
        4: 1503:    if (!dn) {
    #####: 1504:        ret = ENOMEM;
    #####: 1505:        goto done;
        -: 1506:    }
        -: 1507:
        4: 1508:    ret = sysdb_get_bool(sysdb, dn, SYSDB_HAS_ENUMERATED, has_enumerated);
        -: 1509:
        -: 1510:done:
        4: 1511:    talloc_free(tmp_ctx);
        4: 1512:    return ret;
        -: 1513:}
        -: 1514:
        2: 1515:errno_t sysdb_set_enumerated(struct sysdb_ctx *sysdb,
        -: 1516:                             struct sss_domain_info *domain,
        -: 1517:                             bool enumerated)
        -: 1518:{
        -: 1519:    errno_t ret;
        -: 1520:    TALLOC_CTX *tmp_ctx;
        -: 1521:    struct ldb_dn *dn;
        -: 1522:
        2: 1523:    tmp_ctx = talloc_new(NULL);
        2: 1524:    if (!tmp_ctx) {
    #####: 1525:        ret = ENOMEM;
    #####: 1526:        goto done;
        -: 1527:    }
        -: 1528:
        2: 1529:    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain->name);
        2: 1530:    if (!dn) {
    #####: 1531:        ret = ENOMEM;
    #####: 1532:        goto done;
        -: 1533:    }
        -: 1534:
        2: 1535:    ret = sysdb_set_bool(sysdb, dn, domain->name,
        -: 1536:                         SYSDB_HAS_ENUMERATED, enumerated);
        -: 1537:
        -: 1538:done:
        2: 1539:    talloc_free(tmp_ctx);
        2: 1540:    return ret;
        -: 1541:}
        -: 1542:
    #####: 1543:errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
        -: 1544:                                 struct sysdb_attrs *attrs,
        -: 1545:                                 const char *ldap_attr,
        -: 1546:                                 const char **_primary)
        -: 1547:{
        -: 1548:    errno_t ret;
    #####: 1549:    char *rdn_attr = NULL;
    #####: 1550:    char *rdn_val = NULL;
        -: 1551:    struct ldb_message_element *sysdb_name_el;
        -: 1552:    struct ldb_message_element *orig_dn_el;
        -: 1553:    size_t i;
    #####: 1554:    TALLOC_CTX *tmp_ctx = NULL;
        -: 1555:
    #####: 1556:    tmp_ctx = talloc_new(NULL);
    #####: 1557:    if (!tmp_ctx) {
    #####: 1558:        return ENOMEM;
        -: 1559:    }
        -: 1560:
    #####: 1561:    ret = sysdb_attrs_get_el(attrs,
        -: 1562:                             SYSDB_NAME,
        -: 1563:                             &sysdb_name_el);
    #####: 1564:    if (ret != EOK || sysdb_name_el->num_values == 0) {
    #####: 1565:        ret = EINVAL;
    #####: 1566:        goto done;
        -: 1567:    }
        -: 1568:
    #####: 1569:    if (sysdb_name_el->num_values == 1) {
        -: 1570:        /* Entry contains only one name. Just return that */
    #####: 1571:        *_primary = (const char *)sysdb_name_el->values[0].data;
    #####: 1572:        ret = EOK;
    #####: 1573:        goto done;
        -: 1574:    }
        -: 1575:
        -: 1576:    /* Multiple values for name. Check whether one matches the RDN */
        -: 1577:
    #####: 1578:    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
    #####: 1579:    if (ret) {
    #####: 1580:        goto done;
        -: 1581:    }
    #####: 1582:    if (orig_dn_el->num_values == 0) {
    #####: 1583:        DEBUG(1, ("Original DN is not available.\n"));
    #####: 1584:        ret = EINVAL;
    #####: 1585:        goto done;
    #####: 1586:    } else if (orig_dn_el->num_values == 1) {
    #####: 1587:        ret = sysdb_get_rdn(sysdb, tmp_ctx,
    #####: 1588:                            (const char *) orig_dn_el->values[0].data,
        -: 1589:                            &rdn_attr,
        -: 1590:                            &rdn_val);
    #####: 1591:        if (ret != EOK) {
    #####: 1592:            DEBUG(1, ("Could not get rdn from [%s]\n",
        -: 1593:                      (const char *) orig_dn_el->values[0].data));
    #####: 1594:            goto done;
        -: 1595:        }
        -: 1596:    } else {
    #####: 1597:        DEBUG(1, ("Should not have more than one origDN\n"));
    #####: 1598:        ret = EINVAL;
    #####: 1599:        goto done;
        -: 1600:    }
        -: 1601:
        -: 1602:    /* First check whether the attribute name matches */
    #####: 1603:    DEBUG(8, ("Comparing attribute names [%s] and [%s]\n",
        -: 1604:              rdn_attr, ldap_attr));
    #####: 1605:    if (strcasecmp(rdn_attr, ldap_attr) != 0) {
        -: 1606:        /* Multiple entries, and the RDN attribute doesn't match.
        -: 1607:         * We have no way of resolving this deterministically,
        -: 1608:         * so we'll use the first value as a fallback.
        -: 1609:         */
    #####: 1610:        DEBUG(3, ("The entry has multiple names and the RDN attribute does "
        -: 1611:                  "not match. Will use the first value as fallback.\n"));
    #####: 1612:        *_primary = (const char *)sysdb_name_el->values[0].data;
    #####: 1613:        ret = EOK;
    #####: 1614:        goto done;
        -: 1615:    }
        -: 1616:
    #####: 1617:    for (i = 0; i < sysdb_name_el->num_values; i++) {
    #####: 1618:        if (strcasecmp(rdn_val,
    #####: 1619:                       (const char *)sysdb_name_el->values[i].data) == 0) {
        -: 1620:            /* This name matches the RDN. Use it */
    #####: 1621:            break;
        -: 1622:        }
        -: 1623:    }
    #####: 1624:    if (i < sysdb_name_el->num_values) {
        -: 1625:        /* Match was found */
    #####: 1626:        *_primary = (const char *)sysdb_name_el->values[i].data;
        -: 1627:    } else {
        -: 1628:        /* If we can't match the name to the RDN, we just have to
        -: 1629:         * throw up our hands. There's no deterministic way to
        -: 1630:         * decide which name is correct.
        -: 1631:         */
    #####: 1632:        DEBUG(1, ("Cannot save entry. Unable to determine groupname\n"));
    #####: 1633:        ret = EINVAL;
    #####: 1634:        goto done;
        -: 1635:    }
        -: 1636:
    #####: 1637:    ret = EOK;
        -: 1638:
        -: 1639:done:
    #####: 1640:    if (ret != EOK) {
    #####: 1641:        DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
        -: 1642:                  ret, strerror(ret)));
        -: 1643:    }
    #####: 1644:    talloc_free(tmp_ctx);
    #####: 1645:    return ret;
        -: 1646:}
        -: 1647:
        -: 1648:/*
        -: 1649: * An entity with multiple names would have multiple SYSDB_NAME attributes
        -: 1650: * after being translated into sysdb names using a map.
        -: 1651: * Given a primary name returned by sysdb_attrs_primary_name(), this function
        -: 1652: * returns the other SYSDB_NAME attribute values so they can be saved as
        -: 1653: * SYSDB_NAME_ALIAS into cache.
        -: 1654: *
        -: 1655: * If lowercase is set, all aliases are duplicated in lowercase as well.
        -: 1656: */
    #####: 1657:errno_t sysdb_attrs_get_aliases(TALLOC_CTX *mem_ctx,
        -: 1658:                                struct sysdb_attrs *attrs,
        -: 1659:                                const char *primary,
        -: 1660:                                bool lowercase,
        -: 1661:                                const char ***_aliases)
        -: 1662:{
    #####: 1663:    TALLOC_CTX *tmp_ctx = NULL;
        -: 1664:    struct ldb_message_element *sysdb_name_el;
        -: 1665:    size_t i, j, ai;
        -: 1666:    errno_t ret;
    #####: 1667:    const char **aliases = NULL;
        -: 1668:    const char *name;
        -: 1669:    char *lower;
        -: 1670:
    #####: 1671:    if (_aliases == NULL) return EINVAL;
        -: 1672:
    #####: 1673:    tmp_ctx = talloc_new(NULL);
    #####: 1674:    if (!tmp_ctx) {
    #####: 1675:        return ENOMEM;
        -: 1676:    }
        -: 1677:
    #####: 1678:    ret = sysdb_attrs_get_el(attrs,
        -: 1679:                             SYSDB_NAME,
        -: 1680:                             &sysdb_name_el);
    #####: 1681:    if (ret != EOK || sysdb_name_el->num_values == 0) {
    #####: 1682:        ret = EINVAL;
    #####: 1683:        goto done;
        -: 1684:    }
        -: 1685:
    #####: 1686:    aliases = talloc_array(tmp_ctx, const char *,
        -: 1687:                           sysdb_name_el->num_values + 1);
    #####: 1688:    if (!aliases) {
    #####: 1689:        ret = ENOMEM;
    #####: 1690:        goto done;
        -: 1691:    }
        -: 1692:
    #####: 1693:    if (lowercase) {
    #####: 1694:        DEBUG(SSSDBG_TRACE_INTERNAL,
        -: 1695:              ("Domain is case-insensitive; will add lowercased aliases\n"));
        -: 1696:    }
        -: 1697:
    #####: 1698:    ai = 0;
    #####: 1699:    for (i=0; i < sysdb_name_el->num_values; i++) {
    #####: 1700:        name = (const char *)sysdb_name_el->values[i].data;
        -: 1701:
    #####: 1702:        if (lowercase) {
        -: 1703:            /* Domain is case-insensitive. Save the lower-cased version */
    #####: 1704:            lower = sss_tc_utf8_str_tolower(tmp_ctx, name);
    #####: 1705:            if (!lower) {
    #####: 1706:                ret = ENOMEM;
    #####: 1707:                goto done;
        -: 1708:            }
        -: 1709:
    #####: 1710:            for (j=0; j < ai; j++) {
    #####: 1711:                if (sss_utf8_case_eq((const uint8_t *) aliases[j],
        -: 1712:                                     (const uint8_t *) lower) == ENOMATCH) {
    #####: 1713:                    break;
        -: 1714:                }
        -: 1715:            }
        -: 1716:
    #####: 1717:            if (ai == 0 || j < ai) {
    #####: 1718:                aliases[ai] = talloc_strdup(aliases, lower);
    #####: 1719:                if (!aliases[ai]) {
    #####: 1720:                    ret = ENOMEM;
    #####: 1721:                    goto done;
        -: 1722:                }
    #####: 1723:                ai++;
        -: 1724:            }
        -: 1725:        } else {
        -: 1726:            /* Domain is case-sensitive. Save it as-is */
    #####: 1727:            if (strcmp(primary, name) != 0) {
    #####: 1728:                aliases[ai] = talloc_strdup(aliases, name);
    #####: 1729:                if (!aliases[ai]) {
    #####: 1730:                    ret = ENOMEM;
    #####: 1731:                    goto done;
        -: 1732:                }
    #####: 1733:                ai++;
        -: 1734:            }
        -: 1735:        }
        -: 1736:    }
        -: 1737:
    #####: 1738:    aliases[ai] = NULL;
        -: 1739:
    #####: 1740:    ret = EOK;
        -: 1741:
        -: 1742:done:
    #####: 1743:    *_aliases = talloc_steal(mem_ctx, aliases);
    #####: 1744:    talloc_free(tmp_ctx);
    #####: 1745:    return ret;
        -: 1746:}
        -: 1747:
    #####: 1748:errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
        -: 1749:                                      TALLOC_CTX *mem_ctx,
        -: 1750:                                      struct sysdb_attrs **attr_list,
        -: 1751:                                      size_t attr_count,
        -: 1752:                                      const char *ldap_attr,
        -: 1753:                                      char ***name_list)
        -: 1754:{
        -: 1755:    errno_t ret;
        -: 1756:    size_t i, j;
        -: 1757:    char **list;
        -: 1758:    const char *name;
        -: 1759:
        -: 1760:    /* Assume that every entry has a primary name */
    #####: 1761:    list = talloc_array(mem_ctx, char *, attr_count+1);
    #####: 1762:    if (!list) {
    #####: 1763:        return ENOMEM;
        -: 1764:    }
        -: 1765:
    #####: 1766:    j = 0;
    #####: 1767:    for (i = 0; i < attr_count; i++) {
    #####: 1768:        ret = sysdb_attrs_primary_name(sysdb,
    #####: 1769:                                       attr_list[i],
        -: 1770:                                       ldap_attr,
        -: 1771:                                       &name);
    #####: 1772:        if (ret != EOK) {
    #####: 1773:            DEBUG(1, ("Could not determine primary name\n"));
        -: 1774:            /* Skip and continue. Don't advance 'j' */
    #####: 1775:            continue;
        -: 1776:        }
        -: 1777:
    #####: 1778:        list[j] = talloc_strdup(list, name);
    #####: 1779:        if (!list[j]) {
    #####: 1780:            ret = ENOMEM;
    #####: 1781:            goto done;
        -: 1782:        }
        -: 1783:
    #####: 1784:        j++;
        -: 1785:    }
        -: 1786:
        -: 1787:    /* NULL-terminate the list */
    #####: 1788:    list[j] = NULL;
        -: 1789:
    #####: 1790:    *name_list = list;
        -: 1791:
    #####: 1792:    ret = EOK;
        -: 1793:
        -: 1794:done:
    #####: 1795:    if (ret != EOK) {
    #####: 1796:        talloc_free(list);
        -: 1797:    }
    #####: 1798:    return ret;
        -: 1799:}
        -: 1800:
    #####: 1801:errno_t sysdb_get_real_name(TALLOC_CTX *mem_ctx,
        -: 1802:                            struct sysdb_ctx *sysdb,
        -: 1803:                            struct sss_domain_info *domain,
        -: 1804:                            const char *name,
        -: 1805:                            const char **_cname)
        -: 1806:{
        -: 1807:    errno_t ret;
        -: 1808:    TALLOC_CTX *tmp_ctx;
        -: 1809:    struct ldb_result *res;
        -: 1810:    const char *cname;
        -: 1811:
    #####: 1812:    tmp_ctx = talloc_new(NULL);
    #####: 1813:    if (!tmp_ctx) {
    #####: 1814:        return ENOMEM;
        -: 1815:    }
        -: 1816:
    #####: 1817:    ret = sysdb_getpwnam(tmp_ctx, sysdb, domain, name, &res);
    #####: 1818:    if (ret != EOK) {
    #####: 1819:        DEBUG(SSSDBG_OP_FAILURE, ("Cannot canonicalize username\n"));
    #####: 1820:        goto done;
        -: 1821:    }
        -: 1822:
    #####: 1823:    if (res->count == 0) {
        -: 1824:        /* User is not cached yet */
    #####: 1825:        ret = ENOENT;
    #####: 1826:        goto done;
    #####: 1827:    } else if (res->count != 1) {
    #####: 1828:        DEBUG(SSSDBG_CRIT_FAILURE,
        -: 1829:              ("sysdb_getpwnam returned count: [%d]\n", res->count));
    #####: 1830:        ret = EIO;
    #####: 1831:        goto done;
        -: 1832:    }
        -: 1833:
    #####: 1834:    cname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
    #####: 1835:    if (!cname) {
    #####: 1836:        DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no name?\n"));
    #####: 1837:        ret = ENOENT;
    #####: 1838:        goto done;
        -: 1839:    }
        -: 1840:
    #####: 1841:    ret = EOK;
    #####: 1842:    *_cname = talloc_steal(mem_ctx, cname);
        -: 1843:done:
    #####: 1844:    talloc_free(tmp_ctx);
    #####: 1845:    return ret;
        -: 1846:}
        -: 1847:
    #####: 1848:errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count,
        -: 1849:                        struct ldb_message **msgs,
        -: 1850:                        struct sysdb_attrs ***attrs)
        -: 1851:{
        -: 1852:    int i;
        -: 1853:    struct sysdb_attrs **a;
        -: 1854:
    #####: 1855:    a = talloc_array(mem_ctx, struct sysdb_attrs *, count);
    #####: 1856:    if (a == NULL) {
    #####: 1857:        DEBUG(1, ("talloc_array failed.\n"));
    #####: 1858:        return ENOMEM;
        -: 1859:    }
        -: 1860:
    #####: 1861:    for (i = 0; i < count; i++) {
    #####: 1862:        a[i] = talloc(a, struct sysdb_attrs);
    #####: 1863:        if (a[i] == NULL) {
    #####: 1864:            DEBUG(1, ("talloc failed.\n"));
    #####: 1865:            talloc_free(a);
    #####: 1866:            return ENOMEM;
        -: 1867:        }
    #####: 1868:        a[i]->num = msgs[i]->num_elements;
    #####: 1869:        a[i]->a = talloc_steal(a[i], msgs[i]->elements);
        -: 1870:    }
        -: 1871:
    #####: 1872:    *attrs = a;
        -: 1873:
    #####: 1874:    return EOK;
        -: 1875:}
-------------- next part --------------
        -:    0:Source:src/db/sysdb_ops.c
        -:    0:Graph:src/db/sysdb_tests-sysdb_ops.gcno
        -:    0:Data:src/db/sysdb_tests-sysdb_ops.gcda
        -:    0:Runs:9
        -:    0:Programs:7
        -:    1:/*
        -:    2:   SSSD
        -:    3:
        -:    4:   System Database
        -:    5:
        -:    6:   Copyright (C) Simo Sorce <ssorce at redhat.com>	2008
        -:    7:
        -:    8:   This program is free software; you can redistribute it and/or modify
        -:    9:   it under the terms of the GNU General Public License as published by
        -:   10:   the Free Software Foundation; either version 3 of the License, or
        -:   11:   (at your option) any later version.
        -:   12:
        -:   13:   This program is distributed in the hope that it will be useful,
        -:   14:   but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   15:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   16:   GNU General Public License for more details.
        -:   17:
        -:   18:   You should have received a copy of the GNU General Public License
        -:   19:   along with this program.  If not, see <http://www.gnu.org/licenses/>.
        -:   20:*/
        -:   21:
        -:   22:#include "util/util.h"
        -:   23:#include "db/sysdb_private.h"
        -:   24:#include "db/sysdb_services.h"
        -:   25:#include "db/sysdb_autofs.h"
        -:   26:#include "util/crypto/sss_crypto.h"
        -:   27:#include <time.h>
        -:   28:
     5238:   29:int add_string(struct ldb_message *msg, int flags,
        -:   30:               const char *attr, const char *value)
        -:   31:{
        -:   32:    int ret;
        -:   33:
     5238:   34:    ret = ldb_msg_add_empty(msg, attr, flags, NULL);
     5238:   35:    if (ret == LDB_SUCCESS) {
     5238:   36:        ret = ldb_msg_add_string(msg, attr, value);
     5238:   37:        if (ret == LDB_SUCCESS) return EOK;
        -:   38:    }
    #####:   39:    return ENOMEM;
        -:   40:}
        -:   41:
     3368:   42:int add_ulong(struct ldb_message *msg, int flags,
        -:   43:              const char *attr, unsigned long value)
        -:   44:{
        -:   45:    int ret;
        -:   46:
     3368:   47:    ret = ldb_msg_add_empty(msg, attr, flags, NULL);
     3368:   48:    if (ret == LDB_SUCCESS) {
     3368:   49:        ret = ldb_msg_add_fmt(msg, attr, "%lu", value);
     3368:   50:        if (ret == LDB_SUCCESS) return EOK;
        -:   51:    }
    #####:   52:    return ENOMEM;
        -:   53:}
        -:   54:
    #####:   55:static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr)
        -:   56:{
    #####:   57:    const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr);
        -:   58:    long long int l;
        -:   59:
    #####:   60:    if (!v || !v->data) {
    #####:   61:        return 0;
        -:   62:    }
        -:   63:
    #####:   64:    errno = 0;
    #####:   65:    l = strtoll((const char *)v->data, NULL, 10);
    #####:   66:    if (errno) {
    #####:   67:        return (uint32_t)-1;
        -:   68:    }
        -:   69:
    #####:   70:    if (l < 0 || l > ((uint32_t)(-1))) {
    #####:   71:        return (uint32_t)-1;
        -:   72:    }
        -:   73:
    #####:   74:    return l;
        -:   75:}
        -:   76:
      315:   77:static int sss_ldb_modify_permissive(struct ldb_context *ldb,
        -:   78:                                     struct ldb_message *msg)
        -:   79:{
        -:   80:    struct ldb_request *req;
      315:   81:    int ret = EOK;
        -:   82:
      315:   83:    ret = ldb_build_mod_req(&req, ldb, ldb,
        -:   84:                            msg,
        -:   85:                            NULL,
        -:   86:                            NULL,
        -:   87:                            ldb_op_default_callback,
        -:   88:                            NULL);
        -:   89:
      315:   90:    if (ret != LDB_SUCCESS) return ret;
        -:   91:
      315:   92:    ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID,
        -:   93:                                  false, NULL);
      315:   94:    if (ret != LDB_SUCCESS) {
    #####:   95:        talloc_free(req);
    #####:   96:        return ret;
        -:   97:    }
        -:   98:
      315:   99:    ret = ldb_request(ldb, req);
      315:  100:    if (ret == LDB_SUCCESS) {
      315:  101:        ret = ldb_wait(req->handle, LDB_WAIT_ALL);
        -:  102:    }
        -:  103:
      315:  104:    talloc_free(req);
        -:  105:
      315:  106:    return ret;
        -:  107:}
        -:  108:
        -:  109:#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0)
        -:  110:
        -:  111:
        -:  112:/* =Remove-Entry-From-Sysdb=============================================== */
        -:  113:
     1575:  114:int sysdb_delete_entry(struct sysdb_ctx *sysdb,
        -:  115:                       struct ldb_dn *dn,
        -:  116:                       bool ignore_not_found)
        -:  117:{
        -:  118:    int ret;
        -:  119:
     1575:  120:    ret = ldb_delete(sysdb->ldb, dn);
     1575:  121:    switch (ret) {
        -:  122:    case LDB_SUCCESS:
     1575:  123:        return EOK;
        -:  124:    case LDB_ERR_NO_SUCH_OBJECT:
    #####:  125:        if (ignore_not_found) {
    #####:  126:            return EOK;
        -:  127:        }
        -:  128:        /* fall through */
        -:  129:    default:
    #####:  130:        DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
        -:  131:                  ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
    #####:  132:        return sysdb_error_to_errno(ret);
        -:  133:    }
        -:  134:}
        -:  135:
        -:  136:/* =Remove-Subentries-From-Sysdb=========================================== */
        -:  137:
       27:  138:int sysdb_delete_recursive(struct sysdb_ctx *sysdb,
        -:  139:                           struct ldb_dn *dn,
        -:  140:                           bool ignore_not_found)
        -:  141:{
       27:  142:    const char *no_attrs[] = { NULL };
        -:  143:    struct ldb_message **msgs;
        -:  144:    size_t msgs_count;
        -:  145:    int ret;
        -:  146:    int i;
        -:  147:    TALLOC_CTX *tmp_ctx;
        -:  148:
       27:  149:    tmp_ctx = talloc_new(NULL);
       27:  150:    if (!tmp_ctx) {
    #####:  151:        return ENOMEM;
        -:  152:    }
        -:  153:
       27:  154:    ret = ldb_transaction_start(sysdb->ldb);
       27:  155:    if (ret) {
    #####:  156:        ret = sysdb_error_to_errno(ret);
    #####:  157:        goto done;
        -:  158:    }
        -:  159:
       27:  160:    ret = sysdb_search_entry(tmp_ctx, sysdb, dn,
        -:  161:                             LDB_SCOPE_SUBTREE, "(distinguishedName=*)",
        -:  162:                             no_attrs, &msgs_count, &msgs);
       27:  163:    if (ret) {
    #####:  164:        if (ignore_not_found && ret == ENOENT) {
    #####:  165:            ret = EOK;
        -:  166:        }
    #####:  167:        if (ret) {
    #####:  168:            DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret)));
        -:  169:        }
    #####:  170:        goto done;
        -:  171:    }
        -:  172:
       27:  173:    DEBUG(9, ("Found [%d] items to delete.\n", msgs_count));
        -:  174:
       27:  175:    qsort(msgs, msgs_count,
        -:  176:          sizeof(struct ldb_message *), compare_ldb_dn_comp_num);
        -:  177:
      198:  178:    for (i = 0; i < msgs_count; i++) {
      171:  179:        DEBUG(9 ,("Trying to delete [%s].\n",
        -:  180:                  ldb_dn_get_linearized(msgs[i]->dn)));
        -:  181:
      171:  182:        ret = sysdb_delete_entry(sysdb, msgs[i]->dn, false);
      171:  183:        if (ret) {
    #####:  184:            goto done;
        -:  185:        }
        -:  186:    }
        -:  187:
        -:  188:done:
       27:  189:    if (ret == EOK) {
       27:  190:        ret = ldb_transaction_commit(sysdb->ldb);
       27:  191:        ret = sysdb_error_to_errno(ret);
        -:  192:    } else {
    #####:  193:        ldb_transaction_cancel(sysdb->ldb);
        -:  194:    }
       27:  195:    talloc_free(tmp_ctx);
       27:  196:    return ret;
        -:  197:}
        -:  198:
        -:  199:
        -:  200:/* =Search-Entry========================================================== */
        -:  201:
    11641:  202:int sysdb_search_entry(TALLOC_CTX *mem_ctx,
        -:  203:                       struct sysdb_ctx *sysdb,
        -:  204:                       struct ldb_dn *base_dn,
        -:  205:                       int scope,
        -:  206:                       const char *filter,
        -:  207:                       const char **attrs,
        -:  208:                       size_t *msgs_count,
        -:  209:                       struct ldb_message ***msgs)
        -:  210:{
        -:  211:    struct ldb_result *res;
        -:  212:    int ret;
        -:  213:
    11641:  214:    ret = ldb_search(sysdb->ldb, mem_ctx, &res,
        -:  215:                     base_dn, scope, attrs,
        -:  216:                     filter?"%s":NULL, filter);
    11641:  217:    if (ret) {
    #####:  218:        return sysdb_error_to_errno(ret);
        -:  219:    }
        -:  220:
    11641:  221:    *msgs_count = res->count;
    11641:  222:    *msgs = talloc_steal(mem_ctx, res->msgs);
        -:  223:
    11641:  224:    if (res->count == 0) {
     4369:  225:        return ENOENT;
        -:  226:    }
        -:  227:
     7272:  228:    return EOK;
        -:  229:}
        -:  230:
        -:  231:
        -:  232:/* =Search-User-by-[UID/NAME]============================================= */
        -:  233:
     1485:  234:int sysdb_search_user_by_name(TALLOC_CTX *mem_ctx,
        -:  235:                              struct sysdb_ctx *sysdb,
        -:  236:                              struct sss_domain_info *domain,
        -:  237:                              const char *name,
        -:  238:                              const char **attrs,
        -:  239:                              struct ldb_message **msg)
        -:  240:{
        -:  241:    TALLOC_CTX *tmp_ctx;
     1485:  242:    const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
     1485:  243:    struct ldb_message **msgs = NULL;
        -:  244:    struct ldb_dn *basedn;
     1485:  245:    size_t msgs_count = 0;
        -:  246:    int ret;
        -:  247:
     1485:  248:    tmp_ctx = talloc_new(NULL);
     1485:  249:    if (!tmp_ctx) {
    #####:  250:        return ENOMEM;
        -:  251:    }
        -:  252:
     1485:  253:    basedn = sysdb_user_dn(sysdb, tmp_ctx, domain, name);
     1485:  254:    if (!basedn) {
    #####:  255:        ret = ENOMEM;
    #####:  256:        goto done;
        -:  257:    }
        -:  258:
     1485:  259:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
        -:  260:                             attrs?attrs:def_attrs, &msgs_count, &msgs);
     1485:  261:    if (ret) {
     1206:  262:        goto done;
        -:  263:    }
        -:  264:
      279:  265:    *msg = talloc_steal(mem_ctx, msgs[0]);
        -:  266:
        -:  267:done:
     1485:  268:    if (ret == ENOENT) {
     1206:  269:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  270:    }
      279:  271:    else if (ret) {
    #####:  272:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  273:    }
     1485:  274:    talloc_zfree(tmp_ctx);
     1485:  275:    return ret;
        -:  276:}
        -:  277:
      531:  278:int sysdb_search_user_by_uid(TALLOC_CTX *mem_ctx,
        -:  279:                             struct sysdb_ctx *sysdb,
        -:  280:                             struct sss_domain_info *domain,
        -:  281:                             uid_t uid,
        -:  282:                             const char **attrs,
        -:  283:                             struct ldb_message **msg)
        -:  284:{
        -:  285:    TALLOC_CTX *tmp_ctx;
      531:  286:    const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
      531:  287:    struct ldb_message **msgs = NULL;
        -:  288:    struct ldb_dn *basedn;
      531:  289:    size_t msgs_count = 0;
        -:  290:    char *filter;
        -:  291:    int ret;
        -:  292:
      531:  293:    tmp_ctx = talloc_new(NULL);
      531:  294:    if (!tmp_ctx) {
    #####:  295:        return ENOMEM;
        -:  296:    }
        -:  297:
      531:  298:    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -:  299:                            SYSDB_TMPL_USER_BASE, domain->name);
      531:  300:    if (!basedn) {
    #####:  301:        ret = ENOMEM;
    #####:  302:        goto done;
        -:  303:    }
        -:  304:
      531:  305:    filter = talloc_asprintf(tmp_ctx, SYSDB_PWUID_FILTER, (unsigned long)uid);
      531:  306:    if (!filter) {
    #####:  307:        ret = ENOMEM;
    #####:  308:        goto done;
        -:  309:    }
        -:  310:
        -:  311:    /* Use SUBTREE scope here, not ONELEVEL
        -:  312:     * There is a bug in LDB that makes ONELEVEL searches extremely
        -:  313:     * slow (it ignores indexing)
        -:  314:     */
      531:  315:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
        -:  316:                             attrs?attrs:def_attrs, &msgs_count, &msgs);
      531:  317:    if (ret) {
      360:  318:        goto done;
        -:  319:    }
        -:  320:
      171:  321:    *msg = talloc_steal(mem_ctx, msgs[0]);
        -:  322:
        -:  323:done:
      531:  324:    if (ret == ENOENT) {
      360:  325:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  326:    }
      171:  327:    else if (ret) {
    #####:  328:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  329:    }
        -:  330:
      531:  331:    talloc_zfree(tmp_ctx);
      531:  332:    return ret;
        -:  333:}
        -:  334:
        -:  335:
        -:  336:/* =Search-Group-by-[GID/NAME]============================================ */
        -:  337:
     1251:  338:int sysdb_search_group_by_name(TALLOC_CTX *mem_ctx,
        -:  339:                               struct sysdb_ctx *sysdb,
        -:  340:                               struct sss_domain_info *domain,
        -:  341:                               const char *name,
        -:  342:                               const char **attrs,
        -:  343:                               struct ldb_message **msg)
        -:  344:{
        -:  345:    TALLOC_CTX *tmp_ctx;
        -:  346:    static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
     1251:  347:    struct ldb_message **msgs = NULL;
        -:  348:    struct ldb_dn *basedn;
     1251:  349:    size_t msgs_count = 0;
        -:  350:    int ret;
        -:  351:
     1251:  352:    tmp_ctx = talloc_new(NULL);
     1251:  353:    if (!tmp_ctx) {
    #####:  354:        return ENOMEM;
        -:  355:    }
        -:  356:
     1251:  357:    basedn = sysdb_group_dn(sysdb, tmp_ctx, domain, name);
     1251:  358:    if (!basedn) {
    #####:  359:        ret = ENOMEM;
    #####:  360:        goto done;
        -:  361:    }
        -:  362:
     1251:  363:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
        -:  364:                             attrs?attrs:def_attrs, &msgs_count, &msgs);
     1251:  365:    if (ret) {
     1206:  366:        goto done;
        -:  367:    }
        -:  368:
       45:  369:    *msg = talloc_steal(mem_ctx, msgs[0]);
        -:  370:
        -:  371:done:
     1251:  372:    if (ret == ENOENT) {
     1206:  373:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  374:    }
       45:  375:    else if (ret) {
    #####:  376:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  377:    }
     1251:  378:    talloc_zfree(tmp_ctx);
     1251:  379:    return ret;
        -:  380:}
        -:  381:
     7146:  382:int sysdb_search_group_by_gid(TALLOC_CTX *mem_ctx,
        -:  383:                              struct sysdb_ctx *sysdb,
        -:  384:                              struct sss_domain_info *domain,
        -:  385:                              gid_t gid,
        -:  386:                              const char **attrs,
        -:  387:                              struct ldb_message **msg)
        -:  388:{
        -:  389:    TALLOC_CTX *tmp_ctx;
     7146:  390:    const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
     7146:  391:    struct ldb_message **msgs = NULL;
        -:  392:    struct ldb_dn *basedn;
     7146:  393:    size_t msgs_count = 0;
        -:  394:    char *filter;
        -:  395:    int ret;
        -:  396:
     7146:  397:    tmp_ctx = talloc_new(NULL);
     7146:  398:    if (!tmp_ctx) {
    #####:  399:        return ENOMEM;
        -:  400:    }
        -:  401:
     7146:  402:    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -:  403:                            SYSDB_TMPL_GROUP_BASE, domain->name);
     7146:  404:    if (!basedn) {
    #####:  405:        ret = ENOMEM;
    #####:  406:        goto done;
        -:  407:    }
        -:  408:
     7146:  409:    filter = talloc_asprintf(tmp_ctx, SYSDB_GRGID_FILTER, (unsigned long)gid);
     7146:  410:    if (!filter) {
    #####:  411:        ret = ENOMEM;
    #####:  412:        goto done;
        -:  413:    }
        -:  414:
        -:  415:    /* Use SUBTREE scope here, not ONELEVEL
        -:  416:     * There is a bug in LDB that makes ONELEVEL searches extremely
        -:  417:     * slow (it ignores indexing)
        -:  418:     */
     7146:  419:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
        -:  420:                             attrs?attrs:def_attrs, &msgs_count, &msgs);
     7146:  421:    if (ret) {
      972:  422:        goto done;
        -:  423:    }
        -:  424:
     6174:  425:    *msg = talloc_steal(mem_ctx, msgs[0]);
        -:  426:
        -:  427:done:
     7146:  428:    if (ret == ENOENT) {
      972:  429:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  430:    }
     6174:  431:    else if (ret) {
    #####:  432:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  433:    }
        -:  434:
     7146:  435:    talloc_zfree(tmp_ctx);
     7146:  436:    return ret;
        -:  437:}
        -:  438:
        -:  439:
        -:  440:/* =Search-Group-by-Name============================================ */
        -:  441:
      135:  442:int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
        -:  443:                                  struct sysdb_ctx *sysdb,
        -:  444:                                  struct sss_domain_info *domain,
        -:  445:                                  const char *name,
        -:  446:                                  const char **attrs,
        -:  447:                                  struct ldb_message **msg)
        -:  448:{
        -:  449:    TALLOC_CTX *tmp_ctx;
        -:  450:    static const char *def_attrs[] = { SYSDB_NAME, NULL };
      135:  451:    struct ldb_message **msgs = NULL;
        -:  452:    struct ldb_dn *basedn;
      135:  453:    size_t msgs_count = 0;
        -:  454:    int ret;
        -:  455:
      135:  456:    tmp_ctx = talloc_new(NULL);
      135:  457:    if (!tmp_ctx) {
    #####:  458:        return ENOMEM;
        -:  459:    }
        -:  460:
      135:  461:    basedn = sysdb_netgroup_dn(sysdb, tmp_ctx, domain, name);
      135:  462:    if (!basedn) {
    #####:  463:        ret = ENOMEM;
    #####:  464:        goto done;
        -:  465:    }
        -:  466:
      135:  467:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
        -:  468:                             attrs?attrs:def_attrs, &msgs_count, &msgs);
      135:  469:    if (ret) {
    #####:  470:        goto done;
        -:  471:    }
        -:  472:
      135:  473:    *msg = talloc_steal(mem_ctx, msgs[0]);
        -:  474:
        -:  475:done:
      135:  476:    if (ret == ENOENT) {
    #####:  477:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  478:    }
      135:  479:    else if (ret) {
    #####:  480:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  481:    }
      135:  482:    talloc_zfree(tmp_ctx);
      135:  483:    return ret;
        -:  484:}
        -:  485:
        -:  486:/* =Replace-Attributes-On-Entry=========================================== */
        -:  487:
     2313:  488:int sysdb_set_entry_attr(struct sysdb_ctx *sysdb,
        -:  489:                         struct ldb_dn *entry_dn,
        -:  490:                         struct sysdb_attrs *attrs,
        -:  491:                         int mod_op)
        -:  492:{
        -:  493:    struct ldb_message *msg;
        -:  494:    int i, ret;
        -:  495:    int lret;
        -:  496:    TALLOC_CTX *tmp_ctx;
        -:  497:
     2313:  498:    tmp_ctx = talloc_new(NULL);
     2313:  499:    if (!tmp_ctx) {
    #####:  500:        return ENOMEM;
        -:  501:    }
        -:  502:
     2313:  503:    if (!entry_dn || attrs->num == 0) {
    #####:  504:        ret = EINVAL;
    #####:  505:        goto done;
        -:  506:    }
        -:  507:
     2313:  508:    msg = ldb_msg_new(tmp_ctx);
     2313:  509:    if (!msg) {
    #####:  510:        ret = ENOMEM;
    #####:  511:        goto done;
        -:  512:    }
        -:  513:
     2313:  514:    msg->dn = entry_dn;
        -:  515:
     2313:  516:    msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
     2313:  517:    if (!msg->elements) {
    #####:  518:        ret = ENOMEM;
    #####:  519:        goto done;
        -:  520:    }
        -:  521:
     9333:  522:    for (i = 0; i < attrs->num; i++) {
     7020:  523:        msg->elements[i] = attrs->a[i];
     7020:  524:        msg->elements[i].flags = mod_op;
        -:  525:    }
        -:  526:
     2313:  527:    msg->num_elements = attrs->num;
        -:  528:
     2313:  529:    lret = ldb_modify(sysdb->ldb, msg);
     2313:  530:    if (lret != LDB_SUCCESS) {
    #####:  531:        DEBUG(SSSDBG_MINOR_FAILURE,
        -:  532:              ("ldb_modify failed: [%s]\n", ldb_strerror(lret)));
        -:  533:    }
        -:  534:
     2313:  535:    ret = sysdb_error_to_errno(lret);
        -:  536:
        -:  537:done:
     2313:  538:    if (ret == ENOENT) {
    #####:  539:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -:  540:    }
     2313:  541:    else if (ret) {
    #####:  542:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  543:    }
     2313:  544:    talloc_zfree(tmp_ctx);
     2313:  545:    return ret;
        -:  546:}
        -:  547:
        -:  548:
        -:  549:/* =Replace-Attributes-On-User============================================ */
        -:  550:
      693:  551:int sysdb_set_user_attr(struct sysdb_ctx *sysdb,
        -:  552:                        struct sss_domain_info *domain,
        -:  553:                        const char *name,
        -:  554:                        struct sysdb_attrs *attrs,
        -:  555:                        int mod_op)
        -:  556:{
        -:  557:    struct ldb_dn *dn;
        -:  558:    TALLOC_CTX *tmp_ctx;
        -:  559:    errno_t ret;
        -:  560:
      693:  561:    tmp_ctx = talloc_new(NULL);
      693:  562:    if (!tmp_ctx) {
    #####:  563:        return ENOMEM;
        -:  564:    }
        -:  565:
      693:  566:    dn = sysdb_user_dn(sysdb, tmp_ctx, domain, name);
      693:  567:    if (!dn) {
    #####:  568:        ret = ENOMEM;
    #####:  569:        goto done;
        -:  570:    }
        -:  571:
      693:  572:    ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
      693:  573:    if (ret != EOK) {
    #####:  574:        goto done;
        -:  575:    }
        -:  576:
      693:  577:    ret = EOK;
        -:  578:done:
      693:  579:    talloc_zfree(tmp_ctx);
      693:  580:    return ret;
        -:  581:}
        -:  582:
        -:  583:
        -:  584:/* =Replace-Attributes-On-Group=========================================== */
        -:  585:
     1485:  586:int sysdb_set_group_attr(struct sysdb_ctx *sysdb,
        -:  587:                         struct sss_domain_info *domain,
        -:  588:                         const char *name,
        -:  589:                         struct sysdb_attrs *attrs,
        -:  590:                         int mod_op)
        -:  591:{
        -:  592:    struct ldb_dn *dn;
        -:  593:    TALLOC_CTX *tmp_ctx;
        -:  594:    errno_t ret;
        -:  595:
     1485:  596:    tmp_ctx = talloc_new(NULL);
     1485:  597:    if (!tmp_ctx) {
    #####:  598:        ret = ENOMEM;
    #####:  599:        goto done;
        -:  600:    }
        -:  601:
     1485:  602:    dn = sysdb_group_dn(sysdb, tmp_ctx, domain, name);
     1485:  603:    if (!dn) {
    #####:  604:        ret = ENOMEM;
    #####:  605:        goto done;
        -:  606:    }
        -:  607:
     1485:  608:    ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
     1485:  609:    if (ret) {
    #####:  610:        goto done;
        -:  611:    }
        -:  612:
     1485:  613:    ret = EOK;
        -:  614:done:
     1485:  615:    talloc_free(tmp_ctx);
     1485:  616:    return ret;
        -:  617:}
        -:  618:
        -:  619:/* =Replace-Attributes-On-Netgroup=========================================== */
        -:  620:
       99:  621:int sysdb_set_netgroup_attr(struct sysdb_ctx *sysdb,
        -:  622:                            struct sss_domain_info *domain,
        -:  623:                            const char *name,
        -:  624:                            struct sysdb_attrs *attrs,
        -:  625:                            int mod_op)
        -:  626:{
        -:  627:    errno_t ret;
        -:  628:    struct ldb_dn *dn;
        -:  629:    TALLOC_CTX *tmp_ctx;
        -:  630:
       99:  631:    tmp_ctx = talloc_new(NULL);
       99:  632:    if (!tmp_ctx) {
    #####:  633:        return ENOMEM;
        -:  634:    }
        -:  635:
       99:  636:    dn = sysdb_netgroup_dn(sysdb, tmp_ctx, domain, name);
       99:  637:    if (!dn) {
    #####:  638:        ret = ENOMEM;
    #####:  639:        goto done;
        -:  640:    }
        -:  641:
       99:  642:    ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
        -:  643:
        -:  644:done:
       99:  645:    talloc_free(tmp_ctx);
       99:  646:    return ret;
        -:  647:}
        -:  648:
        -:  649:/* =Get-New-ID============================================================ */
        -:  650:
        2:  651:int sysdb_get_new_id(struct sysdb_ctx *sysdb,
        -:  652:                     struct sss_domain_info *domain,
        -:  653:                     uint32_t *_id)
        -:  654:{
        -:  655:    TALLOC_CTX *tmp_ctx;
        2:  656:    const char *attrs_1[] = { SYSDB_NEXTID, NULL };
        2:  657:    const char *attrs_2[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL };
        -:  658:    struct ldb_dn *base_dn;
        -:  659:    char *filter;
        2:  660:    uint32_t new_id = 0;
        -:  661:    struct ldb_message **msgs;
        -:  662:    size_t count;
        -:  663:    struct ldb_message *msg;
        -:  664:    uint32_t id;
        -:  665:    int ret;
        -:  666:    int i;
        -:  667:
        2:  668:    tmp_ctx = talloc_new(NULL);
        2:  669:    if (!tmp_ctx) {
    #####:  670:        return ENOMEM;
        -:  671:    }
        -:  672:
        2:  673:    base_dn = sysdb_domain_dn(sysdb, tmp_ctx, domain);
        2:  674:    if (!base_dn) {
    #####:  675:        talloc_zfree(tmp_ctx);
    #####:  676:        return ENOMEM;
        -:  677:    }
        -:  678:
        2:  679:    ret = ldb_transaction_start(sysdb->ldb);
        2:  680:    if (ret) {
    #####:  681:        talloc_zfree(tmp_ctx);
    #####:  682:        ret = sysdb_error_to_errno(ret);
    #####:  683:        return ret;
        -:  684:    }
        -:  685:
        2:  686:    ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_BASE,
        -:  687:                             SYSDB_NEXTID_FILTER, attrs_1, &count, &msgs);
        2:  688:    switch (ret) {
        -:  689:    case EOK:
    #####:  690:        new_id = get_attr_as_uint32(msgs[0], SYSDB_NEXTID);
    #####:  691:        if (new_id == (uint32_t)(-1)) {
    #####:  692:            DEBUG(1, ("Invalid Next ID in domain %s\n", domain->name));
    #####:  693:            ret = ERANGE;
    #####:  694:            goto done;
        -:  695:        }
        -:  696:
    #####:  697:        if (new_id < domain->id_min) {
    #####:  698:            new_id = domain->id_min;
        -:  699:        }
        -:  700:
    #####:  701:        if ((domain->id_max != 0) && (new_id > domain->id_max)) {
    #####:  702:            DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
        -:  703:                      new_id, domain->id_max));
    #####:  704:            ret = ERANGE;
    #####:  705:            goto done;
        -:  706:        }
    #####:  707:        break;
        -:  708:
        -:  709:    case ENOENT:
        -:  710:        /* looks like the domain is not initialized yet, use min_id */
        2:  711:        new_id = domain->id_min;
        2:  712:        break;
        -:  713:
        -:  714:    default:
    #####:  715:        goto done;
        -:  716:    }
        2:  717:    talloc_zfree(msgs);
        2:  718:    count = 0;
        -:  719:
        -:  720:    /* verify the id is actually really free.
        -:  721:     * search all entries with id >= new_id and < max_id */
        2:  722:    if (domain->id_max) {
    #####:  723:        filter = talloc_asprintf(tmp_ctx,
        -:  724:                                 "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))",
        -:  725:                                 SYSDB_UIDNUM, new_id,
        -:  726:                                 SYSDB_UIDNUM, domain->id_max,
        -:  727:                                 SYSDB_GIDNUM, new_id,
        -:  728:                                 SYSDB_GIDNUM, domain->id_max);
        -:  729:    }
        -:  730:    else {
        2:  731:        filter = talloc_asprintf(tmp_ctx,
        -:  732:                                 "(|(%s>=%u)(%s>=%u))",
        -:  733:                                 SYSDB_UIDNUM, new_id,
        -:  734:                                 SYSDB_GIDNUM, new_id);
        -:  735:    }
        2:  736:    if (!filter) {
    #####:  737:        DEBUG(6, ("Error: Out of memory\n"));
    #####:  738:        ret = ENOMEM;
    #####:  739:        goto done;
        -:  740:    }
        -:  741:
        2:  742:    ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_SUBTREE,
        -:  743:                             filter, attrs_2, &count, &msgs);
        2:  744:    switch (ret) {
        -:  745:    /* if anything was found, find the maximum and increment past it */
        -:  746:    case EOK:
    #####:  747:        for (i = 0; i < count; i++) {
    #####:  748:            id = get_attr_as_uint32(msgs[i], SYSDB_UIDNUM);
    #####:  749:            if (id != (uint32_t)(-1)) {
    #####:  750:                if (id > new_id) new_id = id;
        -:  751:            }
    #####:  752:            id = get_attr_as_uint32(msgs[i], SYSDB_GIDNUM);
    #####:  753:            if (id != (uint32_t)(-1)) {
    #####:  754:                if (id > new_id) new_id = id;
        -:  755:            }
        -:  756:        }
        -:  757:
    #####:  758:        new_id++;
        -:  759:
        -:  760:        /* check again we are not falling out of range */
    #####:  761:        if ((domain->id_max != 0) && (new_id > domain->id_max)) {
    #####:  762:            DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
        -:  763:                      new_id, domain->id_max));
    #####:  764:            ret = ERANGE;
    #####:  765:            goto done;
        -:  766:        }
    #####:  767:        break;
        -:  768:
        -:  769:    case ENOENT:
        2:  770:        break;
        -:  771:
        -:  772:    default:
    #####:  773:        goto done;
        -:  774:    }
        -:  775:
        2:  776:    talloc_zfree(msgs);
        2:  777:    count = 0;
        -:  778:
        -:  779:    /* finally store the new next id */
        2:  780:    msg = ldb_msg_new(tmp_ctx);
        2:  781:    if (!msg) {
    #####:  782:        DEBUG(6, ("Error: Out of memory\n"));
    #####:  783:        ret = ENOMEM;
    #####:  784:        goto done;
        -:  785:    }
        2:  786:    msg->dn = base_dn;
        -:  787:
        2:  788:    ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE,
        2:  789:                    SYSDB_NEXTID, new_id + 1);
        2:  790:    if (ret) {
    #####:  791:        goto done;
        -:  792:    }
        -:  793:
        2:  794:    ret = ldb_modify(sysdb->ldb, msg);
        2:  795:    ret = sysdb_error_to_errno(ret);
        -:  796:
        2:  797:    *_id = new_id;
        -:  798:
        -:  799:done:
        2:  800:    if (ret == EOK) {
        2:  801:        ret = ldb_transaction_commit(sysdb->ldb);
        2:  802:        ret = sysdb_error_to_errno(ret);
        -:  803:    } else {
    #####:  804:        ldb_transaction_cancel(sysdb->ldb);
        -:  805:    }
        2:  806:    if (ret) {
    #####:  807:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  808:    }
        2:  809:    talloc_zfree(tmp_ctx);
        2:  810:    return ret;
        -:  811:}
        -:  812:
        -:  813:
        -:  814:/* =Add-Basic-User-NO-CHECKS============================================== */
        -:  815:
      360:  816:int sysdb_add_basic_user(struct sysdb_ctx *sysdb,
        -:  817:                         struct sss_domain_info *domain,
        -:  818:                         const char *name,
        -:  819:                         uid_t uid, gid_t gid,
        -:  820:                         const char *gecos,
        -:  821:                         const char *homedir,
        -:  822:                         const char *shell)
        -:  823:{
        -:  824:    struct ldb_message *msg;
        -:  825:    int ret;
        -:  826:    TALLOC_CTX *tmp_ctx;
        -:  827:
      360:  828:    tmp_ctx = talloc_new(NULL);
      360:  829:    if (!tmp_ctx) {
    #####:  830:        return ENOMEM;
        -:  831:    }
        -:  832:
      360:  833:    msg = ldb_msg_new(tmp_ctx);
      360:  834:    if (!msg) {
    #####:  835:        ret = ENOMEM;
    #####:  836:        goto done;
        -:  837:    }
        -:  838:
        -:  839:    /* user dn */
      360:  840:    msg->dn = sysdb_user_dn(sysdb, msg, domain, name);
      360:  841:    if (!msg->dn) {
    #####:  842:        ERROR_OUT(ret, ENOMEM, done);
        -:  843:    }
        -:  844:
      360:  845:    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
      360:  846:    if (ret) goto done;
        -:  847:
      360:  848:    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
      360:  849:    if (ret) goto done;
        -:  850:
      360:  851:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid);
      360:  852:    if (ret) goto done;
        -:  853:
      360:  854:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
      360:  855:    if (ret) goto done;
        -:  856:
        -:  857:    /* We set gecos to be the same as fullname on user creation,
        -:  858:     * But we will not enforce coherency after that, it's up to
        -:  859:     * admins to decide if they want to keep it in sync if they change
        -:  860:     * one of the 2 */
      360:  861:    if (gecos && *gecos) {
      351:  862:        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos);
      351:  863:        if (ret) goto done;
      351:  864:        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos);
      351:  865:        if (ret) goto done;
        -:  866:    }
        -:  867:
      360:  868:    if (homedir && *homedir) {
      351:  869:        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir);
      351:  870:        if (ret) goto done;
        -:  871:    }
        -:  872:
      360:  873:    if (shell && *shell) {
      351:  874:        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell);
      351:  875:        if (ret) goto done;
        -:  876:    }
        -:  877:
        -:  878:    /* creation time */
      360:  879:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
      360:  880:                    (unsigned long)time(NULL));
      360:  881:    if (ret) goto done;
        -:  882:
      360:  883:    ret = ldb_add(sysdb->ldb, msg);
      360:  884:    ret = sysdb_error_to_errno(ret);
        -:  885:
        -:  886:done:
      360:  887:    if (ret) {
    #####:  888:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -:  889:    }
      360:  890:    talloc_zfree(tmp_ctx);
      360:  891:    return ret;
        -:  892:}
        -:  893:
        -:  894:static errno_t
      315:  895:sysdb_remove_ghost_from_group(struct sysdb_ctx *sysdb,
        -:  896:                              struct ldb_message *group,
        -:  897:                              struct ldb_message_element *alias_el,
        -:  898:                              const char *name,
        -:  899:                              const char *orig_dn,
        -:  900:                              const char *userdn)
        -:  901:{
        -:  902:    TALLOC_CTX *tmp_ctx;
        -:  903:    struct ldb_message *msg;
        -:  904:    struct ldb_message_element *orig_members;
      315:  905:    bool add_member = false;
      315:  906:    errno_t ret = EOK;
        -:  907:    int i;
        -:  908:
      315:  909:    tmp_ctx = talloc_new(NULL);
      315:  910:    if (!tmp_ctx) {
    #####:  911:        return ENOENT;
        -:  912:    }
        -:  913:
      315:  914:    msg = ldb_msg_new(tmp_ctx);
      315:  915:    if (!msg) {
    #####:  916:        ERROR_OUT(ret, ENOMEM, done);
        -:  917:    }
        -:  918:
      315:  919:    msg->dn = group->dn;
        -:  920:
      315:  921:    if (orig_dn == NULL) {
        -:  922:        /* We have no way of telling which groups this user belongs to.
        -:  923:         * Add it to all that reference it in the ghost attribute */
      315:  924:        add_member = true;
        -:  925:    } else {
    #####:  926:        add_member = false;
    #####:  927:        orig_members = ldb_msg_find_element(group, SYSDB_ORIG_MEMBER);
    #####:  928:        if (orig_members) {
    #####:  929:            for (i = 0; i < orig_members->num_values; i++) {
    #####:  930:                if (strcmp((const char *) orig_members->values[i].data,
        -:  931:                            orig_dn) == 0) {
        -:  932:                    /* This is a direct member. Add the member attribute */
    #####:  933:                    add_member = true;
        -:  934:                }
        -:  935:            }
        -:  936:        } else {
        -:  937:            /* Nothing to compare the originalDN with. Let's rely on the
        -:  938:             * memberof plugin to do the right thing during initgroups..
        -:  939:             */
    #####:  940:            add_member = true;
        -:  941:        }
        -:  942:    }
        -:  943:
      315:  944:    if (add_member) {
      315:  945:        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_MEMBER, userdn);
      315:  946:        if (ret) goto done;
        -:  947:    }
        -:  948:
      315:  949:    ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name);
      315:  950:    if (ret) goto done;
        -:  951:
        -:  952:    /* Delete aliases from the ghost attribute as well */
      315:  953:    for (i = 0; i < alias_el->num_values; i++) {
    #####:  954:        if (strcmp((const char *)alias_el->values[i].data, name) == 0) {
    #####:  955:            continue;
        -:  956:        }
    #####:  957:        ret = ldb_msg_add_string(msg, SYSDB_GHOST,
    #####:  958:                (char *) alias_el->values[i].data);
    #####:  959:        if (ret != LDB_SUCCESS) {
    #####:  960:            ERROR_OUT(ret, EINVAL, done);
        -:  961:        }
        -:  962:    }
        -:  963:
        -:  964:
      315:  965:    ret = sss_ldb_modify_permissive(sysdb->ldb, msg);
      315:  966:    ret = sysdb_error_to_errno(ret);
      315:  967:    if (ret != EOK) {
    #####:  968:        goto done;
        -:  969:    }
        -:  970:
      315:  971:    talloc_zfree(msg);
        -:  972:
        -:  973:
        -:  974:done:
      315:  975:    talloc_free(tmp_ctx);
      315:  976:    return ret;
        -:  977:}
        -:  978:
        -:  979:static errno_t
      351:  980:sysdb_remove_ghostattr_from_groups(struct sysdb_ctx *sysdb,
        -:  981:                                   struct sss_domain_info *domain,
        -:  982:                                   const char *orig_dn,
        -:  983:                                   struct sysdb_attrs *attrs,
        -:  984:                                   const char *name)
        -:  985:{
        -:  986:    TALLOC_CTX *tmp_ctx;
        -:  987:    struct ldb_message **groups;
        -:  988:    struct ldb_message_element *alias_el;
        -:  989:    struct ldb_dn *tmpdn;
      351:  990:    const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, SYSDB_ORIG_MEMBER, NULL};
        -:  991:    const char *userdn;
        -:  992:    char *filter;
      351:  993:    errno_t ret = EOK;
      351:  994:    size_t group_count = 0;
        -:  995:    int i;
        -:  996:
      351:  997:    tmp_ctx = talloc_new(NULL);
      351:  998:    if (!tmp_ctx) {
    #####:  999:        return ENOENT;
        -: 1000:    }
        -: 1001:
      351: 1002:    filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name);
      351: 1003:    if (!filter) {
    #####: 1004:        ret = ENOMEM;
    #####: 1005:        goto done;
        -: 1006:    }
      351: 1007:    ret = sysdb_attrs_get_el(attrs, SYSDB_NAME_ALIAS, &alias_el);
      351: 1008:    if (ret != EOK) {
    #####: 1009:        goto done;
        -: 1010:    }
        -: 1011:
      351: 1012:    for (i = 0; i < alias_el->num_values; i++) {
    #####: 1013:        if (strcmp((const char *)alias_el->values[i].data, name) == 0) {
    #####: 1014:            continue;
        -: 1015:        }
    #####: 1016:        filter = talloc_asprintf_append(filter, "(%s=%s)",
    #####: 1017:                                        SYSDB_GHOST, alias_el->values[i].data);
    #####: 1018:        if (filter == NULL) {
    #####: 1019:            ret = ENOMEM;
    #####: 1020:            goto done;
        -: 1021:        }
        -: 1022:    }
        -: 1023:
      351: 1024:    filter = talloc_asprintf_append(filter, ")");
      351: 1025:    if (filter == NULL) {
    #####: 1026:        ret = ENOMEM;
    #####: 1027:        goto done;
        -: 1028:    }
        -: 1029:
      351: 1030:    tmpdn = sysdb_user_dn(sysdb, tmp_ctx, domain, name);
      351: 1031:    if (!tmpdn) {
    #####: 1032:        ERROR_OUT(ret, ENOMEM, done);
        -: 1033:    }
        -: 1034:
      351: 1035:    userdn = ldb_dn_get_linearized(tmpdn);
      351: 1036:    if (!userdn) {
    #####: 1037:        ERROR_OUT(ret, EINVAL, done);
        -: 1038:    }
        -: 1039:
      351: 1040:    tmpdn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -: 1041:                            SYSDB_TMPL_GROUP_BASE, domain->name);
      351: 1042:    if (!tmpdn) {
    #####: 1043:        ret = ENOMEM;
    #####: 1044:        goto done;
        -: 1045:    }
        -: 1046:
        -: 1047:    /* We need to find all groups that contain this object as a ghost user
        -: 1048:     * and replace the ghost user by actual member record in direct parents.
        -: 1049:     * Note that this object can be referred to either by its name or any
        -: 1050:     * of its aliases
        -: 1051:     */
      351: 1052:    ret = sysdb_search_entry(tmp_ctx, sysdb, tmpdn, LDB_SCOPE_SUBTREE, filter,
        -: 1053:                             group_attrs, &group_count, &groups);
      351: 1054:    if (ret != EOK && ret != ENOENT) {
    #####: 1055:        goto done;
        -: 1056:    }
        -: 1057:
      666: 1058:    for (i = 0; i < group_count; i++) {
      315: 1059:        sysdb_remove_ghost_from_group(sysdb, groups[i], alias_el, name, orig_dn, userdn);
        -: 1060:    }
        -: 1061:
      351: 1062:    ret = EOK;
        -: 1063:
        -: 1064:done:
      351: 1065:    talloc_free(tmp_ctx);
      351: 1066:    return ret;
        -: 1067:}
        -: 1068:
        -: 1069:/* =Add-User-Function===================================================== */
        -: 1070:
      369: 1071:int sysdb_add_user(struct sysdb_ctx *sysdb,
        -: 1072:                   struct sss_domain_info *domain,
        -: 1073:                   const char *name,
        -: 1074:                   uid_t uid, gid_t gid,
        -: 1075:                   const char *gecos,
        -: 1076:                   const char *homedir,
        -: 1077:                   const char *shell,
        -: 1078:                   const char *orig_dn,
        -: 1079:                   struct sysdb_attrs *attrs,
        -: 1080:                   int cache_timeout,
        -: 1081:                   time_t now)
        -: 1082:{
        -: 1083:    TALLOC_CTX *tmp_ctx;
        -: 1084:    struct ldb_message *msg;
        -: 1085:    struct sysdb_attrs *id_attrs;
        -: 1086:    uint32_t id;
        -: 1087:    int ret;
        -: 1088:
      369: 1089:    if (domain->mpg) {
      369: 1090:        if (gid != 0) {
    #####: 1091:            DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n"));
    #####: 1092:            return EINVAL;
        -: 1093:        }
      369: 1094:        gid = uid;
        -: 1095:    }
        -: 1096:
      387: 1097:    if (domain->id_max != 0 && uid != 0 &&
       36: 1098:        (uid < domain->id_min || uid > domain->id_max)) {
    #####: 1099:        DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n",
        -: 1100:                  uid, domain->id_min, domain->id_max));
    #####: 1101:        return ERANGE;
        -: 1102:    }
        -: 1103:
      387: 1104:    if (domain->id_max != 0 && gid != 0 &&
       36: 1105:        (gid < domain->id_min || gid > domain->id_max)) {
    #####: 1106:        DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
        -: 1107:                  gid, domain->id_min, domain->id_max));
    #####: 1108:        return ERANGE;
        -: 1109:    }
        -: 1110:
      369: 1111:    tmp_ctx = talloc_new(NULL);
      369: 1112:    if (!tmp_ctx) {
    #####: 1113:        return ENOMEM;
        -: 1114:    }
        -: 1115:
      369: 1116:    ret = ldb_transaction_start(sysdb->ldb);
      369: 1117:    if (ret) {
    #####: 1118:        ret = sysdb_error_to_errno(ret);
    #####: 1119:        talloc_free(tmp_ctx);
    #####: 1120:        return ret;
        -: 1121:    }
        -: 1122:
      369: 1123:    if (domain->mpg) {
        -: 1124:        /* In MPG domains you can't have groups with the same name as users,
        -: 1125:         * search if a group with the same name exists.
        -: 1126:         * Don't worry about users, if we try to add a user with the same
        -: 1127:         * name the operation will fail */
        -: 1128:
      369: 1129:        ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain,
        -: 1130:                                         name, NULL, &msg);
      369: 1131:        if (ret != ENOENT) {
    #####: 1132:            if (ret == EOK) ret = EEXIST;
    #####: 1133:            goto done;
        -: 1134:        }
        -: 1135:    }
        -: 1136:
        -: 1137:    /* check no other user with the same uid exist */
      369: 1138:    if (uid != 0) {
      369: 1139:        ret = sysdb_search_user_by_uid(tmp_ctx, sysdb, domain,
        -: 1140:                                       uid, NULL, &msg);
      369: 1141:        if (ret != ENOENT) {
       18: 1142:            if (ret == EOK) ret = EEXIST;
       18: 1143:            goto done;
        -: 1144:        }
        -: 1145:    }
        -: 1146:
        -: 1147:    /* try to add the user */
      351: 1148:    ret = sysdb_add_basic_user(sysdb, domain, name,
        -: 1149:                               uid, gid, gecos, homedir, shell);
      351: 1150:    if (ret) goto done;
        -: 1151:
      351: 1152:    if (uid == 0) {
    #####: 1153:        ret = sysdb_get_new_id(sysdb, domain, &id);
    #####: 1154:        if (ret) goto done;
        -: 1155:
    #####: 1156:        id_attrs = sysdb_new_attrs(tmp_ctx);
    #####: 1157:        if (!id_attrs) {
    #####: 1158:            ret = ENOMEM;
    #####: 1159:            goto done;
        -: 1160:        }
    #####: 1161:        ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id);
    #####: 1162:        if (ret) goto done;
        -: 1163:
    #####: 1164:        if (domain->mpg) {
    #####: 1165:            ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id);
    #####: 1166:            if (ret) goto done;
        -: 1167:        }
        -: 1168:
    #####: 1169:        ret = sysdb_set_user_attr(sysdb, domain, name,
        -: 1170:                                  id_attrs, SYSDB_MOD_REP);
    #####: 1171:        goto done;
        -: 1172:    }
        -: 1173:
      351: 1174:    if (!attrs) {
       90: 1175:        attrs = sysdb_new_attrs(tmp_ctx);
       90: 1176:        if (!attrs) {
    #####: 1177:            ret = ENOMEM;
    #####: 1178:            goto done;
        -: 1179:        }
        -: 1180:    }
        -: 1181:
      351: 1182:    if (!now) {
       90: 1183:        now = time(NULL);
        -: 1184:    }
        -: 1185:
      351: 1186:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
      351: 1187:    if (ret) goto done;
        -: 1188:
      594: 1189:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1190:                                 ((cache_timeout) ?
      243: 1191:                                  (now + cache_timeout) : 0));
      351: 1192:    if (ret) goto done;
        -: 1193:
      351: 1194:    ret = sysdb_set_user_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
      351: 1195:    if (ret) goto done;
        -: 1196:
        -: 1197:    /* remove all ghost users */
      351: 1198:    ret = sysdb_remove_ghostattr_from_groups(sysdb, domain,
        -: 1199:                                             orig_dn, attrs, name);
      351: 1200:    if (ret) goto done;
        -: 1201:
      351: 1202:    ret = EOK;
        -: 1203:
        -: 1204:done:
      369: 1205:    if (ret == EOK) {
      351: 1206:        ret = ldb_transaction_commit(sysdb->ldb);
      351: 1207:        ret = sysdb_error_to_errno(ret);
        -: 1208:    } else {
       18: 1209:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
       18: 1210:        ldb_transaction_cancel(sysdb->ldb);
        -: 1211:    }
      369: 1212:    talloc_zfree(tmp_ctx);
      369: 1213:    return ret;
        -: 1214:}
        -: 1215:
        -: 1216:/* =Add-Basic-Group-NO-CHECKS============================================= */
        -: 1217:
     1044: 1218:int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
        -: 1219:                          struct sss_domain_info *domain,
        -: 1220:                          const char *name, gid_t gid)
        -: 1221:{
        -: 1222:    struct ldb_message *msg;
        -: 1223:    int ret;
        -: 1224:    TALLOC_CTX *tmp_ctx;
        -: 1225:
     1044: 1226:    tmp_ctx = talloc_new(NULL);
     1044: 1227:    if (!tmp_ctx) {
    #####: 1228:        return ENOMEM;
        -: 1229:    }
        -: 1230:
     1044: 1231:    msg = ldb_msg_new(tmp_ctx);
     1044: 1232:    if (!msg) {
    #####: 1233:        ret = ENOMEM;
    #####: 1234:        goto done;
        -: 1235:    }
        -: 1236:
        -: 1237:    /* group dn */
     1044: 1238:    msg->dn = sysdb_group_dn(sysdb, msg, domain, name);
     1044: 1239:    if (!msg->dn) {
    #####: 1240:        ERROR_OUT(ret, ENOMEM, done);
        -: 1241:    }
        -: 1242:
     1044: 1243:    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS);
     1044: 1244:    if (ret) goto done;
        -: 1245:
     1044: 1246:    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
     1044: 1247:    if (ret) goto done;
        -: 1248:
     1044: 1249:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
     1044: 1250:    if (ret) goto done;
        -: 1251:
        -: 1252:    /* creation time */
     1044: 1253:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
     1044: 1254:                    (unsigned long)time(NULL));
     1044: 1255:    if (ret) goto done;
        -: 1256:
     1044: 1257:    ret = ldb_add(sysdb->ldb, msg);
     1044: 1258:    ret = sysdb_error_to_errno(ret);
        -: 1259:
        -: 1260:done:
     1044: 1261:    if (ret) {
    #####: 1262:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1263:    }
     1044: 1264:    talloc_zfree(tmp_ctx);
     1044: 1265:    return ret;
        -: 1266:}
        -: 1267:
        -: 1268:
        -: 1269:/* =Add-Group-Function==================================================== */
        -: 1270:
      945: 1271:int sysdb_add_group(struct sysdb_ctx *sysdb,
        -: 1272:                    struct sss_domain_info *domain,
        -: 1273:                    const char *name, gid_t gid,
        -: 1274:                    struct sysdb_attrs *attrs,
        -: 1275:                    int cache_timeout,
        -: 1276:                    time_t now)
        -: 1277:{
        -: 1278:    TALLOC_CTX *tmp_ctx;
        -: 1279:    struct ldb_message *msg;
        -: 1280:    uint32_t id;
        -: 1281:    int ret;
        -: 1282:    bool posix;
        -: 1283:
      954: 1284:    if (domain->id_max != 0 && gid != 0 &&
       18: 1285:        (gid < domain->id_min || gid > domain->id_max)) {
    #####: 1286:        DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
        -: 1287:                  gid, domain->id_min, domain->id_max));
    #####: 1288:        return ERANGE;
        -: 1289:    }
        -: 1290:
      945: 1291:    tmp_ctx = talloc_new(NULL);
      945: 1292:    if (!tmp_ctx) {
    #####: 1293:        return ENOMEM;
        -: 1294:    }
        -: 1295:
      945: 1296:    ret = ldb_transaction_start(sysdb->ldb);
      945: 1297:    if (ret) {
    #####: 1298:        ret = sysdb_error_to_errno(ret);
    #####: 1299:        talloc_free(tmp_ctx);
    #####: 1300:        return ret;
        -: 1301:    }
        -: 1302:
      945: 1303:    if (domain->mpg) {
        -: 1304:        /* In MPG domains you can't have groups with the same name as users,
        -: 1305:         * search if a group with the same name exists.
        -: 1306:         * Don't worry about users, if we try to add a user with the same
        -: 1307:         * name the operation will fail */
        -: 1308:
      945: 1309:        ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain,
        -: 1310:                                        name, NULL, &msg);
      945: 1311:        if (ret != ENOENT) {
    #####: 1312:            if (ret == EOK) ret = EEXIST;
    #####: 1313:            goto done;
        -: 1314:        }
        -: 1315:    }
        -: 1316:
        -: 1317:    /* check no other groups with the same gid exist */
      945: 1318:    if (gid != 0) {
      945: 1319:        ret = sysdb_search_group_by_gid(tmp_ctx, sysdb, domain,
        -: 1320:                                        gid, NULL, &msg);
      945: 1321:        if (ret != ENOENT) {
       18: 1322:            if (ret == EOK) ret = EEXIST;
       18: 1323:            goto done;
        -: 1324:        }
        -: 1325:    }
        -: 1326:
        -: 1327:    /* try to add the group */
      927: 1328:    ret = sysdb_add_basic_group(sysdb, domain, name, gid);
      927: 1329:    if (ret) goto done;
        -: 1330:
      927: 1331:    if (!attrs) {
       90: 1332:        attrs = sysdb_new_attrs(tmp_ctx);
       90: 1333:        if (!attrs) {
    #####: 1334:            ret = ENOMEM;
    #####: 1335:            goto done;
        -: 1336:        }
        -: 1337:    }
        -: 1338:
      927: 1339:    ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix);
      927: 1340:    if (ret == ENOENT) {
      927: 1341:        posix = true;
      927: 1342:        ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, true);
      927: 1343:        if (ret) goto done;
    #####: 1344:    } else if (ret != EOK) {
    #####: 1345:        goto done;
        -: 1346:    }
        -: 1347:
      927: 1348:    if (posix && gid == 0) {
    #####: 1349:        ret = sysdb_get_new_id(sysdb, domain, &id);
    #####: 1350:        if (ret) goto done;
        -: 1351:
    #####: 1352:        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, id);
    #####: 1353:        if (ret) goto done;
        -: 1354:    }
        -: 1355:
      927: 1356:    if (!now) {
       90: 1357:        now = time(NULL);
        -: 1358:    }
        -: 1359:
      927: 1360:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
      927: 1361:    if (ret) goto done;
        -: 1362:
     1746: 1363:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1364:                                 ((cache_timeout) ?
      819: 1365:                                  (now + cache_timeout) : 0));
      927: 1366:    if (ret) goto done;
        -: 1367:
      927: 1368:    ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
        -: 1369:
        -: 1370:done:
      945: 1371:    if (ret == EOK) {
      927: 1372:        ret = ldb_transaction_commit(sysdb->ldb);
      927: 1373:        ret = sysdb_error_to_errno(ret);
        -: 1374:    } else {
       18: 1375:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
       18: 1376:        ldb_transaction_cancel(sysdb->ldb);
        -: 1377:    }
      945: 1378:    talloc_zfree(tmp_ctx);
      945: 1379:    return ret;
        -: 1380:}
        -: 1381:
      117: 1382:int sysdb_add_incomplete_group(struct sysdb_ctx *sysdb,
        -: 1383:                               struct sss_domain_info *domain,
        -: 1384:                               const char *name,
        -: 1385:                               gid_t gid,
        -: 1386:                               const char *original_dn,
        -: 1387:                               bool posix,
        -: 1388:                               time_t now)
        -: 1389:{
        -: 1390:    TALLOC_CTX *tmp_ctx;
        -: 1391:    int ret;
        -: 1392:    struct sysdb_attrs *attrs;
        -: 1393:
      117: 1394:    tmp_ctx = talloc_new(NULL);
      117: 1395:    if (!tmp_ctx) {
    #####: 1396:        return ENOMEM;
        -: 1397:    }
        -: 1398:
        -: 1399:    /* try to add the group */
      117: 1400:    ret = sysdb_add_basic_group(sysdb, domain, name, gid);
      117: 1401:    if (ret) goto done;
        -: 1402:
      117: 1403:    attrs = sysdb_new_attrs(tmp_ctx);
      117: 1404:    if (!attrs) {
    #####: 1405:        ret = ENOMEM;
    #####: 1406:        goto done;
        -: 1407:    }
        -: 1408:
      117: 1409:    if (!now) {
      117: 1410:        now = time(NULL);
        -: 1411:    }
        -: 1412:
      117: 1413:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
      117: 1414:    if (ret) goto done;
        -: 1415:
      117: 1416:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1417:                                 now-1);
      117: 1418:    if (ret) goto done;
        -: 1419:
      117: 1420:    ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, posix);
      117: 1421:    if (ret) goto done;
        -: 1422:
      117: 1423:    if (original_dn) {
       18: 1424:        ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, original_dn);
       18: 1425:        if (ret) goto done;
        -: 1426:    }
        -: 1427:
      117: 1428:    ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
        -: 1429:
        -: 1430:done:
      117: 1431:    if (ret != EOK) {
    #####: 1432:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1433:    }
      117: 1434:    talloc_zfree(tmp_ctx);
      117: 1435:    return ret;
        -: 1436:}
        -: 1437:
        -: 1438:/* =Add-Or-Remove-Group-Memeber=========================================== */
        -: 1439:
        -: 1440:/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */
      504: 1441:int sysdb_mod_group_member(struct sysdb_ctx *sysdb,
        -: 1442:                           struct ldb_dn *member_dn,
        -: 1443:                           struct ldb_dn *group_dn,
        -: 1444:                           int mod_op)
        -: 1445:{
        -: 1446:    struct ldb_message *msg;
        -: 1447:    const char *dn;
        -: 1448:    int ret;
        -: 1449:
      504: 1450:    msg = ldb_msg_new(NULL);
      504: 1451:    if (!msg) {
    #####: 1452:        ERROR_OUT(ret, ENOMEM, fail);
        -: 1453:    }
        -: 1454:
      504: 1455:    msg->dn = group_dn;
      504: 1456:    ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL);
      504: 1457:    if (ret != LDB_SUCCESS) {
    #####: 1458:        ERROR_OUT(ret, ENOMEM, fail);
        -: 1459:    }
        -: 1460:
      504: 1461:    dn = ldb_dn_get_linearized(member_dn);
      504: 1462:    if (!dn) {
    #####: 1463:        ERROR_OUT(ret, EINVAL, fail);
        -: 1464:    }
        -: 1465:
      504: 1466:    ret = ldb_msg_add_string(msg, SYSDB_MEMBER, dn);
      504: 1467:    if (ret != LDB_SUCCESS) {
    #####: 1468:        ERROR_OUT(ret, EINVAL, fail);
        -: 1469:    }
        -: 1470:
      504: 1471:    ret = ldb_modify(sysdb->ldb, msg);
      504: 1472:    ret = sysdb_error_to_errno(ret);
        -: 1473:
        -: 1474:fail:
      504: 1475:    if (ret) {
    #####: 1476:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1477:    }
      504: 1478:    talloc_zfree(msg);
      504: 1479:    return ret;
        -: 1480:}
        -: 1481:
        -: 1482:/* =Add-Basic-Netgroup-NO-CHECKS============================================= */
        -: 1483:
       99: 1484:int sysdb_add_basic_netgroup(struct sysdb_ctx *sysdb,
        -: 1485:                             struct sss_domain_info *domain,
        -: 1486:                             const char *name, const char *description)
        -: 1487:{
        -: 1488:    struct ldb_message *msg;
        -: 1489:    int ret;
        -: 1490:
       99: 1491:    msg = ldb_msg_new(NULL);
       99: 1492:    if (!msg) {
    #####: 1493:        return ENOMEM;
        -: 1494:    }
        -: 1495:
        -: 1496:    /* netgroup dn */
       99: 1497:    msg->dn = sysdb_netgroup_dn(sysdb, msg, domain, name);
       99: 1498:    if (!msg->dn) {
    #####: 1499:        ERROR_OUT(ret, ENOMEM, done);
        -: 1500:    }
        -: 1501:
       99: 1502:    ret = add_string(msg, LDB_FLAG_MOD_ADD,
        -: 1503:                     SYSDB_OBJECTCLASS, SYSDB_NETGROUP_CLASS);
       99: 1504:    if (ret) goto done;
        -: 1505:
       99: 1506:    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
       99: 1507:    if (ret) goto done;
        -: 1508:
       99: 1509:    if (description && *description) {
       99: 1510:        ret = add_string(msg, LDB_FLAG_MOD_ADD,
        -: 1511:                         SYSDB_DESCRIPTION, description);
       99: 1512:        if (ret) goto done;
        -: 1513:    }
        -: 1514:
        -: 1515:    /* creation time */
       99: 1516:    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
       99: 1517:                    (unsigned long) time(NULL));
       99: 1518:    if (ret) goto done;
        -: 1519:
       99: 1520:    ret = ldb_add(sysdb->ldb, msg);
       99: 1521:    ret = sysdb_error_to_errno(ret);
        -: 1522:
        -: 1523:done:
       99: 1524:    if (ret) {
    #####: 1525:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1526:    }
       99: 1527:    talloc_zfree(msg);
       99: 1528:    return ret;
        -: 1529:}
        -: 1530:
        -: 1531:
        -: 1532:/* =Add-Netgroup-Function==================================================== */
        -: 1533:
        9: 1534:int sysdb_add_netgroup(struct sysdb_ctx *sysdb,
        -: 1535:                       struct sss_domain_info *domain,
        -: 1536:                       const char *name,
        -: 1537:                       const char *description,
        -: 1538:                       struct sysdb_attrs *attrs,
        -: 1539:                       char **missing,
        -: 1540:                       int cache_timeout,
        -: 1541:                       time_t now)
        -: 1542:{
        -: 1543:    TALLOC_CTX *tmp_ctx;
        -: 1544:    int ret;
        -: 1545:
        9: 1546:    tmp_ctx = talloc_new(NULL);
        9: 1547:    if (!tmp_ctx) {
    #####: 1548:        return ENOMEM;
        -: 1549:    }
        -: 1550:
        9: 1551:    ret = ldb_transaction_start(sysdb->ldb);
        9: 1552:    if (ret) {
    #####: 1553:        ret = sysdb_error_to_errno(ret);
    #####: 1554:        talloc_free(tmp_ctx);
    #####: 1555:        return ret;
        -: 1556:    }
        -: 1557:
        -: 1558:    /* try to add the netgroup */
        9: 1559:    ret = sysdb_add_basic_netgroup(sysdb, domain, name, description);
        9: 1560:    if (ret && ret != EEXIST) goto done;
        -: 1561:
        9: 1562:    if (!attrs) {
        9: 1563:        attrs = sysdb_new_attrs(tmp_ctx);
        9: 1564:        if (!attrs) {
    #####: 1565:            ret = ENOMEM;
    #####: 1566:            goto done;
        -: 1567:        }
        -: 1568:    }
        -: 1569:
        9: 1570:    if (!now) {
        9: 1571:        now = time(NULL);
        -: 1572:    }
        -: 1573:
        9: 1574:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
        9: 1575:    if (ret) goto done;
        -: 1576:
       18: 1577:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1578:                                 ((cache_timeout) ?
        9: 1579:                                  (now + cache_timeout) : 0));
        9: 1580:    if (ret) goto done;
        -: 1581:
        9: 1582:    ret = sysdb_set_netgroup_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
        -: 1583:
        9: 1584:    if (missing) {
    #####: 1585:        ret = sysdb_remove_attrs(sysdb, domain, name,
        -: 1586:                                 SYSDB_MEMBER_NETGROUP,
        -: 1587:                                 missing);
    #####: 1588:        if (ret != EOK) {
    #####: 1589:            DEBUG(SSSDBG_MINOR_FAILURE, ("Could not remove missing attributes\n"));
        -: 1590:        }
        -: 1591:    }
        -: 1592:
        -: 1593:done:
        9: 1594:    if (ret == EOK) {
        9: 1595:        ret = ldb_transaction_commit(sysdb->ldb);
        9: 1596:        ret = sysdb_error_to_errno(ret);
        -: 1597:    }
        -: 1598:
        9: 1599:    if (ret != EOK) {
    #####: 1600:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
    #####: 1601:        ldb_transaction_cancel(sysdb->ldb);
        -: 1602:    }
        9: 1603:    talloc_zfree(tmp_ctx);
        9: 1604:    return ret;
        -: 1605:}
        -: 1606:
        -: 1607:/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
        -: 1608:
        -: 1609:/* if one of the basic attributes is empty ("") as opposed to NULL,
        -: 1610: * this will just remove it */
        -: 1611:
      441: 1612:int sysdb_store_user(struct sysdb_ctx *sysdb,
        -: 1613:                     struct sss_domain_info *domain,
        -: 1614:                     const char *name,
        -: 1615:                     const char *pwd,
        -: 1616:                     uid_t uid, gid_t gid,
        -: 1617:                     const char *gecos,
        -: 1618:                     const char *homedir,
        -: 1619:                     const char *shell,
        -: 1620:                     const char *orig_dn,
        -: 1621:                     struct sysdb_attrs *attrs,
        -: 1622:                     char **remove_attrs,
        -: 1623:                     uint64_t cache_timeout,
        -: 1624:                     time_t now)
        -: 1625:{
        -: 1626:    TALLOC_CTX *tmp_ctx;
        -: 1627:    struct ldb_message *msg;
        -: 1628:    int ret;
      441: 1629:    errno_t sret = EOK;
      441: 1630:    bool in_transaction = false;
        -: 1631:
      441: 1632:    tmp_ctx = talloc_new(NULL);
      441: 1633:    if (!tmp_ctx) {
    #####: 1634:        return ENOMEM;
        -: 1635:    }
        -: 1636:
      441: 1637:    if (!attrs) {
      441: 1638:        attrs = sysdb_new_attrs(tmp_ctx);
      441: 1639:        if (!attrs) {
    #####: 1640:            ret = ENOMEM;
    #####: 1641:            goto fail;
        -: 1642:        }
        -: 1643:    }
        -: 1644:
      441: 1645:    if (pwd && (domain->legacy_passwords || !*pwd)) {
    #####: 1646:        ret = sysdb_attrs_add_string(attrs, SYSDB_PWD, pwd);
    #####: 1647:        if (ret) goto fail;
        -: 1648:    }
        -: 1649:
      441: 1650:    ret = sysdb_transaction_start(sysdb);
      441: 1651:    if (ret != EOK) {
    #####: 1652:        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
    #####: 1653:        goto fail;
        -: 1654:    }
        -: 1655:
      441: 1656:    in_transaction = true;
        -: 1657:
      441: 1658:    ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain, name, NULL, &msg);
      441: 1659:    if (ret && ret != ENOENT) {
    #####: 1660:        goto fail;
        -: 1661:    }
        -: 1662:
        -: 1663:    /* get transaction timestamp */
      441: 1664:    if (!now) {
      441: 1665:        now = time(NULL);
        -: 1666:    }
        -: 1667:
      441: 1668:    if (ret == ENOENT) {
        -: 1669:        /* users doesn't exist, turn into adding a user */
      261: 1670:        ret = sysdb_add_user(sysdb, domain, name, uid, gid, gecos, homedir,
        -: 1671:                             shell, orig_dn, attrs, cache_timeout, now);
      261: 1672:        if (ret == EEXIST) {
        -: 1673:            /* This may be a user rename. If there is a user with the
        -: 1674:             * same UID, remove it and try to add the basic user again
        -: 1675:             */
        9: 1676:            ret = sysdb_delete_user(sysdb, domain, NULL, uid);
        9: 1677:            if (ret == ENOENT) {
        -: 1678:                /* Not found by UID, return the original EEXIST,
        -: 1679:                 * this may be a conflict in MPG domain or something
        -: 1680:                 * else */
    #####: 1681:                ret = EEXIST;
    #####: 1682:                goto fail;
        9: 1683:            } else if (ret != EOK) {
    #####: 1684:                goto fail;
        -: 1685:            }
        9: 1686:            DEBUG(SSSDBG_MINOR_FAILURE,
        -: 1687:                  ("A user with the same UID [%llu] was removed from the "
        -: 1688:                   "cache\n", (unsigned long long) uid));
        9: 1689:            ret = sysdb_add_user(sysdb, domain, name, uid, gid, gecos, homedir,
        -: 1690:                                 shell, orig_dn, attrs, cache_timeout, now);
        -: 1691:        }
        -: 1692:
        -: 1693:        /* Handle the result of sysdb_add_user */
      261: 1694:        if (ret == EOK) {
      261: 1695:            goto done;
        -: 1696:        } else {
    #####: 1697:            DEBUG(SSSDBG_OP_FAILURE, ("Could not add user\n"));
    #####: 1698:            goto fail;
        -: 1699:        }
        -: 1700:    }
        -: 1701:
        -: 1702:    /* the user exists, let's just replace attributes when set */
      180: 1703:    if (uid) {
      180: 1704:        ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid);
      180: 1705:        if (ret) goto fail;
        -: 1706:    }
        -: 1707:
      180: 1708:    if (gid) {
    #####: 1709:        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
    #####: 1710:        if (ret) goto fail;
        -: 1711:    }
        -: 1712:
      180: 1713:    if (uid && !gid && domain->mpg) {
      180: 1714:        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, uid);
      180: 1715:        if (ret) goto fail;
        -: 1716:    }
        -: 1717:
      180: 1718:    if (gecos) {
      180: 1719:        ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos);
      180: 1720:        if (ret) goto fail;
        -: 1721:    }
        -: 1722:
      180: 1723:    if (homedir) {
      180: 1724:        ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir);
      180: 1725:        if (ret) goto fail;
        -: 1726:    }
        -: 1727:
      180: 1728:    if (shell) {
      180: 1729:        ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell);
      180: 1730:        if (ret) goto fail;
        -: 1731:    }
        -: 1732:
      180: 1733:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
      180: 1734:    if (ret) goto fail;
        -: 1735:
      360: 1736:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1737:                                 ((cache_timeout) ?
      180: 1738:                                  (now + cache_timeout) : 0));
      180: 1739:    if (ret) goto fail;
        -: 1740:
      180: 1741:    ret = sysdb_set_user_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
      180: 1742:    if (ret != EOK) goto fail;
        -: 1743:
      180: 1744:    if (remove_attrs) {
    #####: 1745:        ret = sysdb_remove_attrs(sysdb, domain, name,
        -: 1746:                                    SYSDB_MEMBER_USER,
        -: 1747:                                    remove_attrs);
    #####: 1748:        if (ret != EOK) {
    #####: 1749:            DEBUG(4, ("Could not remove missing attributes\n"));
        -: 1750:        }
        -: 1751:    }
        -: 1752:
        -: 1753:done:
      441: 1754:    ret = sysdb_transaction_commit(sysdb);
      441: 1755:    if (ret != EOK) {
    #####: 1756:        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
    #####: 1757:        goto fail;
        -: 1758:    }
        -: 1759:
      441: 1760:    in_transaction = false;
        -: 1761:
        -: 1762:fail:
      441: 1763:    if (in_transaction) {
    #####: 1764:        sret = sysdb_transaction_cancel(sysdb);
    #####: 1765:        if (sret != EOK) {
    #####: 1766:            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
        -: 1767:        }
        -: 1768:    }
        -: 1769:
      441: 1770:    if (ret) {
    #####: 1771:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1772:    }
      441: 1773:    talloc_zfree(tmp_ctx);
      441: 1774:    return ret;
        -: 1775:}
        -: 1776:
        -: 1777:/* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */
        -: 1778:
        -: 1779:/* this function does not check that all user members are actually present */
        -: 1780:
      846: 1781:int sysdb_store_group(struct sysdb_ctx *sysdb,
        -: 1782:                      struct sss_domain_info *domain,
        -: 1783:                      const char *name,
        -: 1784:                      gid_t gid,
        -: 1785:                      struct sysdb_attrs *attrs,
        -: 1786:                      uint64_t cache_timeout,
        -: 1787:                      time_t now)
        -: 1788:{
        -: 1789:    TALLOC_CTX *tmp_ctx;
        -: 1790:    static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM,
        -: 1791:                                       SYSDB_ORIG_MODSTAMP, NULL };
        -: 1792:    struct ldb_message *msg;
      846: 1793:    bool new_group = false;
        -: 1794:    int ret;
        -: 1795:
      846: 1796:    tmp_ctx = talloc_new(NULL);
      846: 1797:    if (!tmp_ctx) {
    #####: 1798:        return ENOMEM;
        -: 1799:    }
        -: 1800:
      846: 1801:    ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain,
        -: 1802:                                     name, src_attrs, &msg);
      846: 1803:    if (ret && ret != ENOENT) {
    #####: 1804:        goto done;
        -: 1805:    }
      846: 1806:    if (ret == ENOENT) {
      837: 1807:        new_group = true;
        -: 1808:    }
        -: 1809:
      846: 1810:    if (!attrs) {
      117: 1811:        attrs = sysdb_new_attrs(tmp_ctx);
      117: 1812:        if (!attrs) {
    #####: 1813:            ret = ENOMEM;
    #####: 1814:            goto done;
        -: 1815:        }
        -: 1816:    }
        -: 1817:
        -: 1818:    /* get transaction timestamp */
      846: 1819:    if (!now) {
      846: 1820:        now = time(NULL);
        -: 1821:    }
        -: 1822:
        -: 1823:    /* FIXME: use the remote modification timestamp to know if the
        -: 1824:     * group needs any update */
        -: 1825:
      846: 1826:    if (new_group) {
        -: 1827:        /* group doesn't exist, turn into adding a group */
      837: 1828:        ret = sysdb_add_group(sysdb, domain, name, gid,
        -: 1829:                              attrs, cache_timeout, now);
      837: 1830:        if (ret == EEXIST) {
        -: 1831:            /* This may be a group rename. If there is a group with the
        -: 1832:             * same GID, remove it and try to add the basic group again
        -: 1833:             */
        9: 1834:            ret = sysdb_delete_group(sysdb, domain, NULL, gid);
        9: 1835:            if (ret == ENOENT) {
        -: 1836:                /* Not found by GID, return the original EEXIST,
        -: 1837:                 * this may be a conflict in MPG domain or something
        -: 1838:                 * else */
    #####: 1839:                return EEXIST;
        9: 1840:            } else if (ret != EOK) {
    #####: 1841:                goto done;
        -: 1842:            }
        9: 1843:            DEBUG(SSSDBG_MINOR_FAILURE,
        -: 1844:                  ("A group with the same GID [%llu] was removed from the "
        -: 1845:                   "cache\n", (unsigned long long) gid));
        9: 1846:            ret = sysdb_add_group(sysdb, domain, name, gid,
        -: 1847:                                  attrs, cache_timeout, now);
        -: 1848:        }
      837: 1849:        goto done;
        -: 1850:    }
        -: 1851:
        -: 1852:    /* the group exists, let's just replace attributes when set */
        9: 1853:    if (gid) {
        9: 1854:        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
        9: 1855:        if (ret) goto done;
        -: 1856:    }
        -: 1857:
        9: 1858:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
        9: 1859:    if (ret) goto done;
        -: 1860:
       18: 1861:    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
        -: 1862:                                 ((cache_timeout) ?
        9: 1863:                                  (now + cache_timeout) : 0));
        9: 1864:    if (ret) goto done;
        -: 1865:
        9: 1866:    ret = sysdb_set_group_attr(sysdb, domain, name, attrs, SYSDB_MOD_REP);
        -: 1867:
        -: 1868:done:
      846: 1869:    if (ret) {
    #####: 1870:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 1871:    }
      846: 1872:    talloc_zfree(tmp_ctx);
      846: 1873:    return ret;
        -: 1874:}
        -: 1875:
        -: 1876:
        -: 1877:/* =Add-User-to-Group(Native/Legacy)====================================== */
        -: 1878:static int
      504: 1879:sysdb_group_membership_mod(struct sysdb_ctx *sysdb,
        -: 1880:                           struct sss_domain_info *domain,
        -: 1881:                           const char *group,
        -: 1882:                           const char *member,
        -: 1883:                           enum sysdb_member_type type,
        -: 1884:                           int modify_op)
        -: 1885:{
        -: 1886:    struct ldb_dn *group_dn;
        -: 1887:    struct ldb_dn *member_dn;
        -: 1888:    int ret;
      504: 1889:    TALLOC_CTX *tmp_ctx = talloc_new(NULL);
      504: 1890:    if (!tmp_ctx) {
    #####: 1891:        return ENOMEM;
        -: 1892:    }
        -: 1893:
      504: 1894:    if (type == SYSDB_MEMBER_USER) {
      504: 1895:        member_dn = sysdb_user_dn(sysdb, tmp_ctx, domain, member);
    #####: 1896:    } else if (type == SYSDB_MEMBER_GROUP) {
    #####: 1897:        member_dn = sysdb_group_dn(sysdb, tmp_ctx, domain, member);
        -: 1898:    } else {
    #####: 1899:        ret = EINVAL;
    #####: 1900:        goto done;
        -: 1901:    }
        -: 1902:
      504: 1903:    if (!member_dn) {
    #####: 1904:        ret = ENOMEM;
    #####: 1905:        goto done;
        -: 1906:    }
        -: 1907:
      504: 1908:    group_dn = sysdb_group_dn(sysdb, tmp_ctx, domain, group);
      504: 1909:    if (!group_dn) {
    #####: 1910:        ret = ENOMEM;
    #####: 1911:        goto done;
        -: 1912:    }
        -: 1913:
      504: 1914:    ret = sysdb_mod_group_member(sysdb, member_dn, group_dn, modify_op);
        -: 1915:
        -: 1916:done:
      504: 1917:    talloc_free(tmp_ctx);
      504: 1918:    return ret;
        -: 1919:}
        -: 1920:
      387: 1921:int sysdb_add_group_member(struct sysdb_ctx *sysdb,
        -: 1922:                           struct sss_domain_info *domain,
        -: 1923:                           const char *group,
        -: 1924:                           const char *member,
        -: 1925:                           enum sysdb_member_type type)
        -: 1926:{
      387: 1927:    return sysdb_group_membership_mod(sysdb, domain, group,
        -: 1928:                                      member, type, SYSDB_MOD_ADD);
        -: 1929:}
        -: 1930:
        -: 1931:/* =Remove-member-from-Group(Native/Legacy)=============================== */
        -: 1932:
        -: 1933:
      117: 1934:int sysdb_remove_group_member(struct sysdb_ctx *sysdb,
        -: 1935:                              struct sss_domain_info *domain,
        -: 1936:                              const char *group,
        -: 1937:                              const char *member,
        -: 1938:                              enum sysdb_member_type type)
        -: 1939:{
      117: 1940:    return sysdb_group_membership_mod(sysdb, domain, group,
        -: 1941:                                      member, type, SYSDB_MOD_DEL);
        -: 1942:}
        -: 1943:
        -: 1944:
        -: 1945:/* =Password-Caching====================================================== */
        -: 1946:
        9: 1947:int sysdb_cache_password(struct sysdb_ctx *sysdb,
        -: 1948:                         struct sss_domain_info *domain,
        -: 1949:                         const char *username,
        -: 1950:                         const char *password)
        -: 1951:{
        -: 1952:    TALLOC_CTX *tmp_ctx;
        -: 1953:    struct sysdb_attrs *attrs;
        9: 1954:    char *hash = NULL;
        -: 1955:    char *salt;
        -: 1956:    int ret;
        -: 1957:
        9: 1958:    tmp_ctx = talloc_new(NULL);
        9: 1959:    if (!tmp_ctx) {
    #####: 1960:        return ENOMEM;
        -: 1961:    }
        -: 1962:
        9: 1963:    ret = s3crypt_gen_salt(tmp_ctx, &salt);
        9: 1964:    if (ret) {
    #####: 1965:        DEBUG(4, ("Failed to generate random salt.\n"));
    #####: 1966:        goto fail;
        -: 1967:    }
        -: 1968:
        9: 1969:    ret = s3crypt_sha512(tmp_ctx, password, salt, &hash);
        9: 1970:    if (ret) {
    #####: 1971:        DEBUG(4, ("Failed to create password hash.\n"));
    #####: 1972:        goto fail;
        -: 1973:    }
        -: 1974:
        9: 1975:    attrs = sysdb_new_attrs(tmp_ctx);
        9: 1976:    if (!attrs) {
    #####: 1977:        ERROR_OUT(ret, ENOMEM, fail);
        -: 1978:    }
        -: 1979:
        9: 1980:    ret = sysdb_attrs_add_string(attrs, SYSDB_CACHEDPWD, hash);
        9: 1981:    if (ret) goto fail;
        -: 1982:
        -: 1983:    /* FIXME: should we use a different attribute for chache passwords ?? */
        9: 1984:    ret = sysdb_attrs_add_long(attrs, "lastCachedPasswordChange",
        -: 1985:                               (long)time(NULL));
        9: 1986:    if (ret) goto fail;
        -: 1987:
        9: 1988:    ret = sysdb_attrs_add_uint32(attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0U);
        9: 1989:    if (ret) goto fail;
        -: 1990:
        -: 1991:
        9: 1992:    ret = sysdb_set_user_attr(sysdb, domain,
        -: 1993:                              username, attrs, SYSDB_MOD_REP);
        9: 1994:    if (ret) {
    #####: 1995:        goto fail;
        -: 1996:    }
        9: 1997:    talloc_zfree(tmp_ctx);
        9: 1998:    return EOK;
        -: 1999:
        -: 2000:fail:
    #####: 2001:    if (ret) {
    #####: 2002:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2003:    }
    #####: 2004:    talloc_zfree(tmp_ctx);
    #####: 2005:    return ret;
        -: 2006:}
        -: 2007:
        -: 2008:/* =Custom Search================== */
        -: 2009:
      189: 2010:int sysdb_search_custom(TALLOC_CTX *mem_ctx,
        -: 2011:                        struct sysdb_ctx *sysdb,
        -: 2012:                        struct sss_domain_info *domain,
        -: 2013:                        const char *filter,
        -: 2014:                        const char *subtree_name,
        -: 2015:                        const char **attrs,
        -: 2016:                        size_t *msgs_count,
        -: 2017:                        struct ldb_message ***msgs)
        -: 2018:{
        -: 2019:    struct ldb_dn *basedn;
        -: 2020:    int ret;
        -: 2021:
      189: 2022:    if (filter == NULL || subtree_name == NULL) {
    #####: 2023:        return EINVAL;
        -: 2024:    }
        -: 2025:
      189: 2026:    basedn = sysdb_custom_subtree_dn(sysdb, mem_ctx, domain, subtree_name);
      189: 2027:    if (basedn == NULL) {
    #####: 2028:        DEBUG(1, ("sysdb_custom_subtree_dn failed.\n"));
    #####: 2029:        return ENOMEM;
        -: 2030:    }
      189: 2031:    if (!ldb_dn_validate(basedn)) {
    #####: 2032:        DEBUG(1, ("Failed to create DN.\n"));
    #####: 2033:        return EINVAL;
        -: 2034:    }
        -: 2035:
      189: 2036:    ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
        -: 2037:                             LDB_SCOPE_SUBTREE, filter, attrs,
        -: 2038:                             msgs_count, msgs);
      189: 2039:    return ret;
        -: 2040:}
        -: 2041:
      207: 2042:int sysdb_search_custom_by_name(TALLOC_CTX *mem_ctx,
        -: 2043:                                struct sysdb_ctx *sysdb,
        -: 2044:                                struct sss_domain_info *domain,
        -: 2045:                                const char *object_name,
        -: 2046:                                const char *subtree_name,
        -: 2047:                                const char **attrs,
        -: 2048:                                size_t *_count,
        -: 2049:                                struct ldb_message ***_msgs)
        -: 2050:{
        -: 2051:    TALLOC_CTX *tmp_ctx;
        -: 2052:    struct ldb_dn *basedn;
        -: 2053:    struct ldb_message **msgs;
        -: 2054:    size_t count;
        -: 2055:    int ret;
        -: 2056:
      207: 2057:    if (object_name == NULL || subtree_name == NULL) {
    #####: 2058:        return EINVAL;
        -: 2059:    }
        -: 2060:
      207: 2061:    tmp_ctx = talloc_new(NULL);
      207: 2062:    if (!tmp_ctx) {
    #####: 2063:        return ENOMEM;
        -: 2064:    }
        -: 2065:
      207: 2066:    basedn = sysdb_custom_dn(sysdb, tmp_ctx,
        -: 2067:                             domain, object_name, subtree_name);
      207: 2068:    if (basedn == NULL) {
    #####: 2069:        DEBUG(1, ("sysdb_custom_dn failed.\n"));
    #####: 2070:        ret = ENOMEM;
    #####: 2071:        goto done;
        -: 2072:    }
      207: 2073:    if (!ldb_dn_validate(basedn)) {
    #####: 2074:        DEBUG(1, ("Failed to create DN.\n"));
    #####: 2075:        ret = EINVAL;
    #####: 2076:        goto done;
        -: 2077:    }
        -: 2078:
      207: 2079:    ret = sysdb_search_entry(tmp_ctx, sysdb, basedn,
        -: 2080:                             LDB_SCOPE_BASE, NULL, attrs, &count, &msgs);
      207: 2081:    if (ret) {
      180: 2082:        goto done;
        -: 2083:    }
        -: 2084:
       27: 2085:    if (count > 1) {
    #####: 2086:        DEBUG(1, ("More than one result found.\n"));
    #####: 2087:        ret = EFAULT;
    #####: 2088:        goto done;
        -: 2089:    }
        -: 2090:
       27: 2091:    *_count = count;
       27: 2092:    *_msgs = talloc_move(mem_ctx, &msgs);
        -: 2093:
        -: 2094:done:
      207: 2095:    talloc_zfree(tmp_ctx);
      207: 2096:    return ret;
        -: 2097:}
        -: 2098:
        -: 2099:
        -: 2100:/* =Custom Store (replaces-existing-data)================== */
        -: 2101:
      189: 2102:int sysdb_store_custom(struct sysdb_ctx *sysdb,
        -: 2103:                       struct sss_domain_info *domain,
        -: 2104:                       const char *object_name,
        -: 2105:                       const char *subtree_name,
        -: 2106:                       struct sysdb_attrs *attrs)
        -: 2107:{
        -: 2108:    TALLOC_CTX *tmp_ctx;
      189: 2109:    const char *search_attrs[] = { "*", NULL };
      189: 2110:    size_t resp_count = 0;
        -: 2111:    struct ldb_message **resp;
        -: 2112:    struct ldb_message *msg;
        -: 2113:    struct ldb_message_element *el;
      189: 2114:    bool add_object = false;
        -: 2115:    int ret;
        -: 2116:    int i;
        -: 2117:
      189: 2118:    if (object_name == NULL || subtree_name == NULL) {
    #####: 2119:        return EINVAL;
        -: 2120:    }
        -: 2121:
      189: 2122:    ret = ldb_transaction_start(sysdb->ldb);
      189: 2123:    if (ret) {
    #####: 2124:        return sysdb_error_to_errno(ret);
        -: 2125:    }
        -: 2126:
      189: 2127:    tmp_ctx = talloc_new(NULL);
      189: 2128:    if (!tmp_ctx) {
    #####: 2129:        ret = ENOMEM;
    #####: 2130:        goto done;
        -: 2131:    }
        -: 2132:
      189: 2133:    ret = sysdb_search_custom_by_name(tmp_ctx, sysdb, domain,
        -: 2134:                                      object_name, subtree_name,
        -: 2135:                                      search_attrs, &resp_count, &resp);
      189: 2136:    if (ret != EOK && ret != ENOENT) {
    #####: 2137:        goto done;
        -: 2138:    }
        -: 2139:
      189: 2140:    if (ret == ENOENT) {
      180: 2141:       add_object = true;
        -: 2142:    }
        -: 2143:
      189: 2144:    msg = ldb_msg_new(tmp_ctx);
      189: 2145:    if (msg == NULL) {
    #####: 2146:        ret = ENOMEM;
    #####: 2147:        goto done;
        -: 2148:    }
        -: 2149:
      189: 2150:    msg->dn = sysdb_custom_dn(sysdb, tmp_ctx,
        -: 2151:                              domain, object_name, subtree_name);
      189: 2152:    if (!msg->dn) {
    #####: 2153:        DEBUG(1, ("sysdb_custom_dn failed.\n"));
    #####: 2154:        ret = ENOMEM;
    #####: 2155:        goto done;
        -: 2156:    }
        -: 2157:
      189: 2158:    msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
      189: 2159:    if (!msg->elements) {
    #####: 2160:        ret = ENOMEM;
    #####: 2161:        goto done;
        -: 2162:    }
        -: 2163:
      747: 2164:    for (i = 0; i < attrs->num; i++) {
      558: 2165:        msg->elements[i] = attrs->a[i];
      558: 2166:        if (add_object) {
      540: 2167:            msg->elements[i].flags = LDB_FLAG_MOD_ADD;
        -: 2168:        } else {
       18: 2169:            el = ldb_msg_find_element(resp[0], attrs->a[i].name);
       18: 2170:            if (el == NULL) {
        9: 2171:                msg->elements[i].flags = LDB_FLAG_MOD_ADD;
        -: 2172:            } else {
        9: 2173:                msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
        -: 2174:            }
        -: 2175:        }
        -: 2176:    }
      189: 2177:    msg->num_elements = attrs->num;
        -: 2178:
      189: 2179:    if (add_object) {
      180: 2180:        ret = ldb_add(sysdb->ldb, msg);
        -: 2181:    } else {
        9: 2182:        ret = ldb_modify(sysdb->ldb, msg);
        -: 2183:    }
      189: 2184:    if (ret != LDB_SUCCESS) {
    #####: 2185:        DEBUG(1, ("Failed to store custom entry: %s(%d)[%s]\n",
        -: 2186:                  ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
    #####: 2187:        ret = sysdb_error_to_errno(ret);
        -: 2188:    }
        -: 2189:
        -: 2190:done:
      189: 2191:    if (ret) {
    #####: 2192:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
    #####: 2193:        ldb_transaction_cancel(sysdb->ldb);
        -: 2194:    } else {
      189: 2195:        ret = ldb_transaction_commit(sysdb->ldb);
      189: 2196:        ret = sysdb_error_to_errno(ret);
        -: 2197:    }
      189: 2198:    talloc_zfree(tmp_ctx);
      189: 2199:    return ret;
        -: 2200:}
        -: 2201:
        -: 2202:/* = Custom Delete======================================= */
        -: 2203:
       99: 2204:int sysdb_delete_custom(struct sysdb_ctx *sysdb,
        -: 2205:                        struct sss_domain_info *domain,
        -: 2206:                        const char *object_name,
        -: 2207:                        const char *subtree_name)
        -: 2208:{
        -: 2209:    TALLOC_CTX *tmp_ctx;
        -: 2210:    struct ldb_dn *dn;
        -: 2211:    int ret;
        -: 2212:
       99: 2213:    if (object_name == NULL || subtree_name == NULL) {
    #####: 2214:        return EINVAL;
        -: 2215:    }
        -: 2216:
       99: 2217:    tmp_ctx = talloc_new(NULL);
       99: 2218:    if (!tmp_ctx) {
    #####: 2219:        return ENOMEM;
        -: 2220:    }
        -: 2221:
       99: 2222:    dn = sysdb_custom_dn(sysdb, tmp_ctx,
        -: 2223:                         domain, object_name, subtree_name);
       99: 2224:    if (dn == NULL) {
    #####: 2225:        DEBUG(1, ("sysdb_custom_dn failed.\n"));
    #####: 2226:        ret = ENOMEM;
    #####: 2227:        goto done;
        -: 2228:    }
        -: 2229:
       99: 2230:    ret = ldb_delete(sysdb->ldb, dn);
        -: 2231:
       99: 2232:    switch (ret) {
        -: 2233:    case LDB_SUCCESS:
        -: 2234:    case LDB_ERR_NO_SUCH_OBJECT:
       99: 2235:        ret = EOK;
       99: 2236:        break;
        -: 2237:
        -: 2238:    default:
    #####: 2239:        DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
        -: 2240:                  ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
    #####: 2241:        ret = sysdb_error_to_errno(ret);
    #####: 2242:        break;
        -: 2243:    }
        -: 2244:
        -: 2245:done:
       99: 2246:    talloc_zfree(tmp_ctx);
       99: 2247:    return ret;
        -: 2248:}
        -: 2249:
        -: 2250:/* = ASQ search request ======================================== */
        -: 2251:
        9: 2252:int sysdb_asq_search(TALLOC_CTX *mem_ctx,
        -: 2253:                     struct sysdb_ctx *sysdb,
        -: 2254:                     struct ldb_dn *base_dn,
        -: 2255:                     const char *expression,
        -: 2256:                     const char *asq_attribute,
        -: 2257:                     const char **attrs,
        -: 2258:                     size_t *msgs_count,
        -: 2259:                     struct ldb_message ***msgs)
        -: 2260:{
        -: 2261:    TALLOC_CTX *tmp_ctx;
        -: 2262:    struct ldb_request *ldb_req;
        -: 2263:    struct ldb_control **ctrl;
        -: 2264:    struct ldb_asq_control *asq_control;
        -: 2265:    struct ldb_result *res;
        -: 2266:    int ret;
        -: 2267:
        9: 2268:    tmp_ctx = talloc_new(NULL);
        9: 2269:    if (!tmp_ctx) {
    #####: 2270:        return ENOMEM;
        -: 2271:    }
        -: 2272:
        9: 2273:    ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2);
        9: 2274:    if (ctrl == NULL) {
    #####: 2275:        ret = ENOMEM;
    #####: 2276:        goto fail;
        -: 2277:    }
        -: 2278:
        9: 2279:    ctrl[0] = talloc(ctrl, struct ldb_control);
        9: 2280:    if (ctrl[0] == NULL) {
    #####: 2281:        ret = ENOMEM;
    #####: 2282:        goto fail;
        -: 2283:    }
        9: 2284:    ctrl[1] = NULL;
        -: 2285:
        9: 2286:    ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
        9: 2287:    ctrl[0]->critical = 1;
        -: 2288:
        9: 2289:    asq_control = talloc(ctrl[0], struct ldb_asq_control);
        9: 2290:    if (asq_control == NULL) {
    #####: 2291:        ret = ENOMEM;
    #####: 2292:        goto fail;
        -: 2293:    }
        -: 2294:
        9: 2295:    asq_control->request = 1;
        9: 2296:    asq_control->source_attribute = talloc_strdup(asq_control, asq_attribute);
        9: 2297:    if (asq_control->source_attribute == NULL) {
    #####: 2298:        ret = ENOMEM;
    #####: 2299:        goto fail;
        -: 2300:    }
        9: 2301:    asq_control->src_attr_len = strlen(asq_control->source_attribute);
        9: 2302:    ctrl[0]->data = asq_control;
        -: 2303:
        9: 2304:    res = talloc_zero(tmp_ctx, struct ldb_result);
        9: 2305:    if (!res) {
    #####: 2306:        ret = ENOMEM;
    #####: 2307:        goto fail;
        -: 2308:    }
        -: 2309:
        9: 2310:    ret = ldb_build_search_req(&ldb_req, sysdb->ldb, tmp_ctx,
        -: 2311:                               base_dn, LDB_SCOPE_BASE,
        -: 2312:                               expression, attrs, ctrl,
        -: 2313:                               res, ldb_search_default_callback, NULL);
        9: 2314:    if (ret != LDB_SUCCESS) {
    #####: 2315:        ret = sysdb_error_to_errno(ret);
    #####: 2316:        goto fail;
        -: 2317:    }
        -: 2318:
        9: 2319:    ret = ldb_request(sysdb->ldb, ldb_req);
        9: 2320:    if (ret == LDB_SUCCESS) {
        9: 2321:        ret = ldb_wait(ldb_req->handle, LDB_WAIT_ALL);
        -: 2322:    }
        9: 2323:    if (ret) {
    #####: 2324:        ret = sysdb_error_to_errno(ret);
    #####: 2325:        goto fail;
        -: 2326:    }
        -: 2327:
        9: 2328:    *msgs_count = res->count;
        9: 2329:    *msgs = talloc_move(mem_ctx, &res->msgs);
        -: 2330:
        9: 2331:    talloc_zfree(tmp_ctx);
        9: 2332:    return EOK;
        -: 2333:
        -: 2334:fail:
    #####: 2335:    if (ret == ENOENT) {
    #####: 2336:        DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
        -: 2337:    }
    #####: 2338:    else if (ret) {
    #####: 2339:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2340:    }
    #####: 2341:    talloc_zfree(tmp_ctx);
    #####: 2342:    return ret;
        -: 2343:}
        -: 2344:
        -: 2345:/* =Search-Users-with-Custom-Filter====================================== */
        -: 2346:
    #####: 2347:int sysdb_search_users(TALLOC_CTX *mem_ctx,
        -: 2348:                       struct sysdb_ctx *sysdb,
        -: 2349:                       struct sss_domain_info *domain,
        -: 2350:                       const char *sub_filter,
        -: 2351:                       const char **attrs,
        -: 2352:                       size_t *msgs_count,
        -: 2353:                       struct ldb_message ***msgs)
        -: 2354:{
        -: 2355:    TALLOC_CTX *tmp_ctx;
        -: 2356:    struct ldb_dn *basedn;
        -: 2357:    char *filter;
        -: 2358:    int ret;
        -: 2359:
    #####: 2360:    tmp_ctx = talloc_new(NULL);
    #####: 2361:    if (!tmp_ctx) {
    #####: 2362:        return ENOMEM;
        -: 2363:    }
        -: 2364:
    #####: 2365:    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -: 2366:                            SYSDB_TMPL_USER_BASE, domain->name);
    #####: 2367:    if (!basedn) {
    #####: 2368:        DEBUG(2, ("Failed to build base dn\n"));
    #####: 2369:        ret = ENOMEM;
    #####: 2370:        goto fail;
        -: 2371:    }
        -: 2372:
    #####: 2373:    filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_UC, sub_filter);
    #####: 2374:    if (!filter) {
    #####: 2375:        DEBUG(2, ("Failed to build filter\n"));
    #####: 2376:        ret = ENOMEM;
    #####: 2377:        goto fail;
        -: 2378:    }
        -: 2379:
    #####: 2380:    DEBUG(SSSDBG_TRACE_INTERNAL,
        -: 2381:          ("Search users with filter: %s\n", filter));
        -: 2382:
    #####: 2383:    ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
        -: 2384:                             LDB_SCOPE_SUBTREE, filter, attrs,
        -: 2385:                             msgs_count, msgs);
    #####: 2386:    if (ret) {
    #####: 2387:        goto fail;
        -: 2388:    }
        -: 2389:
    #####: 2390:    talloc_zfree(tmp_ctx);
    #####: 2391:    return EOK;
        -: 2392:
        -: 2393:fail:
    #####: 2394:    if (ret == ENOENT) {
    #####: 2395:        DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n"));
        -: 2396:    }
    #####: 2397:    else if (ret) {
    #####: 2398:        DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2399:    }
    #####: 2400:    talloc_zfree(tmp_ctx);
    #####: 2401:    return ret;
        -: 2402:}
        -: 2403:
        -: 2404:/* =Delete-User-by-Name-OR-uid============================================ */
        -: 2405:
      180: 2406:int sysdb_delete_user(struct sysdb_ctx *sysdb,
        -: 2407:                      struct sss_domain_info *domain,
        -: 2408:                      const char *name, uid_t uid)
        -: 2409:{
        -: 2410:    TALLOC_CTX *tmp_ctx;
      180: 2411:    const char *attrs[] = {SYSDB_GHOST, NULL};
        -: 2412:    size_t msg_count;
        -: 2413:    char *filter;
        -: 2414:    struct ldb_message **msgs;
        -: 2415:    struct ldb_message *msg;
        -: 2416:    int ret;
        -: 2417:    int i;
        -: 2418:
      180: 2419:    tmp_ctx = talloc_new(NULL);
      180: 2420:    if (!tmp_ctx) {
    #####: 2421:        return ENOMEM;
        -: 2422:    }
        -: 2423:
      180: 2424:    if (name) {
       27: 2425:        ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain,
        -: 2426:                                        name, NULL, &msg);
        -: 2427:    } else {
      153: 2428:        ret = sysdb_search_user_by_uid(tmp_ctx, sysdb, domain,
        -: 2429:                                       uid, NULL, &msg);
        -: 2430:    }
      180: 2431:    if (ret == EOK) {
      171: 2432:        if (name && uid) {
        -: 2433:            /* verify name/gid match */
        -: 2434:            const char *c_name;
        -: 2435:            uint64_t c_uid;
        -: 2436:
       18: 2437:            c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
       18: 2438:            c_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
       18: 2439:            if (c_name == NULL || c_uid == 0) {
    #####: 2440:                DEBUG(2, ("Attribute is missing but this should never happen!\n"));
    #####: 2441:                ret = EFAULT;
    #####: 2442:                goto fail;
        -: 2443:            }
       18: 2444:            if (strcmp(name, c_name) || uid != c_uid) {
        -: 2445:                /* this is not the entry we are looking for */
    #####: 2446:                ret = EINVAL;
    #####: 2447:                goto fail;
        -: 2448:            }
        -: 2449:        }
        -: 2450:
      171: 2451:        ret = sysdb_delete_entry(sysdb, msg->dn, false);
      171: 2452:        if (ret) {
    #####: 2453:            goto fail;
        -: 2454:        }
        9: 2455:    } else if (ret == ENOENT && name != NULL) {
        -: 2456:        /* Perhaps a ghost user? */
    #####: 2457:        filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_GHOST, name);
    #####: 2458:        if (filter == NULL) {
    #####: 2459:            ret = ENOMEM;
    #####: 2460:            goto fail;
        -: 2461:        }
        -: 2462:
    #####: 2463:        ret = sysdb_search_groups(tmp_ctx, sysdb, domain,
        -: 2464:                                  filter, attrs, &msg_count, &msgs);
    #####: 2465:        if (ret != EOK) {
    #####: 2466:            goto fail;
        -: 2467:        }
        -: 2468:
    #####: 2469:        for (i = 0; i < msg_count; i++) {
    #####: 2470:            msg = ldb_msg_new(tmp_ctx);
    #####: 2471:            if (!msg) {
    #####: 2472:                ERROR_OUT(ret, ENOMEM, fail);
        -: 2473:            }
        -: 2474:
    #####: 2475:            msg->dn = msgs[i]->dn;
        -: 2476:
    #####: 2477:            ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name);
    #####: 2478:            if (ret) goto fail;
        -: 2479:
    #####: 2480:            ret = ldb_modify(sysdb->ldb, msg);
    #####: 2481:            ret = sysdb_error_to_errno(ret);
    #####: 2482:            if (ret != EOK) {
    #####: 2483:                goto fail;
        -: 2484:            }
        -: 2485:
    #####: 2486:            talloc_zfree(msg);
        -: 2487:        }
        -: 2488:    } else {
        -: 2489:        goto fail;
        -: 2490:    }
        -: 2491:
        -: 2492:
      171: 2493:    talloc_zfree(tmp_ctx);
      171: 2494:    return EOK;
        -: 2495:
        -: 2496:fail:
        9: 2497:    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        9: 2498:    talloc_zfree(tmp_ctx);
        9: 2499:    return ret;
        -: 2500:}
        -: 2501:
        -: 2502:
        -: 2503:/* =Search-Groups-with-Custom-Filter===================================== */
        -: 2504:
    #####: 2505:int sysdb_search_groups(TALLOC_CTX *mem_ctx,
        -: 2506:                        struct sysdb_ctx *sysdb,
        -: 2507:                        struct sss_domain_info *domain,
        -: 2508:                        const char *sub_filter,
        -: 2509:                        const char **attrs,
        -: 2510:                        size_t *msgs_count,
        -: 2511:                        struct ldb_message ***msgs)
        -: 2512:{
        -: 2513:    TALLOC_CTX *tmp_ctx;
        -: 2514:    struct ldb_dn *basedn;
        -: 2515:    char *filter;
        -: 2516:    int ret;
        -: 2517:
    #####: 2518:    tmp_ctx = talloc_new(NULL);
    #####: 2519:    if (!tmp_ctx) {
    #####: 2520:        return ENOMEM;
        -: 2521:    }
        -: 2522:
    #####: 2523:    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -: 2524:                            SYSDB_TMPL_GROUP_BASE, domain->name);
    #####: 2525:    if (!basedn) {
    #####: 2526:        DEBUG(2, ("Failed to build base dn\n"));
    #####: 2527:        ret = ENOMEM;
    #####: 2528:        goto fail;
        -: 2529:    }
        -: 2530:
    #####: 2531:    filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_GC, sub_filter);
    #####: 2532:    if (!filter) {
    #####: 2533:        DEBUG(2, ("Failed to build filter\n"));
    #####: 2534:        ret = ENOMEM;
    #####: 2535:        goto fail;
        -: 2536:    }
        -: 2537:
    #####: 2538:    DEBUG(SSSDBG_TRACE_INTERNAL,
        -: 2539:          ("Search groups with filter: %s\n", filter));
        -: 2540:
    #####: 2541:    ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
        -: 2542:                             LDB_SCOPE_SUBTREE, filter, attrs,
        -: 2543:                             msgs_count, msgs);
    #####: 2544:    if (ret) {
    #####: 2545:        goto fail;
        -: 2546:    }
        -: 2547:
    #####: 2548:    talloc_zfree(tmp_ctx);
    #####: 2549:    return EOK;
        -: 2550:
        -: 2551:fail:
    #####: 2552:    if (ret == ENOENT) {
    #####: 2553:        DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n"));
        -: 2554:    }
    #####: 2555:    else if (ret) {
    #####: 2556:        DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2557:    }
    #####: 2558:    talloc_zfree(tmp_ctx);
    #####: 2559:    return ret;
        -: 2560:}
        -: 2561:
        -: 2562:/* =Delete-Group-by-Name-OR-gid=========================================== */
        -: 2563:
      954: 2564:int sysdb_delete_group(struct sysdb_ctx *sysdb,
        -: 2565:                       struct sss_domain_info *domain,
        -: 2566:                       const char *name, gid_t gid)
        -: 2567:{
        -: 2568:    TALLOC_CTX *tmp_ctx;
        -: 2569:    struct ldb_message *msg;
        -: 2570:    int ret;
        -: 2571:
      954: 2572:    tmp_ctx = talloc_new(NULL);
      954: 2573:    if (!tmp_ctx) {
    #####: 2574:        return ENOMEM;
        -: 2575:    }
        -: 2576:
      954: 2577:    if (name) {
       18: 2578:        ret = sysdb_search_group_by_name(tmp_ctx, sysdb, domain,
        -: 2579:                                         name, NULL, &msg);
        -: 2580:    } else {
      936: 2581:        ret = sysdb_search_group_by_gid(tmp_ctx, sysdb, domain,
        -: 2582:                                        gid, NULL, &msg);
        -: 2583:    }
      954: 2584:    if (ret) {
       27: 2585:        goto fail;
        -: 2586:    }
        -: 2587:
      927: 2588:    if (name && gid) {
        -: 2589:        /* verify name/gid match */
        -: 2590:        const char *c_name;
        -: 2591:        uint64_t c_gid;
        -: 2592:
       18: 2593:        c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
       18: 2594:        c_gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
       18: 2595:        if (c_name == NULL || c_gid == 0) {
    #####: 2596:            DEBUG(2, ("Attribute is missing but this should never happen!\n"));
    #####: 2597:            ret = EFAULT;
    #####: 2598:            goto fail;
        -: 2599:        }
       18: 2600:        if (strcmp(name, c_name) || gid != c_gid) {
        -: 2601:            /* this is not the entry we are looking for */
    #####: 2602:            ret = EINVAL;
    #####: 2603:            goto fail;
        -: 2604:        }
        -: 2605:    }
        -: 2606:
      927: 2607:    ret = sysdb_delete_entry(sysdb, msg->dn, false);
      927: 2608:    if (ret) {
    #####: 2609:        goto fail;
        -: 2610:    }
        -: 2611:
      927: 2612:    talloc_zfree(tmp_ctx);
      927: 2613:    return EOK;
        -: 2614:
        -: 2615:fail:
       27: 2616:    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
       27: 2617:    talloc_zfree(tmp_ctx);
       27: 2618:    return ret;
        -: 2619:}
        -: 2620:
        -: 2621:/* =Search-Netgroups-with-Custom-Filter===================================== */
        -: 2622:
    #####: 2623:int sysdb_search_netgroups(TALLOC_CTX *mem_ctx,
        -: 2624:                           struct sysdb_ctx *sysdb,
        -: 2625:                           struct sss_domain_info *domain,
        -: 2626:                           const char *sub_filter,
        -: 2627:                           const char **attrs,
        -: 2628:                           size_t *msgs_count,
        -: 2629:                           struct ldb_message ***msgs)
        -: 2630:{
        -: 2631:    TALLOC_CTX *tmp_ctx;
        -: 2632:    struct ldb_dn *basedn;
        -: 2633:    char *filter;
        -: 2634:    int ret;
        -: 2635:
    #####: 2636:    tmp_ctx = talloc_new(NULL);
    #####: 2637:    if (!tmp_ctx) {
    #####: 2638:        return ENOMEM;
        -: 2639:    }
        -: 2640:
    #####: 2641:    basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
        -: 2642:                            SYSDB_TMPL_NETGROUP_BASE, domain->name);
    #####: 2643:    if (!basedn) {
    #####: 2644:        DEBUG(2, ("Failed to build base dn\n"));
    #####: 2645:        ret = ENOMEM;
    #####: 2646:        goto fail;
        -: 2647:    }
        -: 2648:
    #####: 2649:    filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_NC, sub_filter);
    #####: 2650:    if (!filter) {
    #####: 2651:        DEBUG(2, ("Failed to build filter\n"));
    #####: 2652:        ret = ENOMEM;
    #####: 2653:        goto fail;
        -: 2654:    }
        -: 2655:
    #####: 2656:    DEBUG(6, ("Search netgroups with filter: %s\n", filter));
        -: 2657:
    #####: 2658:    ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
        -: 2659:                             LDB_SCOPE_SUBTREE, filter, attrs,
        -: 2660:                             msgs_count, msgs);
    #####: 2661:    if (ret) {
    #####: 2662:        goto fail;
        -: 2663:    }
        -: 2664:
    #####: 2665:    talloc_zfree(tmp_ctx);
    #####: 2666:    return EOK;
        -: 2667:
        -: 2668:fail:
    #####: 2669:    if (ret == ENOENT) {
    #####: 2670:        DEBUG(SSSDBG_TRACE_FUNC, ("Entry not found\n"));
        -: 2671:    } else {
    #####: 2672:        DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2673:    }
    #####: 2674:    talloc_zfree(tmp_ctx);
    #####: 2675:    return ret;
        -: 2676:}
        -: 2677:
        -: 2678:/* =Delete-Netgroup-by-Name============================================== */
        -: 2679:
       45: 2680:int sysdb_delete_netgroup(struct sysdb_ctx *sysdb,
        -: 2681:                          struct sss_domain_info *domain,
        -: 2682:                          const char *name)
        -: 2683:{
        -: 2684:    TALLOC_CTX *tmp_ctx;
        -: 2685:    struct ldb_message *msg;
        -: 2686:    int ret;
        -: 2687:
       45: 2688:    if (!name) return EINVAL;
        -: 2689:
       45: 2690:    tmp_ctx = talloc_new(NULL);
       45: 2691:    if (!tmp_ctx) {
    #####: 2692:        return ENOMEM;
        -: 2693:    }
        -: 2694:
       45: 2695:    ret = sysdb_search_netgroup_by_name(tmp_ctx, sysdb, domain,
        -: 2696:                                        name, NULL, &msg);
       45: 2697:    if (ret != EOK && ret != ENOENT) {
    #####: 2698:        DEBUG(6, ("sysdb_search_netgroup_by_name failed: %d (%s)\n",
        -: 2699:                   ret, strerror(ret)));
    #####: 2700:        goto done;
       45: 2701:    } else if (ret == ENOENT) {
    #####: 2702:        DEBUG(6, ("Netgroup does not exist, nothing to delete\n"));
    #####: 2703:        ret = EOK;
    #####: 2704:        goto done;
        -: 2705:    }
        -: 2706:
       45: 2707:    ret = sysdb_delete_entry(sysdb, msg->dn, false);
       45: 2708:    if (ret != EOK) {
    #####: 2709:        goto done;
        -: 2710:    }
        -: 2711:
        -: 2712:done:
       45: 2713:    if (ret != EOK) {
    #####: 2714:        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        -: 2715:    }
       45: 2716:    talloc_free(tmp_ctx);
       45: 2717:    return ret;
        -: 2718:}
        -: 2719:
        -: 2720:/* ========= Authentication against cached password ============ */
        -: 2721:
        -: 2722:
       54: 2723:errno_t check_failed_login_attempts(struct confdb_ctx *cdb,
        -: 2724:                                    struct ldb_message *ldb_msg,
        -: 2725:                                    uint32_t *failed_login_attempts,
        -: 2726:                                    time_t *delayed_until)
        -: 2727:{
        -: 2728:    int ret;
        -: 2729:    int allowed_failed_login_attempts;
        -: 2730:    int failed_login_delay;
        -: 2731:    time_t last_failed_login;
        -: 2732:    time_t end;
        -: 2733:    TALLOC_CTX *tmp_ctx;
        -: 2734:
       54: 2735:    tmp_ctx = talloc_new(NULL);
       54: 2736:    if (!tmp_ctx) {
    #####: 2737:        return ENOMEM;
        -: 2738:    }
        -: 2739:
       54: 2740:    *delayed_until = -1;
       54: 2741:    *failed_login_attempts = ldb_msg_find_attr_as_uint(ldb_msg,
        -: 2742:                                                SYSDB_FAILED_LOGIN_ATTEMPTS, 0);
       54: 2743:    last_failed_login = (time_t) ldb_msg_find_attr_as_int64(ldb_msg,
        -: 2744:                                                    SYSDB_LAST_FAILED_LOGIN, 0);
       54: 2745:    ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
        -: 2746:                         CONFDB_PAM_FAILED_LOGIN_ATTEMPTS,
        -: 2747:                         CONFDB_DEFAULT_PAM_FAILED_LOGIN_ATTEMPTS,
        -: 2748:                         &allowed_failed_login_attempts);
       54: 2749:    if (ret != EOK) {
    #####: 2750:        DEBUG(1, ("Failed to read the number of allowed failed login "
        -: 2751:                  "attempts.\n"));
    #####: 2752:        ret = EIO;
    #####: 2753:        goto done;
        -: 2754:    }
       54: 2755:    ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
        -: 2756:                         CONFDB_PAM_FAILED_LOGIN_DELAY,
        -: 2757:                         CONFDB_DEFAULT_PAM_FAILED_LOGIN_DELAY,
        -: 2758:                         &failed_login_delay);
       54: 2759:    if (ret != EOK) {
    #####: 2760:        DEBUG(1, ("Failed to read the failed login delay.\n"));
    #####: 2761:        ret = EIO;
    #####: 2762:        goto done;
        -: 2763:    }
       54: 2764:    DEBUG(9, ("Failed login attempts [%d], allowed failed login attempts [%d], "
        -: 2765:              "failed login delay [%d].\n", *failed_login_attempts,
        -: 2766:              allowed_failed_login_attempts, failed_login_delay));
        -: 2767:
       54: 2768:    if (allowed_failed_login_attempts) {
    #####: 2769:        if (*failed_login_attempts >= allowed_failed_login_attempts) {
    #####: 2770:            if (failed_login_delay) {
    #####: 2771:                end = last_failed_login + (failed_login_delay * 60);
    #####: 2772:                if (end < time(NULL)) {
    #####: 2773:                    DEBUG(7, ("failed_login_delay has passed, "
        -: 2774:                              "resetting failed_login_attempts.\n"));
    #####: 2775:                    *failed_login_attempts = 0;
        -: 2776:                } else {
    #####: 2777:                    DEBUG(7, ("login delayed until %lld.\n", (long long) end));
    #####: 2778:                    *delayed_until = end;
    #####: 2779:                    ret = EACCES;
    #####: 2780:                    goto done;
        -: 2781:                }
        -: 2782:            } else {
    #####: 2783:                DEBUG(4, ("Too many failed logins.\n"));
    #####: 2784:                ret = EACCES;
    #####: 2785:                goto done;
        -: 2786:            }
        -: 2787:        }
        -: 2788:    }
        -: 2789:
       54: 2790:    ret = EOK;
        -: 2791:done:
       54: 2792:    talloc_free(tmp_ctx);
       54: 2793:    return ret;
        -: 2794:}
        -: 2795:
       54: 2796:int sysdb_cache_auth(struct sysdb_ctx *sysdb,
        -: 2797:                     struct sss_domain_info *domain,
        -: 2798:                     const char *name,
        -: 2799:                     const char *password,
        -: 2800:                     struct confdb_ctx *cdb,
        -: 2801:                     bool just_check,
        -: 2802:                     time_t *_expire_date,
        -: 2803:                     time_t *_delayed_until)
        -: 2804:{
        -: 2805:    TALLOC_CTX *tmp_ctx;
       54: 2806:    const char *attrs[] = { SYSDB_NAME, SYSDB_CACHEDPWD, SYSDB_DISABLED,
        -: 2807:                            SYSDB_LAST_LOGIN, SYSDB_LAST_ONLINE_AUTH,
        -: 2808:                            "lastCachedPasswordChange",
        -: 2809:                            "accountExpires", SYSDB_FAILED_LOGIN_ATTEMPTS,
        -: 2810:                            SYSDB_LAST_FAILED_LOGIN, NULL };
        -: 2811:    struct ldb_message *ldb_msg;
        -: 2812:    const char *userhash;
        -: 2813:    char *comphash;
       54: 2814:    uint64_t lastLogin = 0;
        -: 2815:    int cred_expiration;
       54: 2816:    uint32_t failed_login_attempts = 0;
        -: 2817:    struct sysdb_attrs *update_attrs;
       54: 2818:    bool authentication_successful = false;
       54: 2819:    time_t expire_date = -1;
       54: 2820:    time_t delayed_until = -1;
        -: 2821:    int ret;
        -: 2822:
       54: 2823:    if (name == NULL || *name == '\0') {
    #####: 2824:        DEBUG(1, ("Missing user name.\n"));
    #####: 2825:        return EINVAL;
        -: 2826:    }
        -: 2827:
       54: 2828:    if (cdb == NULL) {
    #####: 2829:        DEBUG(1, ("Missing config db context.\n"));
    #####: 2830:        return EINVAL;
        -: 2831:    }
        -: 2832:
       54: 2833:    if (sysdb == NULL) {
    #####: 2834:        DEBUG(1, ("Missing sysdb db context.\n"));
    #####: 2835:        return EINVAL;
        -: 2836:    }
        -: 2837:
       54: 2838:    if (!domain->cache_credentials) {
    #####: 2839:        DEBUG(3, ("Cached credentials not available.\n"));
    #####: 2840:        return EINVAL;
        -: 2841:    }
        -: 2842:
       54: 2843:    tmp_ctx = talloc_new(NULL);
       54: 2844:    if (!tmp_ctx) {
    #####: 2845:        return ENOMEM;
        -: 2846:    }
        -: 2847:
       54: 2848:    ret = ldb_transaction_start(sysdb->ldb);
       54: 2849:    if (ret) {
    #####: 2850:        talloc_zfree(tmp_ctx);
    #####: 2851:        ret = sysdb_error_to_errno(ret);
    #####: 2852:        return ret;
        -: 2853:    }
        -: 2854:
       54: 2855:    ret = sysdb_search_user_by_name(tmp_ctx, sysdb, domain,
        -: 2856:                                    name, attrs, &ldb_msg);
       54: 2857:    if (ret != EOK) {
    #####: 2858:        DEBUG(1, ("sysdb_search_user_by_name failed [%d][%s].\n",
        -: 2859:                  ret, strerror(ret)));
    #####: 2860:        goto done;
        -: 2861:    }
        -: 2862:
        -: 2863:    /* Check offline_auth_cache_timeout */
       54: 2864:    lastLogin = ldb_msg_find_attr_as_uint64(ldb_msg,
        -: 2865:                                            SYSDB_LAST_ONLINE_AUTH,
        -: 2866:                                            0);
        -: 2867:
       54: 2868:    ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
        -: 2869:                         CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration);
       54: 2870:    if (ret != EOK) {
    #####: 2871:        DEBUG(1, ("Failed to read expiration time of offline credentials.\n"));
    #####: 2872:        goto done;
        -: 2873:    }
       54: 2874:    DEBUG(9, ("Offline credentials expiration is [%d] days.\n",
        -: 2875:              cred_expiration));
        -: 2876:
       54: 2877:    if (cred_expiration) {
       27: 2878:        expire_date = lastLogin + (cred_expiration * 86400);
       27: 2879:        if (expire_date < time(NULL)) {
    #####: 2880:            DEBUG(4, ("Cached user entry is too old.\n"));
    #####: 2881:            expire_date = 0;
    #####: 2882:            ret = EACCES;
    #####: 2883:            goto done;
        -: 2884:        }
        -: 2885:    } else {
       27: 2886:        expire_date = 0;
        -: 2887:    }
        -: 2888:
       54: 2889:    ret = check_failed_login_attempts(cdb, ldb_msg, &failed_login_attempts,
        -: 2890:                                      &delayed_until);
       54: 2891:    if (ret != EOK) {
    #####: 2892:        DEBUG(1, ("Failed to check login attempts\n"));
    #####: 2893:        goto done;
        -: 2894:    }
        -: 2895:
        -: 2896:    /* TODO: verify user account (disabled, expired ...) */
        -: 2897:
       54: 2898:    userhash = ldb_msg_find_attr_as_string(ldb_msg, SYSDB_CACHEDPWD, NULL);
       54: 2899:    if (userhash == NULL || *userhash == '\0') {
       18: 2900:        DEBUG(4, ("Cached credentials not available.\n"));
       18: 2901:        ret = ENOENT;
       18: 2902:        goto done;
        -: 2903:    }
        -: 2904:
       36: 2905:    ret = s3crypt_sha512(tmp_ctx, password, userhash, &comphash);
       36: 2906:    if (ret) {
    #####: 2907:        DEBUG(4, ("Failed to create password hash.\n"));
    #####: 2908:        ret = EFAULT;
    #####: 2909:        goto done;
        -: 2910:    }
        -: 2911:
       36: 2912:    update_attrs = sysdb_new_attrs(tmp_ctx);
       36: 2913:    if (update_attrs == NULL) {
    #####: 2914:        DEBUG(1, ("sysdb_new_attrs failed.\n"));
    #####: 2915:        ret = ENOMEM;
    #####: 2916:        goto done;
        -: 2917:    }
        -: 2918:
       36: 2919:    if (strcmp(userhash, comphash) == 0) {
        -: 2920:        /* TODO: probable good point for audit logging */
       18: 2921:        DEBUG(4, ("Hashes do match!\n"));
       18: 2922:        authentication_successful = true;
        -: 2923:
       18: 2924:        if (just_check) {
    #####: 2925:            ret = EOK;
    #####: 2926:            goto done;
        -: 2927:        }
        -: 2928:
       18: 2929:        ret = sysdb_attrs_add_time_t(update_attrs,
        -: 2930:                                     SYSDB_LAST_LOGIN, time(NULL));
       18: 2931:        if (ret != EOK) {
    #####: 2932:            DEBUG(3, ("sysdb_attrs_add_time_t failed, "
        -: 2933:                      "but authentication is successful.\n"));
    #####: 2934:            ret = EOK;
    #####: 2935:            goto done;
        -: 2936:        }
        -: 2937:
       18: 2938:        ret = sysdb_attrs_add_uint32(update_attrs,
        -: 2939:                                     SYSDB_FAILED_LOGIN_ATTEMPTS, 0U);
       18: 2940:        if (ret != EOK) {
    #####: 2941:            DEBUG(3, ("sysdb_attrs_add_uint32 failed, "
        -: 2942:                      "but authentication is successful.\n"));
    #####: 2943:            ret = EOK;
    #####: 2944:            goto done;
        -: 2945:        }
        -: 2946:
        -: 2947:
        -: 2948:    } else {
       18: 2949:        DEBUG(4, ("Authentication failed.\n"));
       18: 2950:        authentication_successful = false;
        -: 2951:
       18: 2952:        ret = sysdb_attrs_add_time_t(update_attrs,
        -: 2953:                                     SYSDB_LAST_FAILED_LOGIN,
        -: 2954:                                     time(NULL));
       18: 2955:        if (ret != EOK) {
    #####: 2956:            DEBUG(3, ("sysdb_attrs_add_time_t failed\n."));
    #####: 2957:            goto done;
        -: 2958:        }
        -: 2959:
       18: 2960:        ret = sysdb_attrs_add_uint32(update_attrs,
        -: 2961:                                     SYSDB_FAILED_LOGIN_ATTEMPTS,
        -: 2962:                                     ++failed_login_attempts);
       18: 2963:        if (ret != EOK) {
    #####: 2964:            DEBUG(3, ("sysdb_attrs_add_uint32 failed.\n"));
    #####: 2965:            goto done;
        -: 2966:        }
        -: 2967:    }
        -: 2968:
       36: 2969:    ret = sysdb_set_user_attr(sysdb, domain,
        -: 2970:                              name, update_attrs, LDB_FLAG_MOD_REPLACE);
       36: 2971:    if (ret) {
    #####: 2972:        DEBUG(1, ("Failed to update Login attempt information!\n"));
        -: 2973:    }
        -: 2974:
        -: 2975:done:
       54: 2976:    if (_expire_date != NULL) {
       54: 2977:        *_expire_date = expire_date;
        -: 2978:    }
       54: 2979:    if (_delayed_until != NULL) {
       54: 2980:        *_delayed_until = delayed_until;
        -: 2981:    }
       54: 2982:    if (ret) {
       18: 2983:        ldb_transaction_cancel(sysdb->ldb);
        -: 2984:    } else {
       36: 2985:        ret = ldb_transaction_commit(sysdb->ldb);
       36: 2986:        ret = sysdb_error_to_errno(ret);
       36: 2987:        if (ret) {
    #####: 2988:            DEBUG(2, ("Failed to commit transaction!\n"));
        -: 2989:        }
        -: 2990:    }
       54: 2991:    if (authentication_successful) {
       18: 2992:        ret = EOK;
        -: 2993:    } else {
       36: 2994:        if (ret == EOK) {
       18: 2995:            ret = EINVAL;
        -: 2996:        }
        -: 2997:    }
       54: 2998:    talloc_free(tmp_ctx);
       54: 2999:    return ret;
        -: 3000:}
        -: 3001:
       27: 3002:errno_t sysdb_update_members(struct sysdb_ctx *sysdb,
        -: 3003:                             struct sss_domain_info *domain,
        -: 3004:                             const char *member,
        -: 3005:                             enum sysdb_member_type type,
        -: 3006:                             const char *const *add_groups,
        -: 3007:                             const char *const *del_groups)
        -: 3008:{
        -: 3009:    errno_t ret;
        -: 3010:    errno_t sret;
        -: 3011:    int i;
       27: 3012:    bool in_transaction = false;
        -: 3013:
       27: 3014:    TALLOC_CTX *tmp_ctx = talloc_new(NULL);
       27: 3015:    if(!tmp_ctx) {
    #####: 3016:        return ENOMEM;
        -: 3017:    }
        -: 3018:
       27: 3019:    ret = sysdb_transaction_start(sysdb);
       27: 3020:    if (ret != EOK) {
    #####: 3021:        DEBUG(0, ("Failed to start update transaction\n"));
    #####: 3022:        goto done;
        -: 3023:    }
        -: 3024:
       27: 3025:    in_transaction = true;
        -: 3026:
       27: 3027:    if (add_groups) {
        -: 3028:        /* Add the user to all add_groups */
       45: 3029:        for (i = 0; add_groups[i]; i++) {
       27: 3030:            ret = sysdb_add_group_member(sysdb, domain,
       27: 3031:                                         add_groups[i], member, type);
       27: 3032:            if (ret != EOK) {
    #####: 3033:                DEBUG(1, ("Could not add member [%s] to group [%s]. "
        -: 3034:                          "Skipping.\n", member, add_groups[i]));
        -: 3035:                /* Continue on, we should try to finish the rest */
        -: 3036:            }
        -: 3037:        }
        -: 3038:    }
        -: 3039:
       27: 3040:    if (del_groups) {
        -: 3041:        /* Remove the user from all del_groups */
       45: 3042:        for (i = 0; del_groups[i]; i++) {
       27: 3043:            ret = sysdb_remove_group_member(sysdb, domain,
       27: 3044:                                            del_groups[i], member, type);
       27: 3045:            if (ret != EOK) {
    #####: 3046:                DEBUG(1, ("Could not remove member [%s] from group [%s]. "
        -: 3047:                          "Skipping\n", member, del_groups[i]));
        -: 3048:                /* Continue on, we should try to finish the rest */
        -: 3049:            }
        -: 3050:        }
        -: 3051:    }
        -: 3052:
       27: 3053:    ret = sysdb_transaction_commit(sysdb);
       27: 3054:    if (ret != EOK) {
    #####: 3055:        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
    #####: 3056:        goto done;
        -: 3057:    }
        -: 3058:
       27: 3059:    in_transaction = false;
        -: 3060:
        -: 3061:done:
       27: 3062:    if (in_transaction) {
    #####: 3063:        sret = sysdb_transaction_cancel(sysdb);
    #####: 3064:        if (sret != EOK) {
    #####: 3065:            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
        -: 3066:        }
        -: 3067:    }
       27: 3068:    talloc_free(tmp_ctx);
       27: 3069:    return ret;
        -: 3070:}
        -: 3071:
    #####: 3072:errno_t sysdb_remove_attrs(struct sysdb_ctx *sysdb,
        -: 3073:                           struct sss_domain_info *domain,
        -: 3074:                           const char *name,
        -: 3075:                           enum sysdb_member_type type,
        -: 3076:                           char **remove_attrs)
        -: 3077:{
        -: 3078:    errno_t ret;
    #####: 3079:    errno_t sret = EOK;
    #####: 3080:    bool in_transaction = false;
        -: 3081:    struct ldb_message *msg;
        -: 3082:    int lret;
        -: 3083:    size_t i;
        -: 3084:
    #####: 3085:    msg = ldb_msg_new(NULL);
    #####: 3086:    if (!msg) return ENOMEM;
        -: 3087:
    #####: 3088:    switch(type) {
        -: 3089:    case SYSDB_MEMBER_USER:
    #####: 3090:        msg->dn = sysdb_user_dn(sysdb, msg, domain, name);
    #####: 3091:        break;
        -: 3092:
        -: 3093:    case SYSDB_MEMBER_GROUP:
    #####: 3094:        msg->dn = sysdb_group_dn(sysdb, msg, domain, name);
    #####: 3095:        break;
        -: 3096:
        -: 3097:    case SYSDB_MEMBER_NETGROUP:
    #####: 3098:        msg->dn = sysdb_netgroup_dn(sysdb, msg, domain, name);
    #####: 3099:        break;
        -: 3100:
        -: 3101:    case SYSDB_MEMBER_SERVICE:
    #####: 3102:        msg->dn = sysdb_svc_dn(sysdb, msg, domain->name, name);
    #####: 3103:        break;
        -: 3104:    }
    #####: 3105:    if (!msg->dn) {
    #####: 3106:        ret = ENOMEM;
    #####: 3107:        goto done;
        -: 3108:    }
        -: 3109:
    #####: 3110:    ret = sysdb_transaction_start(sysdb);
    #####: 3111:    if (ret != EOK) {
    #####: 3112:        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
    #####: 3113:        goto done;
        -: 3114:    }
        -: 3115:
    #####: 3116:    in_transaction = true;
        -: 3117:
    #####: 3118:    for (i = 0; remove_attrs[i]; i++) {
        -: 3119:        /* SYSDB_MEMBEROF is exclusively handled by the memberof plugin */
    #####: 3120:        if (strcasecmp(remove_attrs[i], SYSDB_MEMBEROF) == 0) {
    #####: 3121:            continue;
        -: 3122:        }
    #####: 3123:        DEBUG(8, ("Removing attribute [%s] from [%s]\n",
        -: 3124:                  remove_attrs[i], name));
    #####: 3125:        lret = ldb_msg_add_empty(msg, remove_attrs[i],
        -: 3126:                                 LDB_FLAG_MOD_DELETE, NULL);
    #####: 3127:        if (lret != LDB_SUCCESS) {
    #####: 3128:            ret = sysdb_error_to_errno(lret);
    #####: 3129:            goto done;
        -: 3130:        }
        -: 3131:
        -: 3132:        /* We need to do individual modifies so that we can
        -: 3133:         * skip unknown attributes. Otherwise, any nonexistent
        -: 3134:         * attribute in the sysdb will cause other removals to
        -: 3135:         * fail.
        -: 3136:         */
    #####: 3137:        lret = ldb_modify(sysdb->ldb, msg);
    #####: 3138:        if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
    #####: 3139:            ret = sysdb_error_to_errno(lret);
    #####: 3140:            goto done;
        -: 3141:        }
        -: 3142:
        -: 3143:        /* Remove this attribute and move on to the next one */
    #####: 3144:        ldb_msg_remove_attr(msg, remove_attrs[i]);
        -: 3145:    }
        -: 3146:
    #####: 3147:    ret = sysdb_transaction_commit(sysdb);
    #####: 3148:    if (ret != EOK) {
    #####: 3149:        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
    #####: 3150:        goto done;
        -: 3151:    }
        -: 3152:
    #####: 3153:    in_transaction = false;
        -: 3154:
    #####: 3155:    ret = EOK;
        -: 3156:done:
    #####: 3157:    if (in_transaction) {
    #####: 3158:        sret = sysdb_transaction_cancel(sysdb);
    #####: 3159:        if (sret != EOK) {
    #####: 3160:            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
        -: 3161:        }
        -: 3162:    }
    #####: 3163:    talloc_free(msg);
    #####: 3164:    return ret;
        -: 3165:}
-------------- next part --------------
        -:    0:Source:src/tests/sysdb-tests.c
        -:    0:Graph:src/tests/sysdb_tests-sysdb-tests.gcno
        -:    0:Data:src/tests/sysdb_tests-sysdb-tests.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:/*
        -:    2:   SSSD
        -:    3:
        -:    4:   System Database
        -:    5:
        -:    6:   Copyright (C) Stephen Gallagher <sgallagh at redhat.com>	2009
        -:    7:
        -:    8:   This program is free software; you can redistribute it and/or modify
        -:    9:   it under the terms of the GNU General Public License as published by
        -:   10:   the Free Software Foundation; either version 3 of the License, or
        -:   11:   (at your option) any later version.
        -:   12:
        -:   13:   This program is distributed in the hope that it will be useful,
        -:   14:   but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   15:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   16:   GNU General Public License for more details.
        -:   17:
        -:   18:   You should have received a copy of the GNU General Public License
        -:   19:   along with this program.  If not, see <http://www.gnu.org/licenses/>.
        -:   20:*/
        -:   21:
        -:   22:#include <stdlib.h>
        -:   23:#include <check.h>
        -:   24:#include <talloc.h>
        -:   25:#include <tevent.h>
        -:   26:#include <popt.h>
        -:   27:#include <sys/stat.h>
        -:   28:#include <sys/types.h>
        -:   29:#include "util/util.h"
        -:   30:#include "confdb/confdb_setup.h"
        -:   31:#include "db/sysdb_private.h"
        -:   32:#include "db/sysdb_services.h"
        -:   33:#include "db/sysdb_autofs.h"
        -:   34:#include "tests/common.h"
        -:   35:
        -:   36:#define TESTS_PATH "tests_sysdb"
        -:   37:#define TEST_CONF_FILE "tests_conf.ldb"
        -:   38:
        -:   39:#define TEST_ATTR_NAME "test_attr_name"
        -:   40:#define TEST_ATTR_VALUE "test_attr_value"
        -:   41:#define TEST_ATTR_UPDATE_VALUE "test_attr_update_value"
        -:   42:#define TEST_ATTR_ADD_NAME "test_attr_add_name"
        -:   43:#define TEST_ATTR_ADD_VALUE "test_attr_add_value"
        -:   44:#define CUSTOM_TEST_CONTAINER "custom_test_container"
        -:   45:#define CUSTOM_TEST_OBJECT "custom_test_object"
        -:   46:
        -:   47:#define ASQ_TEST_USER "testuser27010"
        -:   48:#define ASQ_TEST_USER_UID 27010
        -:   49:
        -:   50:#define MBO_USER_BASE 27500
        -:   51:#define MBO_GROUP_BASE 28500
        -:   52:#define NUM_GHOSTS 10
        -:   53:
        -:   54:#define TEST_AUTOFS_MAP_BASE 29500
        -:   55:
        -:   56:struct sysdb_test_ctx {
        -:   57:    struct sysdb_ctx *sysdb;
        -:   58:    struct confdb_ctx *confdb;
        -:   59:    struct tevent_context *ev;
        -:   60:    struct sss_domain_info *domain;
        -:   61:};
        -:   62:
      763:   63:static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
        -:   64:{
        -:   65:    struct sysdb_test_ctx *test_ctx;
        -:   66:    char *conf_db;
        -:   67:    int ret;
        -:   68:
        -:   69:    const char *val[2];
      763:   70:    val[1] = NULL;
        -:   71:
        -:   72:    /* Create tests directory if it doesn't exist */
        -:   73:    /* (relative to current dir) */
      763:   74:    ret = mkdir(TESTS_PATH, 0775);
      763:   75:    if (ret == -1 && errno != EEXIST) {
    #####:   76:        fail("Could not create %s directory", TESTS_PATH);
    #####:   77:        return EFAULT;
        -:   78:    }
        -:   79:
      763:   80:    test_ctx = talloc_zero(NULL, struct sysdb_test_ctx);
      763:   81:    if (test_ctx == NULL) {
    #####:   82:        fail("Could not allocate memory for test context");
    #####:   83:        return ENOMEM;
        -:   84:    }
        -:   85:
        -:   86:    /* Create an event context
        -:   87:     * It will not be used except in confdb_init and sysdb_init
        -:   88:     */
      763:   89:    test_ctx->ev = tevent_context_init(test_ctx);
      763:   90:    if (test_ctx->ev == NULL) {
    #####:   91:        fail("Could not create event context");
    #####:   92:        talloc_free(test_ctx);
    #####:   93:        return EIO;
        -:   94:    }
        -:   95:
      763:   96:    conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE);
      763:   97:    if (conf_db == NULL) {
    #####:   98:        fail("Out of memory, aborting!");
    #####:   99:        talloc_free(test_ctx);
    #####:  100:        return ENOMEM;
        -:  101:    }
      763:  102:    DEBUG(3, ("CONFDB: %s\n", conf_db));
        -:  103:
        -:  104:    /* Connect to the conf db */
      763:  105:    ret = confdb_init(test_ctx, &test_ctx->confdb, conf_db);
      763:  106:    if (ret != EOK) {
    #####:  107:        fail("Could not initialize connection to the confdb");
    #####:  108:        talloc_free(test_ctx);
    #####:  109:        return ret;
        -:  110:    }
        -:  111:
      763:  112:    val[0] = "LOCAL";
      763:  113:    ret = confdb_add_param(test_ctx->confdb, true,
        -:  114:                           "config/sssd", "domains", val);
      763:  115:    if (ret != EOK) {
    #####:  116:        fail("Could not initialize domains placeholder");
    #####:  117:        talloc_free(test_ctx);
    #####:  118:        return ret;
        -:  119:    }
        -:  120:
      763:  121:    val[0] = "local";
      763:  122:    ret = confdb_add_param(test_ctx->confdb, true,
        -:  123:                           "config/domain/LOCAL", "id_provider", val);
      763:  124:    if (ret != EOK) {
    #####:  125:        fail("Could not initialize provider");
    #####:  126:        talloc_free(test_ctx);
    #####:  127:        return ret;
        -:  128:    }
        -:  129:
      763:  130:    val[0] = "TRUE";
      763:  131:    ret = confdb_add_param(test_ctx->confdb, true,
        -:  132:                           "config/domain/LOCAL", "enumerate", val);
      763:  133:    if (ret != EOK) {
    #####:  134:        fail("Could not initialize LOCAL domain");
    #####:  135:        talloc_free(test_ctx);
    #####:  136:        return ret;
        -:  137:    }
        -:  138:
      763:  139:    val[0] = "TRUE";
      763:  140:    ret = confdb_add_param(test_ctx->confdb, true,
        -:  141:                           "config/domain/LOCAL", "cache_credentials", val);
      763:  142:    if (ret != EOK) {
    #####:  143:        fail("Could not initialize LOCAL domain");
    #####:  144:        talloc_free(test_ctx);
    #####:  145:        return ret;
        -:  146:    }
        -:  147:
      763:  148:    ret = sssd_domain_init(test_ctx, test_ctx->confdb, "local",
        -:  149:                           TESTS_PATH, &test_ctx->domain);
      763:  150:    if (ret != EOK) {
    #####:  151:        fail("Could not initialize connection to the sysdb (%d)", ret);
    #####:  152:        talloc_free(test_ctx);
    #####:  153:        return ret;
        -:  154:    }
      763:  155:    test_ctx->sysdb = test_ctx->domain->sysdb;
        -:  156:
      763:  157:    *ctx = test_ctx;
      763:  158:    return EOK;
        -:  159:}
        -:  160:
        -:  161:struct test_data {
        -:  162:    struct tevent_context *ev;
        -:  163:    struct sysdb_test_ctx *ctx;
        -:  164:
        -:  165:    const char *username;
        -:  166:    const char *groupname;
        -:  167:    const char *netgrname;
        -:  168:    const char *autofsmapname;
        -:  169:    uid_t uid;
        -:  170:    gid_t gid;
        -:  171:    const char *shell;
        -:  172:
        -:  173:    bool finished;
        -:  174:    int error;
        -:  175:
        -:  176:    struct sysdb_attrs *attrs;
        -:  177:    const char **attrlist;
        -:  178:    char **memberlist;
        -:  179:    struct ldb_message *msg;
        -:  180:
        -:  181:    size_t msgs_count;
        -:  182:    struct ldb_message **msgs;
        -:  183:};
        -:  184:
       10:  185:static int test_add_user(struct test_data *data)
        -:  186:{
        -:  187:    char *homedir;
        -:  188:    char *gecos;
        -:  189:    int ret;
        -:  190:
       10:  191:    homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
       10:  192:    gecos = talloc_asprintf(data, "Test User %d", data->uid);
        -:  193:
       10:  194:    ret = sysdb_add_user(data->ctx->sysdb, data->ctx->domain, data->username,
        -:  195:                         data->uid, 0, gecos, homedir, "/bin/bash",
        -:  196:                         NULL, NULL, 0, 0);
       10:  197:    return ret;
        -:  198:}
        -:  199:
       45:  200:static int test_store_user(struct test_data *data)
        -:  201:{
        -:  202:    char *homedir;
        -:  203:    char *gecos;
        -:  204:    int ret;
        -:  205:
       45:  206:    homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
       45:  207:    gecos = talloc_asprintf(data, "Test User %d", data->uid);
        -:  208:
       45:  209:    ret = sysdb_store_user(data->ctx->sysdb, data->ctx->domain,
        -:  210:                           data->username, "x",
        -:  211:                           data->uid, 0, gecos, homedir,
       45:  212:                           data->shell ? data->shell : "/bin/bash",
        -:  213:                           NULL, NULL, NULL, -1, 0);
       45:  214:    return ret;
        -:  215:}
        -:  216:
       10:  217:static int test_remove_user(struct test_data *data)
        -:  218:{
        -:  219:    struct ldb_dn *user_dn;
        -:  220:    int ret;
        -:  221:
       20:  222:    user_dn = sysdb_user_dn(data->ctx->sysdb, data,
       10:  223:                            data->ctx->domain, data->username);
       10:  224:    if (!user_dn) return ENOMEM;
        -:  225:
       10:  226:    ret = sysdb_delete_entry(data->ctx->sysdb, user_dn, true);
       10:  227:    return ret;
        -:  228:}
        -:  229:
       15:  230:static int test_remove_user_by_uid(struct test_data *data)
        -:  231:{
        -:  232:    int ret;
        -:  233:
       30:  234:    ret = sysdb_delete_user(data->ctx->sysdb,
       15:  235:                            data->ctx->domain, NULL, data->uid);
       15:  236:    return ret;
        -:  237:}
        -:  238:
        1:  239:static int test_remove_nonexistent_group(struct test_data *data)
        -:  240:{
        -:  241:    int ret;
        -:  242:
        2:  243:    ret = sysdb_delete_group(data->ctx->sysdb,
        1:  244:                             data->ctx->domain, NULL, data->uid);
        1:  245:    return ret;
        -:  246:}
        -:  247:
        1:  248:static int test_remove_nonexistent_user(struct test_data *data)
        -:  249:{
        -:  250:    int ret;
        -:  251:
        2:  252:    ret = sysdb_delete_user(data->ctx->sysdb,
        1:  253:                            data->ctx->domain, NULL, data->uid);
        1:  254:    return ret;
        -:  255:}
        -:  256:
       10:  257:static int test_add_group(struct test_data *data)
        -:  258:{
        -:  259:    int ret;
        -:  260:
       10:  261:    ret = sysdb_add_group(data->ctx->sysdb, data->ctx->domain,
        -:  262:                          data->groupname, data->gid, data->attrs, 0, 0);
       10:  263:    return ret;
        -:  264:}
        -:  265:
       10:  266:static int test_add_incomplete_group(struct test_data *data)
        -:  267:{
        -:  268:    int ret;
        -:  269:
       20:  270:    ret = sysdb_add_incomplete_group(data->ctx->sysdb,
       10:  271:                                     data->ctx->domain, data->groupname,
        -:  272:                                     data->gid, NULL, true, 0);
       10:  273:    return ret;
        -:  274:}
        -:  275:
       20:  276:static int test_store_group(struct test_data *data)
        -:  277:{
        -:  278:    int ret;
        -:  279:
       20:  280:    ret = sysdb_store_group(data->ctx->sysdb, data->ctx->domain,
        -:  281:                            data->groupname, data->gid, data->attrs, -1, 0);
       20:  282:    return ret;
        -:  283:}
        -:  284:
       10:  285:static int test_remove_group(struct test_data *data)
        -:  286:{
        -:  287:    struct ldb_dn *group_dn;
        -:  288:    int ret;
        -:  289:
       20:  290:    group_dn = sysdb_group_dn(data->ctx->sysdb, data,
       10:  291:                              data->ctx->domain, data->groupname);
       10:  292:    if (!group_dn) return ENOMEM;
        -:  293:
       10:  294:    ret = sysdb_delete_entry(data->ctx->sysdb, group_dn, true);
       10:  295:    return ret;
        -:  296:}
        -:  297:
       93:  298:static int test_remove_group_by_gid(struct test_data *data)
        -:  299:{
        -:  300:    int ret;
        -:  301:
      186:  302:    ret = sysdb_delete_group(data->ctx->sysdb,
       93:  303:                             data->ctx->domain, NULL, data->gid);
       93:  304:    if (ret == ENOENT) {
        2:  305:        ret = EOK;
        -:  306:    }
       93:  307:    return ret;
        -:  308:}
        -:  309:
       10:  310:static int test_set_user_attr(struct test_data *data)
        -:  311:{
        -:  312:    int ret;
        -:  313:
       20:  314:    ret = sysdb_set_user_attr(data->ctx->sysdb,
       10:  315:                              data->ctx->domain, data->username,
        -:  316:                              data->attrs, SYSDB_MOD_REP);
       10:  317:    return ret;
        -:  318:}
        -:  319:
       39:  320:static int test_add_group_member(struct test_data *data)
        -:  321:{
        -:  322:    const char *username;
        -:  323:    int ret;
        -:  324:
       39:  325:    username = talloc_asprintf(data, "testuser%d", data->uid);
       39:  326:    if (username == NULL) {
    #####:  327:        return ENOMEM;
        -:  328:    }
        -:  329:
       39:  330:    ret = sysdb_add_group_member(data->ctx->sysdb, data->ctx->domain,
        -:  331:                                 data->groupname, username,
        -:  332:                                 SYSDB_MEMBER_USER);
       39:  333:    return ret;
        -:  334:}
        -:  335:
       10:  336:static int test_remove_group_member(struct test_data *data)
        -:  337:{
        -:  338:    const char *username;
        -:  339:    int ret;
        -:  340:
       10:  341:    username = talloc_asprintf(data, "testuser%d", data->uid);
       10:  342:    if (username == NULL) {
    #####:  343:        return ENOMEM;
        -:  344:    }
        -:  345:
       10:  346:    ret = sysdb_remove_group_member(data->ctx->sysdb, data->ctx->domain,
        -:  347:                                    data->groupname, username,
        -:  348:                                    SYSDB_MEMBER_USER);
       10:  349:    return ret;
        -:  350:}
        -:  351:
       11:  352:static int test_store_custom(struct test_data *data)
        -:  353:{
        -:  354:    char *object_name;
        -:  355:    int ret;
        -:  356:
       11:  357:    object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, data->uid);
       11:  358:    if (!object_name) {
    #####:  359:        return ENOMEM;
        -:  360:    }
        -:  361:
       11:  362:    ret = sysdb_store_custom(data->ctx->sysdb, data->ctx->domain, object_name,
        -:  363:                             CUSTOM_TEST_CONTAINER, data->attrs);
       11:  364:    return ret;
        -:  365:}
        -:  366:
        1:  367:static int test_delete_custom(struct test_data *data)
        -:  368:{
        -:  369:    int ret;
        -:  370:
        1:  371:    ret = sysdb_delete_custom(data->ctx->sysdb, data->ctx->domain,
        -:  372:                              CUSTOM_TEST_OBJECT, CUSTOM_TEST_CONTAINER);
        1:  373:    return ret;
        -:  374:}
        -:  375:
        1:  376:static int test_search_all_users(struct test_data *data)
        -:  377:{
        -:  378:    struct ldb_dn *base_dn;
        -:  379:    int ret;
        -:  380:
        1:  381:    base_dn = ldb_dn_new_fmt(data, data->ctx->sysdb->ldb, SYSDB_TMPL_USER_BASE,
        -:  382:                             "LOCAL");
        1:  383:    if (base_dn == NULL) {
    #####:  384:        return ENOMEM;
        -:  385:    }
        -:  386:
        1:  387:    ret = sysdb_search_entry(data, data->ctx->sysdb, base_dn,
        -:  388:                             LDB_SCOPE_SUBTREE, "objectClass=user",
        -:  389:                             data->attrlist, &data->msgs_count, &data->msgs);
        1:  390:    return ret;
        -:  391:}
        -:  392:
        1:  393:static int test_delete_recursive(struct test_data *data)
        -:  394:{
        -:  395:    struct ldb_dn *dn;
        -:  396:    int ret;
        -:  397:
        1:  398:    dn = ldb_dn_new_fmt(data, data->ctx->sysdb->ldb, SYSDB_DOM_BASE,
        -:  399:                        "LOCAL");
        1:  400:    if (!dn) {
    #####:  401:        return ENOMEM;
        -:  402:    }
        -:  403:
        1:  404:    ret = sysdb_delete_recursive(data->ctx->sysdb, dn, false);
        1:  405:    fail_unless(ret == EOK, "sysdb_delete_recursive returned [%d]", ret);
        1:  406:    return ret;
        -:  407:}
        -:  408:
       31:  409:static int test_memberof_store_group(struct test_data *data)
        -:  410:{
        -:  411:    int ret;
       31:  412:    struct sysdb_attrs *attrs = NULL;
        -:  413:    char *member;
        -:  414:    int i;
        -:  415:
       31:  416:    attrs = sysdb_new_attrs(data);
       31:  417:    if (!attrs) {
    #####:  418:        return ENOMEM;
        -:  419:    }
       59:  420:    for (i = 0; data->attrlist && data->attrlist[i]; i++) {
       28:  421:        member = sysdb_group_strdn(data, data->ctx->domain->name,
       28:  422:                                   data->attrlist[i]);
       28:  423:        if (!member) {
    #####:  424:            return ENOMEM;
        -:  425:        }
       28:  426:        ret = sysdb_attrs_steal_string(attrs, SYSDB_MEMBER, member);
       28:  427:        if (ret != EOK) {
    #####:  428:            return ret;
        -:  429:        }
        -:  430:    }
        -:  431:
       31:  432:    ret = sysdb_store_group(data->ctx->sysdb, data->ctx->domain,
        -:  433:                            data->groupname, data->gid, attrs, -1, 0);
       31:  434:    return ret;
        -:  435:}
        -:  436:
       40:  437:static int test_memberof_store_group_with_ghosts(struct test_data *data)
        -:  438:{
        -:  439:    int ret;
       40:  440:    struct sysdb_attrs *attrs = NULL;
        -:  441:    char *member;
        -:  442:    int i;
        -:  443:
       40:  444:    attrs = sysdb_new_attrs(data);
       40:  445:    if (!attrs) {
    #####:  446:        return ENOMEM;
        -:  447:    }
        -:  448:
       80:  449:    for (i = 0; data->attrlist && data->attrlist[i]; i++) {
       40:  450:        member = sysdb_group_strdn(data, data->ctx->domain->name,
       40:  451:                                   data->attrlist[i]);
       40:  452:        if (!member) {
    #####:  453:            return ENOMEM;
        -:  454:        }
       40:  455:        ret = sysdb_attrs_steal_string(attrs, SYSDB_MEMBER, member);
       40:  456:        if (ret != EOK) {
    #####:  457:            return ret;
        -:  458:        }
        -:  459:    }
        -:  460:
       90:  461:    for (i = 0; data->memberlist && data->memberlist[i]; i++) {
       50:  462:        ret = sysdb_attrs_steal_string(attrs, SYSDB_GHOST,
       50:  463:                                       data->memberlist[i]);
       50:  464:        if (ret != EOK) {
    #####:  465:            return ret;
        -:  466:        }
        -:  467:    }
        -:  468:
       40:  469:    ret = sysdb_store_group(data->ctx->sysdb, data->ctx->domain,
        -:  470:                            data->groupname, data->gid, attrs, -1, 0);
       40:  471:    return ret;
        -:  472:}
        -:  473:
       10:  474:static int test_add_basic_netgroup(struct test_data *data)
        -:  475:{
        -:  476:    const char *description;
        -:  477:    int ret;
        -:  478:
       10:  479:    description = talloc_asprintf(data, "Test Netgroup %d", data->uid);
        -:  480:
       10:  481:    ret = sysdb_add_basic_netgroup(data->ctx->sysdb, data->ctx->domain,
        -:  482:                                   data->netgrname, description);
       10:  483:    return ret;
        -:  484:}
        -:  485:
        5:  486:static int test_remove_netgroup_entry(struct test_data *data)
        -:  487:{
        -:  488:    struct ldb_dn *netgroup_dn;
        -:  489:    int ret;
        -:  490:
       10:  491:    netgroup_dn = sysdb_netgroup_dn(data->ctx->sysdb, data,
        5:  492:                                    data->ctx->domain, data->netgrname);
        5:  493:    if (!netgroup_dn) return ENOMEM;
        -:  494:
        5:  495:    ret = sysdb_delete_entry(data->ctx->sysdb, netgroup_dn, true);
        5:  496:    return ret;
        -:  497:}
        -:  498:
        5:  499:static int test_remove_netgroup_by_name(struct test_data *data)
        -:  500:{
        -:  501:    int ret;
        -:  502:
       10:  503:    ret = sysdb_delete_netgroup(data->ctx->sysdb,
        5:  504:                                data->ctx->domain, data->netgrname);
        5:  505:    return ret;
        -:  506:}
        -:  507:
       10:  508:static int test_set_netgroup_attr(struct test_data *data)
        -:  509:{
        -:  510:    int ret;
        -:  511:    const char *description;
       10:  512:    struct sysdb_attrs *attrs = NULL;
        -:  513:
       10:  514:    description = talloc_asprintf(data, "Sysdb Netgroup %d", data->uid);
        -:  515:
       10:  516:    attrs = sysdb_new_attrs(data);
       10:  517:    if (!attrs) {
    #####:  518:        return ENOMEM;
        -:  519:    }
        -:  520:
       10:  521:    ret = sysdb_attrs_add_string(attrs, SYSDB_DESCRIPTION, description);
       10:  522:    if (ret) {
    #####:  523:        return ret;
        -:  524:    }
        -:  525:
       10:  526:    ret = sysdb_set_netgroup_attr(data->ctx->sysdb, data->ctx->domain,
        -:  527:                                  data->netgrname, attrs, SYSDB_MOD_REP);
       10:  528:    return ret;
        -:  529:}
        -:  530:
       10:  531:START_TEST (test_sysdb_store_user)
        -:  532:{
        -:  533:    struct sysdb_test_ctx *test_ctx;
        -:  534:    struct test_data *data;
        -:  535:    int ret;
        -:  536:
        -:  537:    /* Setup */
       10:  538:    ret = setup_sysdb_tests(&test_ctx);
       10:  539:    if (ret != EOK) {
    #####:  540:        fail("Could not set up the test");
       10:  541:        return;
        -:  542:    }
        -:  543:
       10:  544:    data = talloc_zero(test_ctx, struct test_data);
       10:  545:    data->ctx = test_ctx;
       10:  546:    data->ev = test_ctx->ev;
       10:  547:    data->uid = _i;
       10:  548:    data->gid = _i;
       10:  549:    data->username = talloc_asprintf(data, "testuser%d", _i);
        -:  550:
       10:  551:    ret = test_store_user(data);
        -:  552:
       10:  553:    fail_if(ret != EOK, "Could not store user %s", data->username);
       10:  554:    talloc_free(test_ctx);
        -:  555:}
        -:  556:END_TEST
        -:  557:
       10:  558:START_TEST (test_sysdb_store_user_existing)
        -:  559:{
        -:  560:    struct sysdb_test_ctx *test_ctx;
        -:  561:    struct test_data *data;
        -:  562:    int ret;
        -:  563:
        -:  564:    /* Setup */
       10:  565:    ret = setup_sysdb_tests(&test_ctx);
       10:  566:    if (ret != EOK) {
    #####:  567:        fail("Could not set up the test");
       10:  568:        return;
        -:  569:    }
        -:  570:
       10:  571:    data = talloc_zero(test_ctx, struct test_data);
       10:  572:    data->ctx = test_ctx;
       10:  573:    data->ev = test_ctx->ev;
       10:  574:    data->uid = _i;
       10:  575:    data->gid = _i;
       10:  576:    data->username = talloc_asprintf(data, "testuser%d", _i);
       10:  577:    data->shell = talloc_asprintf(data, "/bin/ksh");
        -:  578:
       10:  579:    ret = test_store_user(data);
        -:  580:
       10:  581:    fail_if(ret != EOK, "Could not store user %s", data->username);
       10:  582:    talloc_free(test_ctx);
        -:  583:}
        -:  584:END_TEST
        -:  585:
       10:  586:START_TEST (test_sysdb_store_group)
        -:  587:{
        -:  588:    struct sysdb_test_ctx *test_ctx;
        -:  589:    struct test_data *data;
        -:  590:    int ret;
        -:  591:
        -:  592:    /* Setup */
       10:  593:    ret = setup_sysdb_tests(&test_ctx);
       10:  594:    if (ret != EOK) {
    #####:  595:        fail("Could not set up the test");
       10:  596:        return;
        -:  597:    }
        -:  598:
       10:  599:    data = talloc_zero(test_ctx, struct test_data);
       10:  600:    data->ctx = test_ctx;
       10:  601:    data->ev = test_ctx->ev;
       10:  602:    data->gid = _i;
       10:  603:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
        -:  604:
       10:  605:    ret = test_store_group(data);
        -:  606:
       10:  607:    fail_if(ret != EOK, "Could not store POSIX group #%d", _i);
       10:  608:    talloc_free(test_ctx);
        -:  609:}
        -:  610:END_TEST
        -:  611:
       10:  612:START_TEST (test_sysdb_remove_local_user)
        -:  613:{
        -:  614:    struct sysdb_test_ctx *test_ctx;
        -:  615:    struct test_data *data;
        -:  616:    int ret;
        -:  617:
        -:  618:    /* Setup */
       10:  619:    ret = setup_sysdb_tests(&test_ctx);
       10:  620:    if (ret != EOK) {
    #####:  621:        fail("Could not set up the test");
       10:  622:        return;
        -:  623:    }
        -:  624:
       10:  625:    data = talloc_zero(test_ctx, struct test_data);
       10:  626:    data->ctx = test_ctx;
       10:  627:    data->ev = test_ctx->ev;
       10:  628:    data->username = talloc_asprintf(data, "testuser%d", _i);
        -:  629:
       10:  630:    ret = test_remove_user(data);
        -:  631:
       10:  632:    fail_if(ret != EOK, "Could not remove user %s", data->username);
       10:  633:    talloc_free(test_ctx);
        -:  634:}
        -:  635:END_TEST
        -:  636:
       10:  637:START_TEST (test_sysdb_remove_local_user_by_uid)
        -:  638:{
        -:  639:    struct sysdb_test_ctx *test_ctx;
        -:  640:    struct test_data *data;
        -:  641:    int ret;
        -:  642:
        -:  643:    /* Setup */
       10:  644:    ret = setup_sysdb_tests(&test_ctx);
       10:  645:    if (ret != EOK) {
    #####:  646:        fail("Could not set up the test");
       10:  647:        return;
        -:  648:    }
        -:  649:
       10:  650:    data = talloc_zero(test_ctx, struct test_data);
       10:  651:    data->ctx = test_ctx;
       10:  652:    data->ev = test_ctx->ev;
       10:  653:    data->uid = _i;
        -:  654:
       10:  655:    ret = test_remove_user_by_uid(data);
        -:  656:
       10:  657:    fail_if(ret != EOK, "Could not remove user with uid %d", _i);
       10:  658:    talloc_free(test_ctx);
        -:  659:}
        -:  660:END_TEST
        -:  661:
       10:  662:START_TEST (test_sysdb_remove_local_group)
        -:  663:{
        -:  664:    struct sysdb_test_ctx *test_ctx;
        -:  665:    struct test_data *data;
        -:  666:    int ret;
        -:  667:
        -:  668:    /* Setup */
       10:  669:    ret = setup_sysdb_tests(&test_ctx);
       10:  670:    if (ret != EOK) {
    #####:  671:        fail("Could not set up the test");
       10:  672:        return;
        -:  673:    }
        -:  674:
       10:  675:    data = talloc_zero(test_ctx, struct test_data);
       10:  676:    data->ctx = test_ctx;
       10:  677:    data->ev = test_ctx->ev;
       10:  678:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
        -:  679:
       10:  680:    ret = test_remove_group(data);
        -:  681:
       10:  682:    fail_if(ret != EOK, "Could not remove group %s", data->groupname);
       10:  683:    talloc_free(test_ctx);
        -:  684:}
        -:  685:END_TEST
        -:  686:
       93:  687:START_TEST (test_sysdb_remove_local_group_by_gid)
        -:  688:{
        -:  689:    struct sysdb_test_ctx *test_ctx;
        -:  690:    struct test_data *data;
        -:  691:    int ret;
        -:  692:
        -:  693:    /* Setup */
       93:  694:    ret = setup_sysdb_tests(&test_ctx);
       93:  695:    if (ret != EOK) {
    #####:  696:        fail("Could not set up the test");
       93:  697:        return;
        -:  698:    }
        -:  699:
       93:  700:    data = talloc_zero(test_ctx, struct test_data);
       93:  701:    data->ctx = test_ctx;
       93:  702:    data->ev = test_ctx->ev;
       93:  703:    data->gid = _i;
        -:  704:
       93:  705:    ret = test_remove_group_by_gid(data);
        -:  706:
       93:  707:    fail_if(ret != EOK, "Could not remove group with gid %d", _i);
       93:  708:    talloc_free(test_ctx);
        -:  709:}
        -:  710:END_TEST
        -:  711:
       10:  712:START_TEST (test_sysdb_add_user)
        -:  713:{
        -:  714:    struct sysdb_test_ctx *test_ctx;
        -:  715:    struct test_data *data;
        -:  716:    int ret;
        -:  717:
        -:  718:    /* Setup */
       10:  719:    ret = setup_sysdb_tests(&test_ctx);
       10:  720:    if (ret != EOK) {
    #####:  721:        fail("Could not set up the test");
       10:  722:        return;
        -:  723:    }
        -:  724:
       10:  725:    data = talloc_zero(test_ctx, struct test_data);
       10:  726:    data->ctx = test_ctx;
       10:  727:    data->ev = test_ctx->ev;
       10:  728:    data->uid = _i;
       10:  729:    data->gid = _i;
       10:  730:    data->username = talloc_asprintf(data, "testuser%d", _i);
        -:  731:
       10:  732:    ret = test_add_user(data);
        -:  733:
       10:  734:    fail_if(ret != EOK, "Could not add user %s", data->username);
       10:  735:    talloc_free(test_ctx);
        -:  736:}
        -:  737:END_TEST
        -:  738:
       10:  739:START_TEST (test_sysdb_add_group)
        -:  740:{
        -:  741:    struct sysdb_test_ctx *test_ctx;
        -:  742:    struct test_data *data;
        -:  743:    int ret;
        -:  744:
        -:  745:    /* Setup */
       10:  746:    ret = setup_sysdb_tests(&test_ctx);
       10:  747:    if (ret != EOK) {
    #####:  748:        fail("Could not set up the test");
       10:  749:        return;
        -:  750:    }
        -:  751:
       10:  752:    data = talloc_zero(test_ctx, struct test_data);
       10:  753:    data->ctx = test_ctx;
       10:  754:    data->ev = test_ctx->ev;
       10:  755:    data->uid = _i;
       10:  756:    data->gid = _i;
       10:  757:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
        -:  758:
       10:  759:    ret = test_add_group(data);
        -:  760:
       10:  761:    fail_if(ret != EOK, "Could not add group %s", data->groupname);
       10:  762:    talloc_free(test_ctx);
        -:  763:}
        -:  764:END_TEST
        -:  765:
       10:  766:START_TEST (test_sysdb_add_group_with_ghosts)
        -:  767:{
        -:  768:    struct sysdb_test_ctx *test_ctx;
        -:  769:    struct test_data *data;
        -:  770:    int ret;
        -:  771:    char *membername;
        -:  772:    int j;
        -:  773:
        -:  774:    /* Setup */
       10:  775:    ret = setup_sysdb_tests(&test_ctx);
       10:  776:    if (ret != EOK) {
    #####:  777:        fail("Could not set up the test");
        -:  778:        return;
        -:  779:    }
        -:  780:
       10:  781:    data = talloc_zero(test_ctx, struct test_data);
       10:  782:    data->ctx = test_ctx;
       10:  783:    data->ev = test_ctx->ev;
       10:  784:    data->uid = _i;
       10:  785:    data->gid = _i;
       10:  786:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
       10:  787:    fail_unless(data->groupname != NULL, "Out of memory\n");
        -:  788:
       10:  789:    data->attrs = sysdb_new_attrs(data);
       10:  790:    if (ret != EOK) {
    #####:  791:        fail("Could not create the changeset");
        -:  792:        return;
        -:  793:    }
        -:  794:
       55:  795:    for (j = MBO_GROUP_BASE; j < _i; j++) {
       45:  796:        membername = talloc_asprintf(data, "testghost%d", j);
       45:  797:        fail_unless(membername != NULL, "Out of memory\n");
       45:  798:        ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, membername);
       45:  799:        if (ret != EOK) {
    #####:  800:            fail_unless(ret == EOK, "Cannot add attr\n");
        -:  801:        }
        -:  802:    }
        -:  803:
       10:  804:    ret = test_store_group(data);
        -:  805:
       10:  806:    fail_if(ret != EOK, "Could not add group %s", data->groupname);
       10:  807:    talloc_free(test_ctx);
        -:  808:}
        -:  809:END_TEST
        -:  810:
       10:  811:START_TEST (test_sysdb_add_incomplete_group)
        -:  812:{
        -:  813:    struct sysdb_test_ctx *test_ctx;
        -:  814:    struct test_data *data;
        -:  815:    int ret;
        -:  816:
        -:  817:    /* Setup */
       10:  818:    ret = setup_sysdb_tests(&test_ctx);
       10:  819:    if (ret != EOK) {
    #####:  820:        fail("Could not set up the test");
       10:  821:        return;
        -:  822:    }
        -:  823:
       10:  824:    data = talloc_zero(test_ctx, struct test_data);
       10:  825:    data->ctx = test_ctx;
       10:  826:    data->ev = test_ctx->ev;
       10:  827:    data->uid = _i;
       10:  828:    data->gid = _i;
       10:  829:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
        -:  830:
       10:  831:    ret = test_add_incomplete_group(data);
        -:  832:
       10:  833:    fail_if(ret != EOK, "Could not add incomplete group %s", data->groupname);
       10:  834:    talloc_free(test_ctx);
        -:  835:}
        -:  836:END_TEST
        -:  837:
       20:  838:START_TEST (test_sysdb_getpwnam)
        -:  839:{
        -:  840:    struct sysdb_test_ctx *test_ctx;
        -:  841:    struct ldb_result *res;
        -:  842:    const char *username;
        -:  843:    uid_t uid;
        -:  844:    int ret;
        -:  845:
        -:  846:    /* Setup */
       20:  847:    ret = setup_sysdb_tests(&test_ctx);
       20:  848:    if (ret != EOK) {
    #####:  849:        fail("Could not set up the test");
       20:  850:        return;
        -:  851:    }
        -:  852:
       20:  853:    username = talloc_asprintf(test_ctx, "testuser%d", _i);
        -:  854:
       40:  855:    ret = sysdb_getpwnam(test_ctx,
       20:  856:                         test_ctx->sysdb,
       20:  857:                         test_ctx->domain,
        -:  858:                         username, &res);
       20:  859:    if (ret) {
    #####:  860:        fail("sysdb_getpwnam failed for username %s (%d: %s)",
        -:  861:             username, ret, strerror(ret));
    #####:  862:        goto done;
        -:  863:    }
        -:  864:
       20:  865:    if (res->count != 1) {
    #####:  866:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####:  867:        goto done;
        -:  868:    }
        -:  869:
       20:  870:    uid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_UIDNUM, 0);
       20:  871:    fail_unless(uid == _i, "Did not find the expected UID");
        -:  872:
        -:  873:    /* Search for the user with the wrong case */
       20:  874:    username = talloc_asprintf(test_ctx, "TESTUSER%d", _i);
        -:  875:
       40:  876:    ret = sysdb_getpwnam(test_ctx,
       20:  877:                         test_ctx->sysdb,
       20:  878:                         test_ctx->domain,
        -:  879:                         username, &res);
       20:  880:    if (ret) {
    #####:  881:        fail("sysdb_getpwnam failed for username %s (%d: %s)",
        -:  882:             username, ret, strerror(ret));
    #####:  883:        goto done;
        -:  884:    }
        -:  885:
       20:  886:    if (res->count != 0) {
    #####:  887:        fail("The upper-case username search should fail.");
        -:  888:    }
        -:  889:
        -:  890:done:
       20:  891:    talloc_free(test_ctx);
        -:  892:}
        -:  893:END_TEST
        -:  894:
       10:  895:START_TEST (test_sysdb_getgrnam)
        -:  896:{
        -:  897:    struct sysdb_test_ctx *test_ctx;
        -:  898:    struct ldb_result *res;
        -:  899:    const char *groupname;
        -:  900:    gid_t gid;
        -:  901:    int ret;
        -:  902:
        -:  903:    /* Setup */
       10:  904:    ret = setup_sysdb_tests(&test_ctx);
       10:  905:    if (ret != EOK) {
    #####:  906:        fail("Could not set up the test");
       10:  907:        return;
        -:  908:    }
        -:  909:
       10:  910:    groupname = talloc_asprintf(test_ctx, "testgroup%d", _i);
        -:  911:
       20:  912:    ret = sysdb_getgrnam(test_ctx,
       10:  913:                         test_ctx->sysdb,
       10:  914:                         test_ctx->domain,
        -:  915:                         groupname, &res);
       10:  916:    if (ret) {
    #####:  917:        fail("sysdb_getgrnam failed for groupname %s (%d: %s)",
        -:  918:             groupname, ret, strerror(ret));
    #####:  919:        goto done;
        -:  920:    }
        -:  921:
       10:  922:    if (res->count != 1) {
    #####:  923:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####:  924:        goto done;
        -:  925:    }
        -:  926:
       10:  927:    gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
       10:  928:    fail_unless(gid == _i,
        -:  929:                "Did not find the expected GID (found %d expected %d)",
        -:  930:                gid, _i);
        -:  931:
        -:  932:    /* Search for the group with the wrong case */
       10:  933:    groupname = talloc_asprintf(test_ctx, "TESTGROUP%d", _i);
        -:  934:
       20:  935:    ret = sysdb_getgrnam(test_ctx,
       10:  936:                         test_ctx->sysdb,
       10:  937:                         test_ctx->domain,
        -:  938:                         groupname, &res);
       10:  939:    if (ret) {
    #####:  940:        fail("sysdb_getgrnam failed for groupname %s (%d: %s)",
        -:  941:             groupname, ret, strerror(ret));
    #####:  942:        goto done;
        -:  943:    }
        -:  944:
       10:  945:    if (res->count != 0) {
    #####:  946:        fail("The upper-case groupname search should fail.");
        -:  947:    }
        -:  948:
        -:  949:done:
       10:  950:    talloc_free(test_ctx);
        -:  951:}
        -:  952:END_TEST
        -:  953:
       10:  954:START_TEST (test_sysdb_getgrgid)
        -:  955:{
        -:  956:    struct sysdb_test_ctx *test_ctx;
        -:  957:    struct ldb_result *res;
        -:  958:    const char *e_groupname;
        -:  959:    const char *groupname;
        -:  960:    int ret;
        -:  961:
        -:  962:    /* Setup */
       10:  963:    ret = setup_sysdb_tests(&test_ctx);
       10:  964:    if (ret != EOK) {
    #####:  965:        fail("Could not set up the test");
       10:  966:        return;
        -:  967:    }
        -:  968:
       30:  969:    ret = sysdb_getgrgid(test_ctx,
       10:  970:                         test_ctx->sysdb,
       10:  971:                         test_ctx->domain,
        -:  972:                         _i, &res);
       10:  973:    if (ret) {
    #####:  974:        fail("sysdb_getgrgid failed for gid %d (%d: %s)",
        -:  975:             _i, ret, strerror(ret));
    #####:  976:        goto done;
        -:  977:    }
        -:  978:
       10:  979:    groupname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, 0);
        -:  980:
       10:  981:    e_groupname = talloc_asprintf(test_ctx, "testgroup%d", _i);
       10:  982:    if (e_groupname == NULL) {
    #####:  983:        fail("Cannot allocate memory");
    #####:  984:        goto done;
        -:  985:    }
        -:  986:
       10:  987:    fail_unless(strcmp(groupname, e_groupname) == 0,
        -:  988:                "Did not find the expected groupname (found %s expected %s)",
        -:  989:                groupname, e_groupname);
        -:  990:done:
       10:  991:    talloc_free(test_ctx);
        -:  992:}
        -:  993:END_TEST
        -:  994:
       10:  995:START_TEST (test_sysdb_getpwuid)
        -:  996:{
        -:  997:    struct sysdb_test_ctx *test_ctx;
        -:  998:    struct ldb_result *res;
        -:  999:    const char *e_username;
        -: 1000:    const char *username;
        -: 1001:    int ret;
        -: 1002:
        -: 1003:    /* Setup */
       10: 1004:    ret = setup_sysdb_tests(&test_ctx);
       10: 1005:    if (ret != EOK) {
    #####: 1006:        fail("Could not set up the test");
       10: 1007:        return;
        -: 1008:    }
        -: 1009:
       30: 1010:    ret = sysdb_getpwuid(test_ctx,
       10: 1011:                         test_ctx->sysdb,
       10: 1012:                         test_ctx->domain,
        -: 1013:                         _i, &res);
       10: 1014:    if (ret) {
    #####: 1015:        fail("sysdb_getpwuid failed for uid %d (%d: %s)",
        -: 1016:             _i, ret, strerror(ret));
    #####: 1017:        goto done;
        -: 1018:    }
        -: 1019:
       10: 1020:    fail_unless(res->count == 1, "Expected 1 user entry, found %d\n",
        -: 1021:                res->count);
        -: 1022:
       10: 1023:    username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, 0);
        -: 1024:
       10: 1025:    e_username = talloc_asprintf(test_ctx, "testuser%d", _i);
       10: 1026:    if (username == NULL) {
    #####: 1027:        fail("Cannot allocate memory");
    #####: 1028:        goto done;
        -: 1029:    }
        -: 1030:
       10: 1031:    fail_unless(strcmp(username, e_username) == 0,
        -: 1032:                "Did not find the expected username (found %s expected %s)",
        -: 1033:                username, e_username);
        -: 1034:done:
       10: 1035:    talloc_free(test_ctx);
        -: 1036:}
        -: 1037:END_TEST
        -: 1038:
        1: 1039:START_TEST (test_sysdb_enumgrent)
        -: 1040:{
        -: 1041:    struct sysdb_test_ctx *test_ctx;
        -: 1042:    struct ldb_result *res;
        -: 1043:    int ret;
        -: 1044:
        -: 1045:    /* Setup */
        1: 1046:    ret = setup_sysdb_tests(&test_ctx);
        1: 1047:    if (ret != EOK) {
    #####: 1048:        fail("Could not set up the test");
        1: 1049:        return;
        -: 1050:    }
        -: 1051:
        2: 1052:    ret = sysdb_enumgrent(test_ctx,
        1: 1053:                          test_ctx->sysdb,
        1: 1054:                          test_ctx->domain,
        -: 1055:                          &res);
        1: 1056:    fail_unless(ret == EOK,
        -: 1057:                "sysdb_enumgrent failed (%d: %s)",
        -: 1058:                ret, strerror(ret));
        -: 1059:
        -: 1060:    /* 10 groups + 10 users (we're MPG) */
        1: 1061:    fail_if(res->count != 20, "Expected 20 users, got %d", res->count);
        -: 1062:
        1: 1063:    talloc_free(test_ctx);
        -: 1064:}
        -: 1065:END_TEST
        -: 1066:
        1: 1067:START_TEST (test_sysdb_enumpwent)
        -: 1068:{
        -: 1069:    struct sysdb_test_ctx *test_ctx;
        -: 1070:    struct ldb_result *res;
        -: 1071:    int ret;
        -: 1072:
        -: 1073:    /* Setup */
        1: 1074:    ret = setup_sysdb_tests(&test_ctx);
        1: 1075:    if (ret != EOK) {
    #####: 1076:        fail("Could not set up the test");
        1: 1077:        return;
        -: 1078:    }
        -: 1079:
        2: 1080:    ret = sysdb_enumpwent(test_ctx,
        1: 1081:                          test_ctx->sysdb,
        1: 1082:                          test_ctx->domain,
        -: 1083:                          &res);
        1: 1084:    fail_unless(ret == EOK,
        -: 1085:                "sysdb_enumpwent failed (%d: %s)",
        -: 1086:                ret, strerror(ret));
        -: 1087:
        1: 1088:    fail_if(res->count != 10, "Expected 10 users, got %d", res->count);
        -: 1089:
        1: 1090:    talloc_free(test_ctx);
        -: 1091:}
        -: 1092:END_TEST
        -: 1093:
        -: 1094:
       10: 1095:START_TEST (test_sysdb_set_user_attr)
        -: 1096:{
        -: 1097:    struct sysdb_test_ctx *test_ctx;
        -: 1098:    struct test_data *data;
        -: 1099:    int ret;
        -: 1100:
        -: 1101:    /* Setup */
       10: 1102:    ret = setup_sysdb_tests(&test_ctx);
       10: 1103:    if (ret != EOK) {
    #####: 1104:        fail("Could not set up the test");
        -: 1105:        return;
        -: 1106:    }
        -: 1107:
       10: 1108:    data = talloc_zero(test_ctx, struct test_data);
       10: 1109:    data->ctx = test_ctx;
       10: 1110:    data->ev = test_ctx->ev;
       10: 1111:    data->username = talloc_asprintf(data, "testuser%d", _i);
        -: 1112:
       10: 1113:    data->attrs = sysdb_new_attrs(test_ctx);
       10: 1114:    if (ret != EOK) {
    #####: 1115:        fail("Could not create the changeset");
        -: 1116:        return;
        -: 1117:    }
        -: 1118:
       10: 1119:    ret = sysdb_attrs_add_string(data->attrs,
        -: 1120:                                 SYSDB_SHELL,
        -: 1121:                                 "/bin/ksh");
       10: 1122:    if (ret != EOK) {
    #####: 1123:        fail("Could not create the changeset");
        -: 1124:        return;
        -: 1125:    }
        -: 1126:
       10: 1127:    ret = test_set_user_attr(data);
        -: 1128:
       10: 1129:    fail_if(ret != EOK, "Could not modify user %s", data->username);
        -: 1130:
       10: 1131:    talloc_free(test_ctx);
        -: 1132:}
        -: 1133:END_TEST
        -: 1134:
       20: 1135:START_TEST (test_sysdb_get_user_attr)
        -: 1136:{
        -: 1137:    struct sysdb_test_ctx *test_ctx;
       20: 1138:    const char *attrs[] = { SYSDB_SHELL, NULL };
        -: 1139:    struct ldb_result *res;
        -: 1140:    const char *attrval;
        -: 1141:    char *username;
        -: 1142:    int ret;
        -: 1143:
        -: 1144:    /* Setup */
       20: 1145:    ret = setup_sysdb_tests(&test_ctx);
       20: 1146:    if (ret != EOK) {
    #####: 1147:        fail("Could not set up the test");
       20: 1148:        return;
        -: 1149:    }
        -: 1150:
       20: 1151:    username = talloc_asprintf(test_ctx, "testuser%d", _i);
        -: 1152:
       20: 1153:    ret = sysdb_get_user_attr(test_ctx, test_ctx->sysdb,
       20: 1154:                              test_ctx->domain, username, attrs, &res);
       20: 1155:    if (ret) {
    #####: 1156:        fail("Could not get attributes for user %s", username);
    #####: 1157:        goto done;
        -: 1158:    }
        -: 1159:
       20: 1160:    fail_if(res->count != 1,
        -: 1161:            "Invalid number of entries, expected 1, got %d", res->count);
        -: 1162:
       20: 1163:    attrval = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, 0);
       20: 1164:    fail_if(strcmp(attrval, "/bin/ksh"),
        -: 1165:            "Got bad attribute value for user %s", username);
        -: 1166:done:
       20: 1167:    talloc_free(test_ctx);
        -: 1168:}
        -: 1169:END_TEST
        -: 1170:
       10: 1171:START_TEST (test_sysdb_add_group_member)
        -: 1172:{
        -: 1173:    struct sysdb_test_ctx *test_ctx;
        -: 1174:    struct test_data *data;
        -: 1175:    int ret;
        -: 1176:
        -: 1177:    /* Setup */
       10: 1178:    ret = setup_sysdb_tests(&test_ctx);
       10: 1179:    if (ret != EOK) {
    #####: 1180:        fail("Could not set up the test");
       10: 1181:        return;
        -: 1182:    }
        -: 1183:
       10: 1184:    data = talloc_zero(test_ctx, struct test_data);
       10: 1185:    data->ctx = test_ctx;
       10: 1186:    data->ev = test_ctx->ev;
       10: 1187:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
       10: 1188:    data->uid = _i - 1000; /* the UID of user to add */
        -: 1189:
       10: 1190:    ret = test_add_group_member(data);
        -: 1191:
       10: 1192:    fail_if(ret != EOK, "Could not modify group %s", data->groupname);
       10: 1193:    talloc_free(test_ctx);
        -: 1194:}
        -: 1195:END_TEST
        -: 1196:
       10: 1197:START_TEST (test_sysdb_remove_group_member)
        -: 1198:{
        -: 1199:    struct sysdb_test_ctx *test_ctx;
        -: 1200:    struct test_data *data;
        -: 1201:    int ret;
        -: 1202:
        -: 1203:    /* Setup */
       10: 1204:    ret = setup_sysdb_tests(&test_ctx);
       10: 1205:    if (ret != EOK) {
    #####: 1206:        fail("Could not set up the test");
       10: 1207:        return;
        -: 1208:    }
        -: 1209:
       10: 1210:    data = talloc_zero(test_ctx, struct test_data);
       10: 1211:    data->ctx = test_ctx;
       10: 1212:    data->ev = test_ctx->ev;
       10: 1213:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
       10: 1214:    data->uid = _i - 1000; /* the UID of user to add */
        -: 1215:
       10: 1216:    ret = test_remove_group_member(data);
        -: 1217:
       10: 1218:    talloc_free(test_ctx);
        -: 1219:}
        -: 1220:END_TEST
        -: 1221:
        1: 1222:START_TEST (test_sysdb_remove_nonexistent_user)
        -: 1223:{
        -: 1224:    struct sysdb_test_ctx *test_ctx;
        -: 1225:    struct test_data *data;
        -: 1226:    int ret;
        -: 1227:
        -: 1228:    /* Setup */
        1: 1229:    ret = setup_sysdb_tests(&test_ctx);
        1: 1230:    if (ret != EOK) {
    #####: 1231:        fail("Could not set up the test");
        1: 1232:        return;
        -: 1233:    }
        -: 1234:
        1: 1235:    data = talloc_zero(test_ctx, struct test_data);
        1: 1236:    data->ctx = test_ctx;
        1: 1237:    data->ev = test_ctx->ev;
        1: 1238:    data->uid = 12345;
        -: 1239:
        1: 1240:    ret = test_remove_nonexistent_user(data);
        -: 1241:
        1: 1242:    fail_if(ret != ENOENT, "Unexpected return code %d, expected ENOENT", ret);
        1: 1243:    talloc_free(test_ctx);
        -: 1244:}
        -: 1245:END_TEST
        -: 1246:
        1: 1247:START_TEST (test_sysdb_remove_nonexistent_group)
        -: 1248:{
        -: 1249:    struct sysdb_test_ctx *test_ctx;
        -: 1250:    struct test_data *data;
        -: 1251:    int ret;
        -: 1252:
        -: 1253:    /* Setup */
        1: 1254:    ret = setup_sysdb_tests(&test_ctx);
        1: 1255:    if (ret != EOK) {
    #####: 1256:        fail("Could not set up the test");
        1: 1257:        return;
        -: 1258:    }
        -: 1259:
        1: 1260:    data = talloc_zero(test_ctx, struct test_data);
        1: 1261:    data->ctx = test_ctx;
        1: 1262:    data->ev = test_ctx->ev;
        1: 1263:    data->uid = 12345;
        -: 1264:
        1: 1265:    ret = test_remove_nonexistent_group(data);
        -: 1266:
        1: 1267:    fail_if(ret != ENOENT, "Unexpected return code %d, expected ENOENT", ret);
        1: 1268:    talloc_free(test_ctx);
        -: 1269:}
        -: 1270:END_TEST
        -: 1271:
       10: 1272:START_TEST (test_sysdb_store_custom)
        -: 1273:{
        -: 1274:    struct sysdb_test_ctx *test_ctx;
        -: 1275:    struct test_data *data;
        -: 1276:    int ret;
        -: 1277:
        -: 1278:    /* Setup */
       10: 1279:    ret = setup_sysdb_tests(&test_ctx);
       10: 1280:    if (ret != EOK) {
    #####: 1281:        fail("Could not set up the test");
        -: 1282:        return;
        -: 1283:    }
        -: 1284:
       10: 1285:    data = talloc_zero(test_ctx, struct test_data);
       10: 1286:    data->ctx = test_ctx;
       10: 1287:    data->ev = test_ctx->ev;
       10: 1288:    data->uid = _i;
       10: 1289:    data->attrs = sysdb_new_attrs(test_ctx);
       10: 1290:    if (ret != EOK) {
    #####: 1291:        fail("Could not create attribute list");
        -: 1292:        return;
        -: 1293:    }
        -: 1294:
       10: 1295:    ret = sysdb_attrs_add_string(data->attrs,
        -: 1296:                                 TEST_ATTR_NAME,
        -: 1297:                                 TEST_ATTR_VALUE);
       10: 1298:    if (ret != EOK) {
    #####: 1299:        fail("Could not add attribute");
        -: 1300:        return;
        -: 1301:    }
        -: 1302:
       10: 1303:    ret = test_store_custom(data);
        -: 1304:
       10: 1305:    fail_if(ret != EOK, "Could not add custom object");
       10: 1306:    talloc_free(test_ctx);
        -: 1307:}
        -: 1308:END_TEST
        -: 1309:
        1: 1310:START_TEST (test_sysdb_search_custom_by_name)
        -: 1311:{
        -: 1312:    struct sysdb_test_ctx *test_ctx;
        -: 1313:    struct test_data *data;
        -: 1314:    int ret;
        -: 1315:    char *object_name;
        -: 1316:
        -: 1317:    /* Setup */
        1: 1318:    ret = setup_sysdb_tests(&test_ctx);
        1: 1319:    if (ret != EOK) {
    #####: 1320:        fail("Could not set up the test");
        1: 1321:        return;
        -: 1322:    }
        -: 1323:
        1: 1324:    data = talloc_zero(test_ctx, struct test_data);
        1: 1325:    fail_unless(data != NULL, "talloc_zero failed");
        1: 1326:    data->ctx = test_ctx;
        1: 1327:    data->ev = test_ctx->ev;
        1: 1328:    data->attrlist = talloc_array(test_ctx, const char *, 2);
        1: 1329:    fail_unless(data->attrlist != NULL, "talloc_array failed");
        1: 1330:    data->attrlist[0] = TEST_ATTR_NAME;
        1: 1331:    data->attrlist[1] = NULL;
        -: 1332:
        1: 1333:    object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, 29010);
        1: 1334:    fail_unless(object_name != NULL, "talloc_asprintf failed");
        -: 1335:
        2: 1336:    ret = sysdb_search_custom_by_name(data, data->ctx->sysdb,
        1: 1337:                                      data->ctx->domain,
        -: 1338:                                      object_name,
        -: 1339:                                      CUSTOM_TEST_CONTAINER,
        -: 1340:                                      data->attrlist,
        -: 1341:                                      &data->msgs_count,
        -: 1342:                                      &data->msgs);
        -: 1343:
        1: 1344:    fail_if(ret != EOK, "Could not search custom object");
        -: 1345:
        1: 1346:    fail_unless(data->msgs_count == 1,
        -: 1347:                "Wrong number of objects, exptected [1] got [%d]",
        -: 1348:                data->msgs_count);
        1: 1349:    fail_unless(data->msgs[0]->num_elements == 1,
        -: 1350:                "Wrong number of results, expected [1] got [%d]",
        -: 1351:                data->msgs[0]->num_elements);
        1: 1352:    fail_unless(strcmp(data->msgs[0]->elements[0].name, TEST_ATTR_NAME) == 0,
        -: 1353:                "Wrong attribute name");
        1: 1354:    fail_unless(data->msgs[0]->elements[0].num_values == 1,
        -: 1355:                "Wrong number of attribute values");
        1: 1356:    fail_unless(strncmp((const char *)data->msgs[0]->elements[0].values[0].data,
        -: 1357:                        TEST_ATTR_VALUE,
        -: 1358:                        data->msgs[0]->elements[0].values[0].length) == 0,
        -: 1359:                "Wrong attribute value");
        -: 1360:
        1: 1361:    talloc_free(test_ctx);
        -: 1362:}
        -: 1363:END_TEST
        -: 1364:
        1: 1365:START_TEST (test_sysdb_update_custom)
        -: 1366:{
        -: 1367:    struct sysdb_test_ctx *test_ctx;
        -: 1368:    struct test_data *data;
        -: 1369:    int ret;
        -: 1370:
        -: 1371:    /* Setup */
        1: 1372:    ret = setup_sysdb_tests(&test_ctx);
        1: 1373:    if (ret != EOK) {
    #####: 1374:        fail("Could not set up the test");
        -: 1375:        return;
        -: 1376:    }
        -: 1377:
        1: 1378:    data = talloc_zero(test_ctx, struct test_data);
        1: 1379:    data->ctx = test_ctx;
        1: 1380:    data->ev = test_ctx->ev;
        1: 1381:    data->uid = 29010;
        1: 1382:    data->attrs = sysdb_new_attrs(test_ctx);
        1: 1383:    if (ret != EOK) {
    #####: 1384:        fail("Could not create attribute list");
        -: 1385:        return;
        -: 1386:    }
        -: 1387:
        1: 1388:    ret = sysdb_attrs_add_string(data->attrs,
        -: 1389:                                 TEST_ATTR_NAME,
        -: 1390:                                 TEST_ATTR_UPDATE_VALUE);
        1: 1391:    if (ret != EOK) {
    #####: 1392:        fail("Could not add attribute");
        -: 1393:        return;
        -: 1394:    }
        -: 1395:
        1: 1396:    ret = sysdb_attrs_add_string(data->attrs,
        -: 1397:                                 TEST_ATTR_ADD_NAME,
        -: 1398:                                 TEST_ATTR_ADD_VALUE);
        1: 1399:    if (ret != EOK) {
    #####: 1400:        fail("Could not add attribute");
        -: 1401:        return;
        -: 1402:    }
        -: 1403:
        1: 1404:    ret = test_store_custom(data);
        -: 1405:
        1: 1406:    fail_if(ret != EOK, "Could not add custom object");
        1: 1407:    talloc_free(test_ctx);
        -: 1408:}
        -: 1409:END_TEST
        -: 1410:
        1: 1411:START_TEST (test_sysdb_search_custom_update)
        -: 1412:{
        -: 1413:    struct sysdb_test_ctx *test_ctx;
        -: 1414:    struct test_data *data;
        -: 1415:    int ret;
        -: 1416:    char *object_name;
        -: 1417:    struct ldb_message_element *el;
        -: 1418:
        -: 1419:    /* Setup */
        1: 1420:    ret = setup_sysdb_tests(&test_ctx);
        1: 1421:    if (ret != EOK) {
    #####: 1422:        fail("Could not set up the test");
        1: 1423:        return;
        -: 1424:    }
        -: 1425:
        1: 1426:    data = talloc_zero(test_ctx, struct test_data);
        1: 1427:    fail_unless(data != NULL, "talloc_zero failed");
        1: 1428:    data->ctx = test_ctx;
        1: 1429:    data->ev = test_ctx->ev;
        1: 1430:    data->attrlist = talloc_array(test_ctx, const char *, 3);
        1: 1431:    fail_unless(data->attrlist != NULL, "talloc_array failed");
        1: 1432:    data->attrlist[0] = TEST_ATTR_NAME;
        1: 1433:    data->attrlist[1] = TEST_ATTR_ADD_NAME;
        1: 1434:    data->attrlist[2] = NULL;
        -: 1435:
        1: 1436:    object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, 29010);
        1: 1437:    fail_unless(object_name != NULL, "talloc_asprintf failed");
        -: 1438:
        2: 1439:    ret = sysdb_search_custom_by_name(data, data->ctx->sysdb,
        1: 1440:                                      data->ctx->domain,
        -: 1441:                                      object_name,
        -: 1442:                                      CUSTOM_TEST_CONTAINER,
        -: 1443:                                      data->attrlist,
        -: 1444:                                      &data->msgs_count,
        -: 1445:                                      &data->msgs);
        -: 1446:
        1: 1447:    fail_if(ret != EOK, "Could not search custom object");
        -: 1448:
        1: 1449:    fail_unless(data->msgs_count == 1,
        -: 1450:                "Wrong number of objects, exptected [1] got [%d]",
        -: 1451:                data->msgs_count);
        1: 1452:    fail_unless(data->msgs[0]->num_elements == 2,
        -: 1453:                "Wrong number of results, expected [2] got [%d]",
        -: 1454:                data->msgs[0]->num_elements);
        -: 1455:
        1: 1456:    el = ldb_msg_find_element(data->msgs[0], TEST_ATTR_NAME);
        1: 1457:    fail_unless(el != NULL, "Attribute [%s] not found", TEST_ATTR_NAME);
        1: 1458:    fail_unless(el->num_values == 1, "Wrong number ([%d] instead of 1) "
        -: 1459:                "of attribute values for [%s]", el->num_values,
        -: 1460:                TEST_ATTR_NAME);
        1: 1461:    fail_unless(strncmp((const char *) el->values[0].data,
        -: 1462:                TEST_ATTR_UPDATE_VALUE,
        -: 1463:                el->values[0].length) == 0,
        -: 1464:                "Wrong attribute value");
        -: 1465:
        1: 1466:    el = ldb_msg_find_element(data->msgs[0], TEST_ATTR_ADD_NAME);
        1: 1467:    fail_unless(el != NULL, "Attribute [%s] not found", TEST_ATTR_ADD_NAME);
        1: 1468:    fail_unless(el->num_values == 1, "Wrong number ([%d] instead of 1) "
        -: 1469:                "of attribute values for [%s]", el->num_values,
        -: 1470:                TEST_ATTR_ADD_NAME);
        1: 1471:    fail_unless(strncmp((const char *) el->values[0].data,
        -: 1472:                TEST_ATTR_ADD_VALUE,
        -: 1473:                el->values[0].length) == 0,
        -: 1474:                "Wrong attribute value");
        -: 1475:
        -: 1476:
        1: 1477:    talloc_free(test_ctx);
        -: 1478:}
        -: 1479:END_TEST
        -: 1480:
        1: 1481:START_TEST (test_sysdb_search_custom)
        -: 1482:{
        -: 1483:    struct sysdb_test_ctx *test_ctx;
        -: 1484:    struct test_data *data;
        -: 1485:    int ret;
        1: 1486:    const char *filter = "(distinguishedName=*)";
        -: 1487:
        -: 1488:    /* Setup */
        1: 1489:    ret = setup_sysdb_tests(&test_ctx);
        1: 1490:    if (ret != EOK) {
    #####: 1491:        fail("Could not set up the test");
        1: 1492:        return;
        -: 1493:    }
        -: 1494:
        1: 1495:    data = talloc_zero(test_ctx, struct test_data);
        1: 1496:    fail_unless(data != NULL, "talloc_zero failed");
        1: 1497:    data->ctx = test_ctx;
        1: 1498:    data->ev = test_ctx->ev;
        1: 1499:    data->attrlist = talloc_array(test_ctx, const char *, 3);
        1: 1500:    fail_unless(data->attrlist != NULL, "talloc_array failed");
        1: 1501:    data->attrlist[0] = TEST_ATTR_NAME;
        1: 1502:    data->attrlist[1] = TEST_ATTR_ADD_NAME;
        1: 1503:    data->attrlist[2] = NULL;
        -: 1504:
        2: 1505:    ret = sysdb_search_custom(data, data->ctx->sysdb,
        1: 1506:                              data->ctx->domain, filter,
        -: 1507:                              CUSTOM_TEST_CONTAINER,
        -: 1508:                              data->attrlist,
        -: 1509:                              &data->msgs_count,
        -: 1510:                              &data->msgs);
        -: 1511:
        1: 1512:    fail_if(ret != EOK, "Could not search custom object");
        -: 1513:
        1: 1514:    fail_unless(data->msgs_count == 10,
        -: 1515:                "Wrong number of objects, exptected [10] got [%d]",
        -: 1516:                data->msgs_count);
        -: 1517:
        1: 1518:    talloc_free(test_ctx);
        -: 1519:}
        -: 1520:END_TEST
        -: 1521:
        1: 1522:START_TEST (test_sysdb_delete_custom)
        -: 1523:{
        -: 1524:    struct sysdb_test_ctx *test_ctx;
        -: 1525:    struct test_data *data;
        -: 1526:    int ret;
        -: 1527:
        -: 1528:    /* Setup */
        1: 1529:    ret = setup_sysdb_tests(&test_ctx);
        1: 1530:    if (ret != EOK) {
    #####: 1531:        fail("Could not set up the test");
        1: 1532:        return;
        -: 1533:    }
        -: 1534:
        1: 1535:    data = talloc_zero(test_ctx, struct test_data);
        1: 1536:    data->ctx = test_ctx;
        1: 1537:    data->ev = test_ctx->ev;
        -: 1538:
        1: 1539:    ret = test_delete_custom(data);
        -: 1540:
        1: 1541:    fail_if(ret != EOK, "Could not delete custom object");
        1: 1542:    talloc_free(test_ctx);
        -: 1543:}
        -: 1544:END_TEST
        -: 1545:
        1: 1546:START_TEST (test_sysdb_cache_password)
        -: 1547:{
        -: 1548:    struct sysdb_test_ctx *test_ctx;
        -: 1549:    struct test_data *data;
        -: 1550:    int ret;
        -: 1551:
        -: 1552:    /* Setup */
        1: 1553:    ret = setup_sysdb_tests(&test_ctx);
        1: 1554:    fail_unless(ret == EOK, "Could not set up the test");
        -: 1555:
        1: 1556:    data = talloc_zero(test_ctx, struct test_data);
        1: 1557:    data->ctx = test_ctx;
        1: 1558:    data->ev = test_ctx->ev;
        1: 1559:    data->username = talloc_asprintf(data, "testuser%d", _i);
        -: 1560:
        1: 1561:    ret = sysdb_cache_password(test_ctx->sysdb, test_ctx->domain,
        -: 1562:                               data->username, data->username);
        -: 1563:
        1: 1564:    fail_unless(ret == EOK, "sysdb_cache_password request failed [%d].", ret);
        -: 1565:
        1: 1566:    talloc_free(test_ctx);
        -: 1567:}
        1: 1568:END_TEST
        -: 1569:
        3: 1570:static void cached_authentication_without_expiration(const char *username,
        -: 1571:                                                     const char *password,
        -: 1572:                                                     int expected_result)
        -: 1573:{
        -: 1574:    struct sysdb_test_ctx *test_ctx;
        -: 1575:    struct test_data *data;
        -: 1576:    int ret;
        3: 1577:    time_t expire_date = -1;
        3: 1578:    time_t delayed_until = -1;
        -: 1579:    const char *val[2];
        3: 1580:    val[1] = NULL;
        -: 1581:
        -: 1582:    /* Setup */
        3: 1583:    ret = setup_sysdb_tests(&test_ctx);
        3: 1584:    fail_unless(ret == EOK, "Could not set up the test");
        -: 1585:
        3: 1586:    data = talloc_zero(test_ctx, struct test_data);
        3: 1587:    data->ctx = test_ctx;
        3: 1588:    data->ev = test_ctx->ev;
        3: 1589:    data->username = username;
        -: 1590:
        3: 1591:    val[0] = "0";
        3: 1592:    ret = confdb_add_param(test_ctx->confdb, true, CONFDB_PAM_CONF_ENTRY,
        -: 1593:                           CONFDB_PAM_CRED_TIMEOUT, val);
        3: 1594:    if (ret != EOK) {
    #####: 1595:        fail("Could not initialize provider");
    #####: 1596:        talloc_free(test_ctx);
        3: 1597:        return;
        -: 1598:    }
        -: 1599:
        6: 1600:    ret = sysdb_cache_auth(test_ctx->sysdb,
        3: 1601:                           test_ctx->domain, data->username,
        3: 1602:                           password, test_ctx->confdb, false,
        -: 1603:                           &expire_date, &delayed_until);
        -: 1604:
        3: 1605:    fail_unless(ret == expected_result, "sysdb_cache_auth request does not "
        -: 1606:                                        "return expected result [%d].",
        -: 1607:                                        expected_result);
        -: 1608:
        3: 1609:    fail_unless(expire_date == 0, "Wrong expire date, expected [%d], got [%d]",
        -: 1610:                                  0, expire_date);
        -: 1611:
        3: 1612:    fail_unless(delayed_until == -1, "Wrong delay, expected [%d], got [%d]",
        -: 1613:                                  -1, delayed_until);
        -: 1614:
        3: 1615:    talloc_free(test_ctx);
        -: 1616:}
        -: 1617:
        3: 1618:static void cached_authentication_with_expiration(const char *username,
        -: 1619:                                                  const char *password,
        -: 1620:                                                  int expected_result)
        -: 1621:{
        -: 1622:    struct sysdb_test_ctx *test_ctx;
        -: 1623:    struct test_data *data;
        -: 1624:    int ret;
        3: 1625:    time_t expire_date = -1;
        -: 1626:    const char *val[2];
        3: 1627:    val[1] = NULL;
        -: 1628:    time_t now;
        -: 1629:    time_t expected_expire_date;
        3: 1630:    time_t delayed_until = -1;
        -: 1631:
        -: 1632:    /* Setup */
        3: 1633:    ret = setup_sysdb_tests(&test_ctx);
        3: 1634:    fail_unless(ret == EOK, "Could not set up the test");
        -: 1635:
        3: 1636:    data = talloc_zero(test_ctx, struct test_data);
        3: 1637:    data->ctx = test_ctx;
        3: 1638:    data->ev = test_ctx->ev;
        3: 1639:    data->username = username;
        -: 1640:
        3: 1641:    val[0] = "1";
        3: 1642:    ret = confdb_add_param(test_ctx->confdb, true, CONFDB_PAM_CONF_ENTRY,
        -: 1643:                           CONFDB_PAM_CRED_TIMEOUT, val);
        3: 1644:    if (ret != EOK) {
    #####: 1645:        fail("Could not initialize provider");
    #####: 1646:        talloc_free(test_ctx);
        3: 1647:        return;
        -: 1648:    }
        -: 1649:
        3: 1650:    now = time(NULL);
        3: 1651:    expected_expire_date = now + (24 * 60 * 60);
        3: 1652:    DEBUG(9, ("Setting SYSDB_LAST_ONLINE_AUTH to [%lld].\n", (long long) now));
        -: 1653:
        3: 1654:    data->attrs = sysdb_new_attrs(data);
        3: 1655:    ret = sysdb_attrs_add_time_t(data->attrs, SYSDB_LAST_ONLINE_AUTH, now);
        -: 1656:
        3: 1657:    ret = sysdb_set_user_attr(data->ctx->sysdb, data->ctx->domain,
        -: 1658:                              data->username, data->attrs, SYSDB_MOD_REP);
        3: 1659:    fail_unless(ret == EOK, "Could not modify user %s", data->username);
        -: 1660:
        6: 1661:    ret = sysdb_cache_auth(test_ctx->sysdb,
        3: 1662:                           data->ctx->domain, data->username,
        3: 1663:                           password, test_ctx->confdb, false,
        -: 1664:                           &expire_date, &delayed_until);
        -: 1665:
        3: 1666:    fail_unless(ret == expected_result,
        -: 1667:                "sysdb_cache_auth request does not return expected "
        -: 1668:                "result [%d], got [%d].", expected_result, ret);
        -: 1669:
        3: 1670:    fail_unless(expire_date == expected_expire_date,
        -: 1671:                "Wrong expire date, expected [%d], got [%d]",
        -: 1672:                expected_expire_date, expire_date);
        -: 1673:
        3: 1674:    fail_unless(delayed_until == -1, "Wrong delay, expected [%d], got [%d]",
        -: 1675:                                  -1, delayed_until);
        -: 1676:
        3: 1677:    talloc_free(test_ctx);
        -: 1678:}
        -: 1679:
        1: 1680:START_TEST (test_sysdb_cached_authentication_missing_password)
        -: 1681:{
        -: 1682:    TALLOC_CTX *tmp_ctx;
        -: 1683:    char *username;
        -: 1684:
        1: 1685:    tmp_ctx = talloc_new(NULL);
        1: 1686:    fail_unless(tmp_ctx != NULL, "talloc_new failed.");
        -: 1687:
        1: 1688:    username = talloc_asprintf(tmp_ctx, "testuser%d", _i);
        1: 1689:    fail_unless(username != NULL, "talloc_asprintf failed.");
        -: 1690:
        1: 1691:    cached_authentication_without_expiration(username, "abc", ENOENT);
        1: 1692:    cached_authentication_with_expiration(username, "abc", ENOENT);
        -: 1693:
        1: 1694:    talloc_free(tmp_ctx);
        -: 1695:
        -: 1696:}
        1: 1697:END_TEST
        -: 1698:
        1: 1699:START_TEST (test_sysdb_cached_authentication_wrong_password)
        -: 1700:{
        -: 1701:    TALLOC_CTX *tmp_ctx;
        -: 1702:    char *username;
        -: 1703:
        1: 1704:    tmp_ctx = talloc_new(NULL);
        1: 1705:    fail_unless(tmp_ctx != NULL, "talloc_new failed.");
        -: 1706:
        1: 1707:    username = talloc_asprintf(tmp_ctx, "testuser%d", _i);
        1: 1708:    fail_unless(username != NULL, "talloc_asprintf failed.");
        -: 1709:
        1: 1710:    cached_authentication_without_expiration(username, "abc", EINVAL);
        1: 1711:    cached_authentication_with_expiration(username, "abc", EINVAL);
        -: 1712:
        1: 1713:    talloc_free(tmp_ctx);
        -: 1714:
        -: 1715:}
        1: 1716:END_TEST
        -: 1717:
        1: 1718:START_TEST (test_sysdb_cached_authentication)
        -: 1719:{
        -: 1720:    TALLOC_CTX *tmp_ctx;
        -: 1721:    char *username;
        -: 1722:
        1: 1723:    tmp_ctx = talloc_new(NULL);
        1: 1724:    fail_unless(tmp_ctx != NULL, "talloc_new failed.");
        -: 1725:
        1: 1726:    username = talloc_asprintf(tmp_ctx, "testuser%d", _i);
        1: 1727:    fail_unless(username != NULL, "talloc_asprintf failed.");
        -: 1728:
        1: 1729:    cached_authentication_without_expiration(username, username, EOK);
        1: 1730:    cached_authentication_with_expiration(username, username, EOK);
        -: 1731:
        1: 1732:    talloc_free(tmp_ctx);
        -: 1733:
        -: 1734:}
        1: 1735:END_TEST
        -: 1736:
        9: 1737:START_TEST (test_sysdb_prepare_asq_test_user)
        -: 1738:{
        -: 1739:    struct sysdb_test_ctx *test_ctx;
        -: 1740:    struct test_data *data;
        -: 1741:    int ret;
        -: 1742:
        -: 1743:    /* Setup */
        9: 1744:    ret = setup_sysdb_tests(&test_ctx);
        9: 1745:    if (ret != EOK) {
    #####: 1746:        fail("Could not set up the test");
        9: 1747:        return;
        -: 1748:    }
        -: 1749:
        9: 1750:    data = talloc_zero(test_ctx, struct test_data);
        9: 1751:    data->ctx = test_ctx;
        9: 1752:    data->ev = test_ctx->ev;
        9: 1753:    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
        9: 1754:    data->uid = ASQ_TEST_USER_UID;
        -: 1755:
        9: 1756:    ret = test_add_group_member(data);
        -: 1757:
        9: 1758:    fail_if(ret != EOK, "Could not modify group %s", data->groupname);
        9: 1759:    talloc_free(test_ctx);
        -: 1760:}
        -: 1761:END_TEST
        -: 1762:
        1: 1763:START_TEST (test_sysdb_asq_search)
        -: 1764:{
        -: 1765:    struct sysdb_test_ctx *test_ctx;
        -: 1766:    struct test_data *data;
        -: 1767:    struct ldb_dn *user_dn;
        -: 1768:    int ret;
        -: 1769:    size_t msgs_count;
        -: 1770:    struct ldb_message **msgs;
        -: 1771:    int i;
        -: 1772:    char *gid_str;
        -: 1773:
        -: 1774:    /* Setup */
        1: 1775:    ret = setup_sysdb_tests(&test_ctx);
        1: 1776:    if (ret != EOK) {
    #####: 1777:        fail("Could not set up the test");
        1: 1778:        return;
        -: 1779:    }
        -: 1780:
        1: 1781:    data = talloc_zero(test_ctx, struct test_data);
        1: 1782:    data->ctx = test_ctx;
        1: 1783:    data->ev = test_ctx->ev;
        1: 1784:    data->attrlist = talloc_array(data, const char *, 2);
        1: 1785:    fail_unless(data->attrlist != NULL, "talloc_array failed");
        -: 1786:
        1: 1787:    data->attrlist[0] = "gidNumber";
        1: 1788:    data->attrlist[1] = NULL;
        -: 1789:
        1: 1790:    user_dn = sysdb_user_dn(data->ctx->sysdb, data,
        1: 1791:                            data->ctx->domain, ASQ_TEST_USER);
        1: 1792:    fail_unless(user_dn != NULL, "sysdb_user_dn failed");
        -: 1793:
        1: 1794:    ret = sysdb_asq_search(data, test_ctx->sysdb,
        -: 1795:                           user_dn, NULL, "memberof",
        -: 1796:                           data->attrlist, &msgs_count, &msgs);
        -: 1797:
        1: 1798:    fail_if(ret != EOK, "Failed to send ASQ search request.\n");
        -: 1799:
        1: 1800:    fail_unless(msgs_count == 10, "wrong number of results, "
        -: 1801:                                  "found [%d] expected [10]", msgs_count);
        -: 1802:
       11: 1803:    for (i = 0; i < msgs_count; i++) {
       10: 1804:        fail_unless(msgs[i]->num_elements == 1, "wrong number of elements, "
        -: 1805:                                     "found [%d] expected [1]",
        -: 1806:                                     msgs[i]->num_elements);
        -: 1807:
       10: 1808:        fail_unless(msgs[i]->elements[0].num_values == 1,
        -: 1809:                    "wrong number of values, found [%d] expected [1]",
        -: 1810:                    msgs[i]->elements[0].num_values);
        -: 1811:
       10: 1812:        gid_str = talloc_asprintf(data, "%d", 28010 + i);
       10: 1813:        fail_unless(gid_str != NULL, "talloc_asprintf failed.");
       10: 1814:        fail_unless(strncmp(gid_str,
        -: 1815:                            (const char *) msgs[i]->elements[0].values[0].data,
        -: 1816:                            msgs[i]->elements[0].values[0].length)  == 0,
        -: 1817:                            "wrong value, found [%.*s] expected [%s]",
        -: 1818:                            msgs[i]->elements[0].values[0].length,
        -: 1819:                            msgs[i]->elements[0].values[0].data, gid_str);
        -: 1820:    }
        -: 1821:
        1: 1822:    talloc_free(test_ctx);
        -: 1823:}
        -: 1824:END_TEST
        -: 1825:
        1: 1826:START_TEST (test_sysdb_search_all_users)
        -: 1827:{
        -: 1828:    struct sysdb_test_ctx *test_ctx;
        -: 1829:    struct test_data *data;
        -: 1830:    int ret;
        -: 1831:    int i;
        -: 1832:    char *uid_str;
        -: 1833:
        -: 1834:    /* Setup */
        1: 1835:    ret = setup_sysdb_tests(&test_ctx);
        1: 1836:    if (ret != EOK) {
    #####: 1837:        fail("Could not set up the test");
        1: 1838:        return;
        -: 1839:    }
        -: 1840:
        1: 1841:    data = talloc_zero(test_ctx, struct test_data);
        1: 1842:    data->ctx = test_ctx;
        1: 1843:    data->ev = test_ctx->ev;
        1: 1844:    data->attrlist = talloc_array(data, const char *, 2);
        1: 1845:    fail_unless(data->attrlist != NULL, "talloc_array failed");
        -: 1846:
        1: 1847:    data->attrlist[0] = "uidNumber";
        1: 1848:    data->attrlist[1] = NULL;
        -: 1849:
        1: 1850:    ret = test_search_all_users(data);
        -: 1851:
        1: 1852:    fail_if(ret != EOK, "Search failed");
        -: 1853:
        1: 1854:    fail_unless(data->msgs_count == 10,
        -: 1855:                "wrong number of results, found [%d] expected [10]",
        -: 1856:                data->msgs_count);
        -: 1857:
       11: 1858:    for (i = 0; i < data->msgs_count; i++) {
       10: 1859:        fail_unless(data->msgs[i]->num_elements == 1,
        -: 1860:                    "wrong number of elements, found [%d] expected [1]",
        -: 1861:                    data->msgs[i]->num_elements);
        -: 1862:
       10: 1863:        fail_unless(data->msgs[i]->elements[0].num_values == 1,
        -: 1864:                    "wrong number of values, found [%d] expected [1]",
        -: 1865:                    data->msgs[i]->elements[0].num_values);
        -: 1866:
       10: 1867:        uid_str = talloc_asprintf(data, "%d", 27010 + i);
       10: 1868:        fail_unless(uid_str != NULL, "talloc_asprintf failed.");
       10: 1869:        fail_unless(strncmp(uid_str,
        -: 1870:                            (char *) data->msgs[i]->elements[0].values[0].data,
        -: 1871:                            data->msgs[i]->elements[0].values[0].length)  == 0,
        -: 1872:                            "wrong value, found [%.*s] expected [%s]",
        -: 1873:                            data->msgs[i]->elements[0].values[0].length,
        -: 1874:                            data->msgs[i]->elements[0].values[0].data, uid_str);
        -: 1875:    }
        -: 1876:
        1: 1877:    talloc_free(test_ctx);
        -: 1878:}
        -: 1879:END_TEST
        -: 1880:
        1: 1881:START_TEST (test_sysdb_delete_recursive)
        -: 1882:{
        -: 1883:    struct sysdb_test_ctx *test_ctx;
        -: 1884:    struct test_data *data;
        -: 1885:    int ret;
        -: 1886:
        -: 1887:    /* Setup */
        1: 1888:    ret = setup_sysdb_tests(&test_ctx);
        1: 1889:    if (ret != EOK) {
    #####: 1890:        fail("Could not set up the test");
        1: 1891:        return;
        -: 1892:    }
        -: 1893:
        1: 1894:    data = talloc_zero(test_ctx, struct test_data);
        1: 1895:    data->ctx = test_ctx;
        1: 1896:    data->ev = test_ctx->ev;
        -: 1897:
        1: 1898:    ret = test_delete_recursive(data);
        -: 1899:
        1: 1900:    fail_if(ret != EOK, "Recursive delete failed");
        1: 1901:    talloc_free(test_ctx);
        -: 1902:}
        -: 1903:END_TEST
        -: 1904:
        1: 1905:START_TEST (test_sysdb_attrs_replace_name)
        -: 1906:{
        -: 1907:    struct sysdb_attrs *attrs;
        -: 1908:    struct ldb_message_element *el;
        -: 1909:    int ret;
        -: 1910:
        1: 1911:    attrs = sysdb_new_attrs(NULL);
        1: 1912:    fail_unless(attrs != NULL, "sysdb_new_attrs failed");
        -: 1913:
        1: 1914:    ret = sysdb_attrs_add_string(attrs, "foo", "bar");
        1: 1915:    fail_unless(ret == EOK, "sysdb_attrs_add_string failed");
        -: 1916:
        1: 1917:    ret = sysdb_attrs_add_string(attrs, "fool", "bool");
        1: 1918:    fail_unless(ret == EOK, "sysdb_attrs_add_string failed");
        -: 1919:
        1: 1920:    ret = sysdb_attrs_add_string(attrs, "foot", "boot");
        1: 1921:    fail_unless(ret == EOK, "sysdb_attrs_add_string failed");
        -: 1922:
        1: 1923:    ret = sysdb_attrs_replace_name(attrs, "foo", "foot");
        1: 1924:    fail_unless(ret == EEXIST,
        -: 1925:                "sysdb_attrs_replace overwrites existing attribute");
        -: 1926:
        1: 1927:    ret = sysdb_attrs_replace_name(attrs, "foo", "oof");
        1: 1928:    fail_unless(ret == EOK, "sysdb_attrs_replace failed");
        -: 1929:
        1: 1930:    ret = sysdb_attrs_get_el(attrs, "foo", &el);
        1: 1931:    fail_unless(ret == EOK, "sysdb_attrs_get_el failed");
        1: 1932:    fail_unless(el->num_values == 0, "Attribute foo is not empty.");
        -: 1933:
        1: 1934:    ret = sysdb_attrs_get_el(attrs, "oof", &el);
        1: 1935:    fail_unless(ret == EOK, "sysdb_attrs_get_el failed");
        1: 1936:    fail_unless(el->num_values == 1,
        -: 1937:                "Wrong number of values for attribute oof, "
        -: 1938:                "expected [1] got [%d].", el->num_values);
        1: 1939:    fail_unless(strncmp("bar", (char *) el->values[0].data,
        -: 1940:                        el->values[0].length) == 0,
        -: 1941:                "Wrong value, expected [bar] got [%.*s]", el->values[0].length,
        -: 1942:                                                          el->values[0].data);
        -: 1943:
        1: 1944:    talloc_free(attrs);
        -: 1945:}
        1: 1946:END_TEST
        -: 1947:
       30: 1948:START_TEST (test_sysdb_memberof_store_group)
        -: 1949:{
        -: 1950:    struct sysdb_test_ctx *test_ctx;
        -: 1951:    struct test_data *data;
        -: 1952:    int ret;
        -: 1953:
        -: 1954:    /* Setup */
       30: 1955:    ret = setup_sysdb_tests(&test_ctx);
       30: 1956:    if (ret != EOK) {
    #####: 1957:        fail("Could not set up the test");
       30: 1958:        return;
        -: 1959:    }
        -: 1960:
       30: 1961:    data = talloc_zero(test_ctx, struct test_data);
       30: 1962:    data->ctx = test_ctx;
       30: 1963:    data->ev = test_ctx->ev;
       30: 1964:    data->gid = MBO_GROUP_BASE + _i;
       30: 1965:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 1966:
       30: 1967:    if (_i == 0) {
        3: 1968:        data->attrlist = NULL;
        -: 1969:    } else {
       27: 1970:        data->attrlist = talloc_array(data, const char *, 2);
       27: 1971:        fail_unless(data->attrlist != NULL, "talloc_array failed.");
       27: 1972:        data->attrlist[0] = talloc_asprintf(data, "testgroup%d", data->gid - 1);
       27: 1973:        data->attrlist[1] = NULL;
        -: 1974:    }
        -: 1975:
       30: 1976:    ret = test_memberof_store_group(data);
        -: 1977:
       30: 1978:    fail_if(ret != EOK, "Could not store POSIX group #%d", data->gid);
       30: 1979:    talloc_free(test_ctx);
        -: 1980:}
        -: 1981:END_TEST
        -: 1982:
       30: 1983:START_TEST (test_sysdb_memberof_store_group_with_ghosts)
        -: 1984:{
        -: 1985:    struct sysdb_test_ctx *test_ctx;
        -: 1986:    struct test_data *data;
        -: 1987:    int ret;
        -: 1988:
        -: 1989:    /* Setup */
       30: 1990:    ret = setup_sysdb_tests(&test_ctx);
       30: 1991:    if (ret != EOK) {
    #####: 1992:        fail("Could not set up the test");
       30: 1993:        return;
        -: 1994:    }
        -: 1995:
       30: 1996:    data = talloc_zero(test_ctx, struct test_data);
       30: 1997:    data->ctx = test_ctx;
       30: 1998:    data->ev = test_ctx->ev;
       30: 1999:    data->gid = _i;
       30: 2000:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2001:
       30: 2002:    if (_i == 0) {
    #####: 2003:        data->attrlist = NULL;
        -: 2004:    } else {
       30: 2005:        data->attrlist = talloc_array(data, const char *, 2);
       30: 2006:        fail_unless(data->attrlist != NULL, "talloc_array failed.");
       30: 2007:        data->attrlist[0] = talloc_asprintf(data, "testgroup%d", data->gid - 1);
       30: 2008:        data->attrlist[1] = NULL;
        -: 2009:    }
        -: 2010:
       30: 2011:    data->memberlist = talloc_array(data, char *, 2);
       30: 2012:    fail_unless(data->memberlist != NULL, "talloc_array failed.");
       30: 2013:    data->memberlist[0] = talloc_asprintf(data, "testuser%d", data->gid);
       30: 2014:    data->memberlist[1] = NULL;
        -: 2015:
       30: 2016:    ret = test_memberof_store_group_with_ghosts(data);
        -: 2017:
       30: 2018:    fail_if(ret != EOK, "Could not store POSIX group #%d", data->gid);
       30: 2019:    talloc_free(test_ctx);
        -: 2020:}
        -: 2021:END_TEST
        -: 2022:
       10: 2023:START_TEST (test_sysdb_memberof_store_group_with_double_ghosts)
        -: 2024:{
        -: 2025:    struct sysdb_test_ctx *test_ctx;
        -: 2026:    struct test_data *data;
        -: 2027:    int ret;
        -: 2028:
        -: 2029:    /* Setup */
       10: 2030:    ret = setup_sysdb_tests(&test_ctx);
       10: 2031:    if (ret != EOK) {
    #####: 2032:        fail("Could not set up the test");
       10: 2033:        return;
        -: 2034:    }
        -: 2035:
       10: 2036:    data = talloc_zero(test_ctx, struct test_data);
       10: 2037:    data->ctx = test_ctx;
       10: 2038:    data->ev = test_ctx->ev;
       10: 2039:    data->gid = _i;
       10: 2040:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2041:
       10: 2042:    if (_i == 0) {
    #####: 2043:        data->attrlist = NULL;
        -: 2044:    } else {
       10: 2045:        data->attrlist = talloc_array(data, const char *, 2);
       10: 2046:        fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2047:        data->attrlist[0] = talloc_asprintf(data, "testgroup%d", data->gid - 1);
       10: 2048:        data->attrlist[1] = NULL;
        -: 2049:    }
        -: 2050:
       10: 2051:    data->memberlist = talloc_array(data, char *, 3);
       10: 2052:    fail_unless(data->memberlist != NULL, "talloc_array failed.");
       10: 2053:    data->memberlist[0] = talloc_asprintf(data, "testusera%d", data->gid);
       10: 2054:    data->memberlist[1] = talloc_asprintf(data, "testuserb%d", data->gid);
       10: 2055:    data->memberlist[2] = NULL;
        -: 2056:
       10: 2057:    ret = test_memberof_store_group_with_ghosts(data);
        -: 2058:
       10: 2059:    fail_if(ret != EOK, "Could not store POSIX group #%d", data->gid);
       10: 2060:    talloc_free(test_ctx);
        -: 2061:}
        -: 2062:END_TEST
        -: 2063:
       10: 2064:START_TEST (test_sysdb_memberof_mod_add)
        -: 2065:{
        -: 2066:    struct sysdb_test_ctx *test_ctx;
        -: 2067:    struct test_data *data;
        -: 2068:    char *ghostname;
        -: 2069:    int ret;
        -: 2070:    struct ldb_message_element *el;
        -: 2071:    struct ldb_val gv, *test_gv;
        -: 2072:    gid_t itergid;
        -: 2073:
        -: 2074:    /* Setup */
       10: 2075:    ret = setup_sysdb_tests(&test_ctx);
       10: 2076:    if (ret != EOK) {
    #####: 2077:        fail("Could not set up the test");
        -: 2078:        return;
        -: 2079:    }
        -: 2080:
       10: 2081:    data = talloc_zero(test_ctx, struct test_data);
       10: 2082:    data->ctx = test_ctx;
       10: 2083:    data->ev = test_ctx->ev;
       10: 2084:    data->gid = _i;
       10: 2085:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2086:
       10: 2087:    data->attrs = sysdb_new_attrs(data);
       10: 2088:    if (ret != EOK) {
    #####: 2089:        fail("Could not create the changeset");
        -: 2090:        return;
        -: 2091:    }
        -: 2092:
       10: 2093:    ghostname = talloc_asprintf(data, "testghost%d", _i);
       10: 2094:    fail_unless(ghostname != NULL, "Out of memory\n");
       10: 2095:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname);
       10: 2096:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 2097:
       10: 2098:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2099:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2100:    data->attrlist[0] = SYSDB_GHOST;
       10: 2101:    data->attrlist[1] = NULL;
        -: 2102:
        -: 2103:    /* Before the add, the groups should not contain the ghost attribute */
       65: 2104:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2105:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2106:                                        test_ctx->domain,
        -: 2107:                                        itergid,
        -: 2108:                                        data->attrlist, &data->msg);
       55: 2109:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2110:                (unsigned long long) data->gid);
        -: 2111:
       55: 2112:        gv.data = (uint8_t *) ghostname;
       55: 2113:        gv.length = strlen(ghostname);
        -: 2114:
       55: 2115:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2116:        if (data->gid > MBO_GROUP_BASE) {
        -: 2117:            /* The first group would have the ghost attribute gone completely */
       45: 2118:            fail_if(el == NULL, "Cannot find ghost element\n");
       45: 2119:            test_gv = ldb_msg_find_val(el, &gv);
       45: 2120:            fail_unless(test_gv == NULL,
        -: 2121:                        "Ghost user %s unexpectedly found\n", ghostname);
        -: 2122:        } else {
       10: 2123:            fail_unless(el == NULL, "Stray values in ghost element?\n");
        -: 2124:        }
        -: 2125:    }
        -: 2126:
        -: 2127:    /* Perform the add operation */
       10: 2128:    ret =  sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 2129:                                data->groupname, data->attrs, SYSDB_MOD_ADD);
       10: 2130:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 2131:
        -: 2132:    /* Before the delete, all groups with gid >= _i have the testuser%_i
        -: 2133:     * as a member
        -: 2134:     */
       65: 2135:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2136:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2137:                                        test_ctx->domain,
        -: 2138:                                        itergid,
        -: 2139:                                        data->attrlist, &data->msg);
       55: 2140:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2141:                (unsigned long long) data->gid);
        -: 2142:
       55: 2143:        gv.data = (uint8_t *) ghostname;
       55: 2144:        gv.length = strlen(ghostname);
        -: 2145:
       55: 2146:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2147:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2148:
       55: 2149:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2150:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname);
        -: 2151:    }
       10: 2152:    talloc_free(test_ctx);
        -: 2153:}
        -: 2154:END_TEST
        -: 2155:
       10: 2156:START_TEST (test_sysdb_memberof_mod_replace)
        -: 2157:{
        -: 2158:    struct sysdb_test_ctx *test_ctx;
        -: 2159:    struct test_data *data;
        -: 2160:    char *ghostname_del;
        -: 2161:    char *ghostname_add;
        -: 2162:    int ret;
        -: 2163:    struct ldb_message_element *el;
        -: 2164:    struct ldb_val gv, *test_gv;
        -: 2165:    gid_t itergid;
        -: 2166:
        -: 2167:    /* Setup */
       10: 2168:    ret = setup_sysdb_tests(&test_ctx);
       10: 2169:    if (ret != EOK) {
    #####: 2170:        fail("Could not set up the test");
        -: 2171:        return;
        -: 2172:    }
        -: 2173:
       10: 2174:    data = talloc_zero(test_ctx, struct test_data);
       10: 2175:    data->ctx = test_ctx;
       10: 2176:    data->ev = test_ctx->ev;
       10: 2177:    data->gid = _i;
       10: 2178:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2179:
       10: 2180:    data->attrs = sysdb_new_attrs(data);
       10: 2181:    if (ret != EOK) {
    #####: 2182:        fail("Could not create the changeset");
        -: 2183:        return;
        -: 2184:    }
        -: 2185:
        -: 2186:    /* The test replaces the testuser%i attribute with testghost%i */
       10: 2187:    ghostname_del = talloc_asprintf(data, "testuser%d", _i);
       10: 2188:    fail_unless(ghostname_del != NULL, "Out of memory\n");
        -: 2189:
       10: 2190:    ghostname_add = talloc_asprintf(data, "testghost%d", _i);
       10: 2191:    fail_unless(ghostname_add != NULL, "Out of memory\n");
       10: 2192:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
       10: 2193:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 2194:
       10: 2195:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2196:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2197:    data->attrlist[0] = SYSDB_GHOST;
       10: 2198:    data->attrlist[1] = NULL;
        -: 2199:
        -: 2200:    /* Before the replace, all groups with gid >= _i have the testuser%_i
        -: 2201:     * as a member
        -: 2202:     */
       65: 2203:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2204:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2205:                                        test_ctx->domain,
        -: 2206:                                        itergid,
        -: 2207:                                        data->attrlist, &data->msg);
       55: 2208:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2209:                (unsigned long long) data->gid);
        -: 2210:
       55: 2211:        gv.data = (uint8_t *) ghostname_del;
       55: 2212:        gv.length = strlen(ghostname_del);
        -: 2213:
       55: 2214:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2215:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2216:
       55: 2217:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2218:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
        -: 2219:    }
        -: 2220:
        -: 2221:    /* Perform the replace operation */
       10: 2222:    ret =  sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 2223:                                data->groupname, data->attrs, SYSDB_MOD_REP);
       10: 2224:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 2225:
        -: 2226:    /* After the replace, all groups with gid >= _i have the testghost%_i
        -: 2227:     * as a member
        -: 2228:     */
       65: 2229:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2230:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2231:                                        test_ctx->domain,
        -: 2232:                                        itergid,
        -: 2233:                                        data->attrlist, &data->msg);
       55: 2234:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2235:                (unsigned long long) data->gid);
        -: 2236:
       55: 2237:        gv.data = (uint8_t *) ghostname_add;
       55: 2238:        gv.length = strlen(ghostname_add);
        -: 2239:
       55: 2240:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2241:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2242:
       55: 2243:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2244:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
        -: 2245:    }
        -: 2246:
       10: 2247:    talloc_free(test_ctx);
        -: 2248:}
        -: 2249:END_TEST
        -: 2250:
       10: 2251:START_TEST (test_sysdb_memberof_mod_replace_keep)
        -: 2252:{
        -: 2253:    struct sysdb_test_ctx *test_ctx;
        -: 2254:    struct test_data *data;
        -: 2255:    char *ghostname_rep;
        -: 2256:    char *ghostname_del;
        -: 2257:    char *ghostname_check;
        -: 2258:    int ret;
        -: 2259:    struct ldb_message_element *el;
        -: 2260:    struct ldb_val gv, *test_gv;
        -: 2261:    gid_t itergid;
        -: 2262:    uid_t iteruid;
        -: 2263:
        -: 2264:    /* Setup */
       10: 2265:    ret = setup_sysdb_tests(&test_ctx);
       10: 2266:    if (ret != EOK) {
    #####: 2267:        fail("Could not set up the test");
        -: 2268:        return;
        -: 2269:    }
        -: 2270:
       10: 2271:    data = talloc_zero(test_ctx, struct test_data);
       10: 2272:    data->ctx = test_ctx;
       10: 2273:    data->ev = test_ctx->ev;
       10: 2274:    data->gid = MBO_GROUP_BASE + 10 - _i;
       10: 2275:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2276:
       10: 2277:    data->attrs = sysdb_new_attrs(data);
       10: 2278:    if (ret != EOK) {
    #####: 2279:        fail("Could not create the changeset");
        -: 2280:        return;
        -: 2281:    }
        -: 2282:
        -: 2283:    /* The test replaces the attributes (testusera$gid, testuserb$gid) with
        -: 2284:     * just testusera$gid. The result should be not only testusera, but also
        -: 2285:     * all ghost users inherited from child groups
        -: 2286:     */
       10: 2287:    ghostname_rep = talloc_asprintf(data, "testusera%d", data->gid);
       10: 2288:    fail_unless(ghostname_rep != NULL, "Out of memory\n");
       10: 2289:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_rep);
       10: 2290:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 2291:
       10: 2292:    ghostname_del = talloc_asprintf(data, "testuserb%d", data->gid);
       10: 2293:    fail_unless(ghostname_del != NULL, "Out of memory\n");
        -: 2294:
       10: 2295:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2296:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2297:    data->attrlist[0] = SYSDB_GHOST;
       10: 2298:    data->attrlist[1] = NULL;
        -: 2299:
        -: 2300:    /* Before the replace, all groups with gid >= _i have both testuser a
        -: 2301:     * and testuserb as a member
        -: 2302:     */
       65: 2303:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2304:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2305:                                        test_ctx->domain,
        -: 2306:                                        itergid,
        -: 2307:                                        data->attrlist, &data->msg);
       55: 2308:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2309:                (unsigned long long) data->gid);
        -: 2310:
       55: 2311:        gv.data = (uint8_t *) ghostname_rep;
       55: 2312:        gv.length = strlen(ghostname_rep);
        -: 2313:
       55: 2314:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2315:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2316:
       55: 2317:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2318:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_rep);
        -: 2319:
       55: 2320:        gv.data = (uint8_t *) ghostname_del;
       55: 2321:        gv.length = strlen(ghostname_rep);
        -: 2322:
       55: 2323:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2324:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
        -: 2325:
        -: 2326:        /* inherited users must be there */
      385: 2327:        for (iteruid = MBO_GROUP_BASE ; iteruid < itergid ; iteruid++) {
      330: 2328:            ghostname_check = talloc_asprintf(data, "testusera%d", iteruid);
      330: 2329:            gv.data = (uint8_t *) ghostname_check;
      330: 2330:            gv.length = strlen(ghostname_check);
        -: 2331:
      330: 2332:            test_gv = ldb_msg_find_val(el, &gv);
      330: 2333:            fail_if(test_gv == NULL, "Cannot find inherited ghost user %s\n",
        -: 2334:                    ghostname_check);
        -: 2335:
      330: 2336:            if (iteruid < data->gid) {
        -: 2337:                /* Also check the B user if it hasn't been deleted yet */
      165: 2338:                ghostname_check = talloc_asprintf(data, "testuserb%d", iteruid);
      165: 2339:                gv.data = (uint8_t *) ghostname_check;
      165: 2340:                gv.length = strlen(ghostname_check);
        -: 2341:
      165: 2342:                test_gv = ldb_msg_find_val(el, &gv);
      165: 2343:                fail_if(test_gv == NULL, "Cannot find inherited ghost user %s\n",
        -: 2344:                        ghostname_check);
        -: 2345:            }
      330: 2346:            talloc_zfree(ghostname_check);
        -: 2347:        }
        -: 2348:    }
        -: 2349:
        -: 2350:    /* Perform the replace operation */
       10: 2351:    ret =  sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 2352:                                data->groupname, data->attrs, SYSDB_MOD_REP);
       10: 2353:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 2354:
        -: 2355:    /* After the replace, testusera should still be there, but we also need
        -: 2356:     * to keep ghost users inherited from other groups
        -: 2357:     */
       65: 2358:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2359:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2360:                                        test_ctx->domain,
        -: 2361:                                        itergid,
        -: 2362:                                        data->attrlist, &data->msg);
       55: 2363:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2364:                (unsigned long long) data->gid);
        -: 2365:
       55: 2366:        gv.data = (uint8_t *) ghostname_rep;
       55: 2367:        gv.length = strlen(ghostname_rep);
        -: 2368:
        -: 2369:        /* testusera must still be there */
       55: 2370:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2371:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2372:
       55: 2373:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2374:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_rep);
        -: 2375:
        -: 2376:        /* testuserb must be gone */
       55: 2377:        gv.data = (uint8_t *) ghostname_del;
       55: 2378:        gv.length = strlen(ghostname_rep);
        -: 2379:
       55: 2380:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2381:        fail_unless(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
        -: 2382:
        -: 2383:        /* inherited users must still be there */
      385: 2384:        for (iteruid = MBO_GROUP_BASE ; iteruid < itergid ; iteruid++) {
      330: 2385:            ghostname_check = talloc_asprintf(data, "testusera%d", iteruid);
      330: 2386:            gv.data = (uint8_t *) ghostname_check;
      330: 2387:            gv.length = strlen(ghostname_check);
        -: 2388:
      330: 2389:            test_gv = ldb_msg_find_val(el, &gv);
      330: 2390:            fail_if(test_gv == NULL, "Cannot find inherited ghost user %s\n",
        -: 2391:                    ghostname_check);
        -: 2392:
      330: 2393:            if (iteruid < data->gid) {
        -: 2394:                /* Also check the B user if it hasn't been deleted yet */
      165: 2395:                ghostname_check = talloc_asprintf(data, "testuserb%d", iteruid);
      165: 2396:                gv.data = (uint8_t *) ghostname_check;
      165: 2397:                gv.length = strlen(ghostname_check);
        -: 2398:
      165: 2399:                test_gv = ldb_msg_find_val(el, &gv);
      165: 2400:                fail_if(test_gv == NULL, "Cannot find inherited ghost user %s\n",
        -: 2401:                        ghostname_check);
        -: 2402:            }
      330: 2403:            talloc_zfree(ghostname_check);
        -: 2404:        }
        -: 2405:    }
        -: 2406:
       10: 2407:    talloc_free(test_ctx);
        -: 2408:}
        -: 2409:END_TEST
        -: 2410:
        1: 2411:START_TEST (test_sysdb_memberof_close_loop)
        -: 2412:{
        -: 2413:    struct sysdb_test_ctx *test_ctx;
        -: 2414:    struct test_data *data;
        -: 2415:    int ret;
        -: 2416:
        -: 2417:    /* Setup */
        1: 2418:    ret = setup_sysdb_tests(&test_ctx);
        1: 2419:    if (ret != EOK) {
    #####: 2420:        fail("Could not set up the test");
        1: 2421:        return;
        -: 2422:    }
        -: 2423:
        1: 2424:    data = talloc_zero(test_ctx, struct test_data);
        1: 2425:    data->ctx = test_ctx;
        1: 2426:    data->ev = test_ctx->ev;
        1: 2427:    data->gid = MBO_GROUP_BASE;
        1: 2428:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2429:
        1: 2430:    data->attrlist = talloc_array(data, const char *, 2);
        1: 2431:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
        1: 2432:    data->attrlist[0] = talloc_asprintf(data, "testgroup%d", data->gid + 9);
        1: 2433:    data->attrlist[1] = NULL;
        -: 2434:
        1: 2435:    ret = test_memberof_store_group(data);
        -: 2436:
        1: 2437:    fail_if(ret != EOK, "Could not store POSIX group #%d", data->gid);
        1: 2438:    talloc_free(test_ctx);
        -: 2439:}
        -: 2440:END_TEST
        -: 2441:
       20: 2442:START_TEST (test_sysdb_memberof_store_user)
        -: 2443:{
        -: 2444:    struct sysdb_test_ctx *test_ctx;
        -: 2445:    struct test_data *data;
        -: 2446:    int ret;
        -: 2447:
        -: 2448:    /* Setup */
       20: 2449:    ret = setup_sysdb_tests(&test_ctx);
       20: 2450:    if (ret != EOK) {
    #####: 2451:        fail("Could not set up the test");
       20: 2452:        return;
        -: 2453:    }
        -: 2454:
       20: 2455:    data = talloc_zero(test_ctx, struct test_data);
       20: 2456:    data->ctx = test_ctx;
       20: 2457:    data->ev = test_ctx->ev;
       20: 2458:    data->uid = MBO_USER_BASE + _i;
       20: 2459:    data->gid = 0; /* MPG domain */
       20: 2460:    data->username = talloc_asprintf(data, "testuser%d", data->uid);
        -: 2461:
       20: 2462:    ret = test_store_user(data);
        -: 2463:
       20: 2464:    fail_if(ret != EOK, "Could not store user %s", data->username);
       20: 2465:    talloc_free(test_ctx);
        -: 2466:}
        -: 2467:END_TEST
        -: 2468:
       20: 2469:START_TEST (test_sysdb_memberof_add_group_member)
        -: 2470:{
        -: 2471:    struct sysdb_test_ctx *test_ctx;
        -: 2472:    struct test_data *data;
        -: 2473:    int ret;
        -: 2474:
        -: 2475:    /* Setup */
       20: 2476:    ret = setup_sysdb_tests(&test_ctx);
       20: 2477:    if (ret != EOK) {
    #####: 2478:        fail("Could not set up the test");
       20: 2479:        return;
        -: 2480:    }
        -: 2481:
       20: 2482:    data = talloc_zero(test_ctx, struct test_data);
       20: 2483:    data->ctx = test_ctx;
       20: 2484:    data->ev = test_ctx->ev;
       20: 2485:    data->groupname = talloc_asprintf(data, "testgroup%d", _i + MBO_GROUP_BASE);
       20: 2486:    data->uid = MBO_USER_BASE + _i;
        -: 2487:
       20: 2488:    ret = test_add_group_member(data);
        -: 2489:
       20: 2490:    fail_if(ret != EOK, "Could not modify group %s", data->groupname);
        -: 2491:
       20: 2492:    talloc_free(test_ctx);
        -: 2493:}
        -: 2494:END_TEST
        -: 2495:
       10: 2496:START_TEST (test_sysdb_memberof_check_memberuid_without_group_5)
        -: 2497:{
        -: 2498:    struct sysdb_test_ctx *test_ctx;
        -: 2499:    struct test_data *data;
        -: 2500:    int ret;
        -: 2501:
        -: 2502:    /* Setup */
       10: 2503:    ret = setup_sysdb_tests(&test_ctx);
       10: 2504:    if (ret != EOK) {
    #####: 2505:        fail("Could not set up the test");
       10: 2506:        return;
        -: 2507:    }
        -: 2508:
       10: 2509:    data = talloc_zero(test_ctx, struct test_data);
       10: 2510:    data->ctx = test_ctx;
       10: 2511:    data->ev = test_ctx->ev;
       10: 2512:    data->gid = _i + MBO_GROUP_BASE;
        -: 2513:
       10: 2514:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2515:    fail_unless(data->attrlist != NULL, "tallo_array failed.");
       10: 2516:    data->attrlist[0] = "memberuid";
       10: 2517:    data->attrlist[1] = NULL;
        -: 2518:
       30: 2519:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2520:                                    test_ctx->domain,
       10: 2521:                                    _i + MBO_GROUP_BASE,
        -: 2522:                                    data->attrlist, &data->msg);
       10: 2523:    if (_i == 5) {
        1: 2524:        fail_unless(ret == ENOENT,
        -: 2525:                    "sysdb_search_group_by_gid found "
        -: 2526:                    "already deleted group");
        1: 2527:        if (ret == ENOENT) ret = EOK;
        -: 2528:
        1: 2529:        fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2530:    } else {
        9: 2531:        fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2532:
        9: 2533:        fail_unless(data->msg->num_elements == 1,
        -: 2534:                    "Wrong number of results, expected [1] got [%d]",
        -: 2535:                    data->msg->num_elements);
        9: 2536:        fail_unless(strcmp(data->msg->elements[0].name, "memberuid") == 0,
        -: 2537:                    "Wrong attribute name");
        9: 2538:        fail_unless(data->msg->elements[0].num_values == ((_i + 1) % 6),
        -: 2539:                    "Wrong number of attribute values, "
        -: 2540:                    "expected [%d] got [%d]", ((_i + 1) % 6),
        -: 2541:                    data->msg->elements[0].num_values);
        -: 2542:    }
        -: 2543:
       10: 2544:    talloc_free(test_ctx);
        -: 2545:}
        -: 2546:END_TEST
        -: 2547:
       10: 2548:START_TEST (test_sysdb_memberof_check_memberuid)
        -: 2549:{
        -: 2550:    struct sysdb_test_ctx *test_ctx;
        -: 2551:    struct test_data *data;
        -: 2552:    int ret;
        -: 2553:
        -: 2554:    /* Setup */
       10: 2555:    ret = setup_sysdb_tests(&test_ctx);
       10: 2556:    if (ret != EOK) {
    #####: 2557:        fail("Could not set up the test");
       10: 2558:        return;
        -: 2559:    }
        -: 2560:
       10: 2561:    data = talloc_zero(test_ctx, struct test_data);
       10: 2562:    data->ctx = test_ctx;
       10: 2563:    data->ev = test_ctx->ev;
       10: 2564:    data->gid = _i + MBO_GROUP_BASE;
        -: 2565:
       10: 2566:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2567:    fail_unless(data->attrlist != NULL, "tallo_array failed.");
       10: 2568:    data->attrlist[0] = "memberuid";
       10: 2569:    data->attrlist[1] = NULL;
        -: 2570:
       30: 2571:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2572:                                    test_ctx->domain,
       10: 2573:                                    _i + MBO_GROUP_BASE,
        -: 2574:                                    data->attrlist, &data->msg);
        -: 2575:
       10: 2576:    fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2577:
       10: 2578:    fail_unless(data->msg->num_elements == 1,
        -: 2579:                "Wrong number of results, expected [1] got [%d]",
        -: 2580:                data->msg->num_elements);
       10: 2581:    fail_unless(strcmp(data->msg->elements[0].name, "memberuid") == 0,
        -: 2582:                "Wrong attribute name");
       10: 2583:    fail_unless(data->msg->elements[0].num_values == _i + 1,
        -: 2584:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2585:                _i + 1, data->msg->elements[0].num_values);
        -: 2586:
       10: 2587:    talloc_free(test_ctx);
        -: 2588:}
        -: 2589:END_TEST
        -: 2590:
       10: 2591:START_TEST (test_sysdb_memberof_check_memberuid_loop)
        -: 2592:{
        -: 2593:    struct sysdb_test_ctx *test_ctx;
        -: 2594:    struct test_data *data;
        -: 2595:    int ret;
        -: 2596:
        -: 2597:    /* Setup */
       10: 2598:    ret = setup_sysdb_tests(&test_ctx);
       10: 2599:    if (ret != EOK) {
    #####: 2600:        fail("Could not set up the test");
       10: 2601:        return;
        -: 2602:    }
        -: 2603:
       10: 2604:    data = talloc_zero(test_ctx, struct test_data);
       10: 2605:    data->ctx = test_ctx;
       10: 2606:    data->ev = test_ctx->ev;
       10: 2607:    data->gid = _i + MBO_GROUP_BASE;
        -: 2608:
       10: 2609:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2610:    fail_unless(data->attrlist != NULL, "tallo_array failed.");
       10: 2611:    data->attrlist[0] = "memberuid";
       10: 2612:    data->attrlist[1] = NULL;
        -: 2613:
       30: 2614:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2615:                                    test_ctx->domain,
       10: 2616:                                    _i + MBO_GROUP_BASE,
        -: 2617:                                    data->attrlist, &data->msg);
        -: 2618:
       10: 2619:    fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2620:
       10: 2621:    fail_unless(data->msg->num_elements == 1,
        -: 2622:                "Wrong number of results, expected [1] got [%d]",
        -: 2623:                data->msg->num_elements);
       10: 2624:    fail_unless(strcmp(data->msg->elements[0].name, "memberuid") == 0,
        -: 2625:                "Wrong attribute name");
       10: 2626:    fail_unless(data->msg->elements[0].num_values == 10,
        -: 2627:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2628:                10, data->msg->elements[0].num_values);
        -: 2629:
       10: 2630:    talloc_free(test_ctx);
        -: 2631:}
        -: 2632:END_TEST
        -: 2633:
       10: 2634:START_TEST (test_sysdb_memberof_check_memberuid_loop_without_group_5)
        -: 2635:{
        -: 2636:    struct sysdb_test_ctx *test_ctx;
        -: 2637:    struct test_data *data;
        -: 2638:    int ret;
        -: 2639:
        -: 2640:    /* Setup */
       10: 2641:    ret = setup_sysdb_tests(&test_ctx);
       10: 2642:    if (ret != EOK) {
    #####: 2643:        fail("Could not set up the test");
       10: 2644:        return;
        -: 2645:    }
        -: 2646:
       10: 2647:    data = talloc_zero(test_ctx, struct test_data);
       10: 2648:    data->ctx = test_ctx;
       10: 2649:    data->ev = test_ctx->ev;
       10: 2650:    data->gid = _i + MBO_GROUP_BASE;
        -: 2651:
       10: 2652:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2653:    fail_unless(data->attrlist != NULL, "tallo_array failed.");
       10: 2654:    data->attrlist[0] = "memberuid";
       10: 2655:    data->attrlist[1] = NULL;
        -: 2656:
       30: 2657:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2658:                                    test_ctx->domain,
       10: 2659:                                    _i + MBO_GROUP_BASE,
        -: 2660:                                    data->attrlist, &data->msg);
        -: 2661:
       10: 2662:    if (_i == 5) {
        1: 2663:        fail_unless(ret == ENOENT,
        -: 2664:                    "sysdb_search_group_by_gid_send found "
        -: 2665:                    "already deleted group");
        1: 2666:        if (ret == ENOENT) ret = EOK;
        -: 2667:
        1: 2668:        fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2669:    } else {
        9: 2670:        fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2671:
        9: 2672:        fail_unless(data->msg->num_elements == 1,
        -: 2673:                    "Wrong number of results, expected [1] got [%d]",
        -: 2674:                    data->msg->num_elements);
        9: 2675:        fail_unless(strcmp(data->msg->elements[0].name, "memberuid") == 0,
        -: 2676:                    "Wrong attribute name");
        9: 2677:        fail_unless(data->msg->elements[0].num_values == ((_i + 5) % 10),
        -: 2678:                    "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2679:                    ((_i + 5) % 10), data->msg->elements[0].num_values);
        -: 2680:    }
        -: 2681:
       10: 2682:    talloc_free(test_ctx);
        -: 2683:}
        -: 2684:END_TEST
        -: 2685:
       40: 2686:START_TEST (test_sysdb_memberof_check_nested_ghosts)
        -: 2687:{
        -: 2688:    struct sysdb_test_ctx *test_ctx;
        -: 2689:    struct test_data *data;
        -: 2690:    int ret;
        -: 2691:
        -: 2692:    /* Setup */
       40: 2693:    ret = setup_sysdb_tests(&test_ctx);
       40: 2694:    if (ret != EOK) {
    #####: 2695:        fail("Could not set up the test");
       40: 2696:        return;
        -: 2697:    }
        -: 2698:
       40: 2699:    data = talloc_zero(test_ctx, struct test_data);
       40: 2700:    data->ctx = test_ctx;
       40: 2701:    data->ev = test_ctx->ev;
       40: 2702:    data->gid = _i;
        -: 2703:
       40: 2704:    data->attrlist = talloc_array(data, const char *, 2);
       40: 2705:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       40: 2706:    data->attrlist[0] = SYSDB_GHOST;
       40: 2707:    data->attrlist[1] = NULL;
        -: 2708:
       80: 2709:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       40: 2710:                                    test_ctx->domain,
        -: 2711:                                    data->gid,
        -: 2712:                                    data->attrlist, &data->msg);
       40: 2713:    fail_if(ret != EOK, "Cannot retrieve group %llu\n", (unsigned long long) data->gid);
        -: 2714:
       40: 2715:    fail_unless(strcmp(data->msg->elements[0].name, SYSDB_GHOST) == 0,
        -: 2716:                "Wrong attribute name");
       40: 2717:    fail_unless(data->msg->elements[0].num_values == _i - MBO_GROUP_BASE + 1,
        -: 2718:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2719:                _i + 1, data->msg->elements[0].num_values);
        -: 2720:
       40: 2721:    talloc_free(test_ctx);
        -: 2722:}
        -: 2723:END_TEST
        -: 2724:
       10: 2725:START_TEST (test_sysdb_memberof_check_nested_double_ghosts)
        -: 2726:{
        -: 2727:    struct sysdb_test_ctx *test_ctx;
        -: 2728:    struct test_data *data;
        -: 2729:    int ret;
        -: 2730:
        -: 2731:    /* Setup */
       10: 2732:    ret = setup_sysdb_tests(&test_ctx);
       10: 2733:    if (ret != EOK) {
    #####: 2734:        fail("Could not set up the test");
       10: 2735:        return;
        -: 2736:    }
        -: 2737:
       10: 2738:    data = talloc_zero(test_ctx, struct test_data);
       10: 2739:    data->ctx = test_ctx;
       10: 2740:    data->ev = test_ctx->ev;
       10: 2741:    data->gid = _i;
        -: 2742:
       10: 2743:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2744:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2745:    data->attrlist[0] = SYSDB_GHOST;
       10: 2746:    data->attrlist[1] = NULL;
        -: 2747:
       20: 2748:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2749:                                    test_ctx->domain,
        -: 2750:                                    data->gid,
        -: 2751:                                    data->attrlist, &data->msg);
       10: 2752:    fail_if(ret != EOK, "Cannot retrieve group %llu\n", (unsigned long long) data->gid);
        -: 2753:
       10: 2754:    fail_unless(strcmp(data->msg->elements[0].name, SYSDB_GHOST) == 0,
        -: 2755:                "Wrong attribute name");
       10: 2756:    fail_unless(data->msg->elements[0].num_values == (_i - MBO_GROUP_BASE + 1)*2,
        -: 2757:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2758:                (_i - MBO_GROUP_BASE + 1)*2,
        -: 2759:                data->msg->elements[0].num_values);
        -: 2760:
       10: 2761:    talloc_free(test_ctx);
        -: 2762:}
        -: 2763:END_TEST
        -: 2764:
        9: 2765:START_TEST (test_sysdb_memberof_remove_child_group_and_check_ghost)
        -: 2766:{
        -: 2767:    struct sysdb_test_ctx *test_ctx;
        -: 2768:    struct test_data *data;
        -: 2769:    int ret;
        -: 2770:    gid_t delgid;
        -: 2771:
        -: 2772:    /* Setup */
        9: 2773:    ret = setup_sysdb_tests(&test_ctx);
        9: 2774:    if (ret != EOK) {
    #####: 2775:        fail("Could not set up the test");
        9: 2776:        return;
        -: 2777:    }
        -: 2778:
        9: 2779:    data = talloc_zero(test_ctx, struct test_data);
        9: 2780:    data->ctx = test_ctx;
        9: 2781:    data->ev = test_ctx->ev;
        9: 2782:    data->gid = _i;
        9: 2783:    delgid = data->gid - 1;
        -: 2784:
        9: 2785:    data->attrlist = talloc_array(data, const char *, 2);
        9: 2786:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
        9: 2787:    data->attrlist[0] = SYSDB_GHOST;
        9: 2788:    data->attrlist[1] = NULL;
        -: 2789:
       18: 2790:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        9: 2791:                                    test_ctx->domain,
        -: 2792:                                    data->gid,
        -: 2793:                                    data->attrlist, &data->msg);
        9: 2794:    fail_if(ret != EOK, "Cannot retrieve group %llu\n", (unsigned long long) data->gid);
        -: 2795:
        9: 2796:    fail_unless(strcmp(data->msg->elements[0].name, SYSDB_GHOST) == 0,
        -: 2797:                "Wrong attribute name");
        -: 2798:
        -: 2799:    /* Expect our own and our parent's */
        9: 2800:    fail_unless(data->msg->elements[0].num_values == 2,
        -: 2801:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2802:                2, data->msg->elements[0].num_values);
        -: 2803:
        -: 2804:    /* Remove the parent */
        9: 2805:    ret = sysdb_delete_group(data->ctx->sysdb, data->ctx->domain, NULL, delgid);
        9: 2806:    fail_if(ret != EOK, "Cannot delete group %llu [%d]: %s\n",
        -: 2807:            (unsigned long long) data->gid, ret, strerror(ret));
        -: 2808:
        9: 2809:    talloc_free(data->msg);
        -: 2810:
        -: 2811:    /* Check the parent again. The inherited ghost user should be gone. */
       18: 2812:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        9: 2813:                                    test_ctx->domain,
        -: 2814:                                    data->gid, data->attrlist, &data->msg);
        9: 2815:    fail_if(ret != EOK, "Cannot retrieve group %llu\n", (unsigned long long) data->gid);
        -: 2816:
        9: 2817:    fail_unless(strcmp(data->msg->elements[0].name, SYSDB_GHOST) == 0,
        -: 2818:                "Wrong attribute name");
        -: 2819:
        -: 2820:    /* Expect our own now only */
        9: 2821:    fail_unless(data->msg->elements[0].num_values == 1,
        -: 2822:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2823:                1, data->msg->elements[0].num_values);
        -: 2824:
        9: 2825:    talloc_free(test_ctx);
        -: 2826:}
        -: 2827:END_TEST
        -: 2828:
       10: 2829:START_TEST (test_sysdb_memberof_mod_del)
        -: 2830:{
        -: 2831:    struct sysdb_test_ctx *test_ctx;
        -: 2832:    struct test_data *data;
        -: 2833:    char *ghostname;
        -: 2834:    int ret;
        -: 2835:    struct ldb_message_element *el;
        -: 2836:    struct ldb_val gv, *test_gv;
        -: 2837:    gid_t itergid;
        -: 2838:
        -: 2839:    /* Setup */
       10: 2840:    ret = setup_sysdb_tests(&test_ctx);
       10: 2841:    if (ret != EOK) {
    #####: 2842:        fail("Could not set up the test");
        -: 2843:        return;
        -: 2844:    }
        -: 2845:
       10: 2846:    data = talloc_zero(test_ctx, struct test_data);
       10: 2847:    data->ctx = test_ctx;
       10: 2848:    data->ev = test_ctx->ev;
       10: 2849:    data->gid = _i;
       10: 2850:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 2851:
       10: 2852:    data->attrs = sysdb_new_attrs(data);
       10: 2853:    if (ret != EOK) {
    #####: 2854:        fail("Could not create the changeset");
        -: 2855:        return;
        -: 2856:    }
        -: 2857:
       10: 2858:    ghostname = talloc_asprintf(data, "testuser%d", _i);
       10: 2859:    fail_unless(ghostname != NULL, "Out of memory\n");
       10: 2860:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname);
       10: 2861:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 2862:
       10: 2863:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2864:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2865:    data->attrlist[0] = SYSDB_GHOST;
       10: 2866:    data->attrlist[1] = NULL;
        -: 2867:
        -: 2868:    /* Before the delete, all groups with gid >= _i have the testuser%_i
        -: 2869:     * as a member
        -: 2870:     */
       65: 2871:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2872:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2873:                                        test_ctx->domain,
        -: 2874:                                        itergid,
        -: 2875:                                        data->attrlist, &data->msg);
       55: 2876:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2877:                (unsigned long long) data->gid);
        -: 2878:
       55: 2879:        gv.data = (uint8_t *) ghostname;
       55: 2880:        gv.length = strlen(ghostname);
        -: 2881:
       55: 2882:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2883:        fail_if(el == NULL, "Cannot find ghost element\n");
        -: 2884:
       55: 2885:        test_gv = ldb_msg_find_val(el, &gv);
       55: 2886:        fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname);
        -: 2887:    }
        -: 2888:
        -: 2889:    /* Delete the attribute */
       10: 2890:    ret = sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 2891:                               data->groupname, data->attrs, SYSDB_MOD_DEL);
       10: 2892:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 2893:
        -: 2894:    /* After the delete, we shouldn't be able to find the ghost attribute */
       65: 2895:    for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
      110: 2896:        ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       55: 2897:                                        test_ctx->domain,
        -: 2898:                                        itergid,
        -: 2899:                                        data->attrlist, &data->msg);
       55: 2900:        fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 2901:                (unsigned long long) data->gid);
        -: 2902:
       55: 2903:        gv.data = (uint8_t *) ghostname;
       55: 2904:        gv.length = strlen(ghostname);
        -: 2905:
       55: 2906:        el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
       55: 2907:        if (itergid > data->gid) {
        -: 2908:            /* The first group would have the ghost attribute gone completely */
       45: 2909:            fail_if(el == NULL, "Cannot find ghost element\n");
       45: 2910:            test_gv = ldb_msg_find_val(el, &gv);
       45: 2911:            fail_unless(test_gv == NULL,
        -: 2912:                        "Ghost user %s unexpectedly found\n", ghostname);
        -: 2913:        } else {
       10: 2914:            fail_unless(el == NULL, "Stray values in ghost element?\n");
        -: 2915:        }
        -: 2916:    }
        -: 2917:
       10: 2918:    talloc_free(test_ctx);
        -: 2919:}
        -: 2920:END_TEST
        -: 2921:
       10: 2922:START_TEST (test_sysdb_memberof_check_ghost)
        -: 2923:{
        -: 2924:    struct sysdb_test_ctx *test_ctx;
        -: 2925:    struct test_data *data;
        -: 2926:    int ret, j;
        -: 2927:    char *expected;
        -: 2928:
        -: 2929:    /* Setup */
       10: 2930:    ret = setup_sysdb_tests(&test_ctx);
       10: 2931:    if (ret != EOK) {
    #####: 2932:        fail("Could not set up the test");
        -: 2933:        return;
        -: 2934:    }
        -: 2935:
       10: 2936:    data = talloc_zero(test_ctx, struct test_data);
       10: 2937:    data->ctx = test_ctx;
       10: 2938:    data->ev = test_ctx->ev;
       10: 2939:    data->gid = _i;
        -: 2940:
       10: 2941:    data->attrlist = talloc_array(data, const char *, 2);
       10: 2942:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 2943:    data->attrlist[0] = SYSDB_GHOST;
       10: 2944:    data->attrlist[1] = NULL;
        -: 2945:
       20: 2946:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 2947:                                    test_ctx->domain,
        -: 2948:                                    data->gid,
        -: 2949:                                    data->attrlist, &data->msg);
        -: 2950:
       10: 2951:    fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 2952:
       10: 2953:    if (_i > MBO_GROUP_BASE) {
        -: 2954:        /* After the previous test, the first group (gid == MBO_GROUP_BASE)
        -: 2955:         * has no ghost users. That's a legitimate test case we need to account
        -: 2956:         * for now.
        -: 2957:         */
        9: 2958:        fail_unless(data->msg->num_elements == 1,
        -: 2959:                    "Wrong number of results, expected [1] got [%d] for %d",
        -: 2960:                    data->msg->num_elements, data->gid);
        -: 2961:    }
        -: 2962:
       10: 2963:    if (data->msg->num_elements == 0) {
        1: 2964:        talloc_free(test_ctx);
        -: 2965:        return;
        -: 2966:    }
        -: 2967:
        9: 2968:    fail_unless(strcmp(data->msg->elements[0].name, SYSDB_GHOST) == 0,
        -: 2969:                "Wrong attribute name");
        9: 2970:    fail_unless(data->msg->elements[0].num_values == _i - MBO_GROUP_BASE,
        -: 2971:                "Wrong number of attribute values, expected [%d] got [%d]",
        -: 2972:                _i + 1, data->msg->elements[0].num_values);
        -: 2973:
       54: 2974:    for (j = MBO_GROUP_BASE; j < _i; j++) {
       45: 2975:        expected = talloc_asprintf(data, "testghost%d", j);
       45: 2976:        fail_if(expected == NULL, "OOM\n");
       45: 2977:        fail_unless(strcmp(expected,
        -: 2978:                           (const char *) data->msg->elements[0].values[j-MBO_GROUP_BASE].data) == 0);
       45: 2979:        talloc_free(expected);
        -: 2980:    }
        -: 2981:
        9: 2982:    talloc_free(test_ctx);
        -: 2983:}
        -: 2984:END_TEST
        -: 2985:
        5: 2986:START_TEST (test_sysdb_memberof_convert_to_real_users)
        -: 2987:{
        -: 2988:    struct sysdb_test_ctx *test_ctx;
        -: 2989:    struct test_data *data;
        -: 2990:    int ret;
        -: 2991:
        -: 2992:    /* Setup */
        5: 2993:    ret = setup_sysdb_tests(&test_ctx);
        5: 2994:    if (ret != EOK) {
    #####: 2995:        fail("Could not set up the test");
        5: 2996:        return;
        -: 2997:    }
        -: 2998:
        5: 2999:    data = talloc_zero(test_ctx, struct test_data);
        5: 3000:    data->ctx = test_ctx;
        5: 3001:    data->ev = test_ctx->ev;
        5: 3002:    data->uid = _i * 2;
        5: 3003:    data->gid = _i * 2;
        5: 3004:    data->username = talloc_asprintf(data, "testghost%d", _i);
        -: 3005:
        5: 3006:    ret = test_store_user(data);
        5: 3007:    fail_if(ret != EOK, "Cannot add user %s\n", data->username);
        -: 3008:}
        -: 3009:END_TEST
        -: 3010:
       10: 3011:START_TEST (test_sysdb_memberof_check_convert)
        -: 3012:{
        -: 3013:    struct sysdb_test_ctx *test_ctx;
        -: 3014:    struct test_data *data;
        -: 3015:    int ret;
        -: 3016:    struct ldb_message_element *ghosts;
        -: 3017:    struct ldb_message_element *members;
        -: 3018:    int exp_mem, exp_gh;
        -: 3019:
        -: 3020:    /* Setup */
       10: 3021:    ret = setup_sysdb_tests(&test_ctx);
       10: 3022:    if (ret != EOK) {
    #####: 3023:        fail("Could not set up the test");
        -: 3024:        return;
        -: 3025:    }
        -: 3026:
       10: 3027:    data = talloc_zero(test_ctx, struct test_data);
       10: 3028:    data->ctx = test_ctx;
       10: 3029:    data->ev = test_ctx->ev;
       10: 3030:    data->gid = _i;
        -: 3031:
       10: 3032:    data->attrlist = talloc_array(data, const char *, 3);
       10: 3033:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
       10: 3034:    data->attrlist[0] = SYSDB_GHOST;
       10: 3035:    data->attrlist[1] = SYSDB_MEMBER;
       10: 3036:    data->attrlist[2] = NULL;
        -: 3037:
       20: 3038:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
       10: 3039:                                    test_ctx->domain,
        -: 3040:                                    data->gid,
        -: 3041:                                    data->attrlist, &data->msg);
        -: 3042:
       10: 3043:    fail_if(ret != EOK, "Could not check group %d", data->gid);
        -: 3044:
       10: 3045:    fail_unless(data->msg->num_elements == (_i == MBO_GROUP_BASE) ? 0 : 1,
        -: 3046:                "Wrong number of results, expected [1] got [%d] for %d",
        -: 3047:                data->msg->num_elements, data->gid);
        -: 3048:
       10: 3049:    if (data->msg->num_elements == 0) {
        1: 3050:        talloc_free(test_ctx);
        -: 3051:        return;
        -: 3052:    }
        -: 3053:
        -: 3054:
        9: 3055:    members = ldb_msg_find_element(data->msg, SYSDB_MEMBER);
        9: 3056:    exp_mem = _i - MBO_GROUP_BASE;
        9: 3057:    if (exp_mem > NUM_GHOSTS/2) {
        4: 3058:        exp_mem = NUM_GHOSTS/2;
        -: 3059:    }
        -: 3060:
        9: 3061:    ghosts = ldb_msg_find_element(data->msg, SYSDB_GHOST);
        9: 3062:    exp_gh = _i - MBO_GROUP_BASE - 5;
        9: 3063:    if (exp_gh < 0) {
        4: 3064:        exp_gh = 0;
        -: 3065:    }
        -: 3066:
        9: 3067:    fail_if(exp_mem != members->num_values,
        -: 3068:            "Expected %d members, found %d\n", exp_mem, members->num_values);
        9: 3069:    if (exp_gh) {
        4: 3070:        fail_if(exp_gh != ghosts->num_values,
        -: 3071:                "Expected %d members, found %d\n", exp_gh, ghosts->num_values);
        -: 3072:    }
        -: 3073:
        9: 3074:    talloc_free(test_ctx);
        -: 3075:}
        -: 3076:END_TEST
        -: 3077:
        4: 3078:START_TEST (test_sysdb_memberof_ghost_replace)
        -: 3079:{
        -: 3080:    struct sysdb_test_ctx *test_ctx;
        -: 3081:    struct test_data *data;
        -: 3082:    char *ghostname_del;
        -: 3083:    char *ghostname_add;
        -: 3084:    int ret;
        -: 3085:    struct ldb_message_element *el;
        -: 3086:    struct ldb_val gv, *test_gv;
        -: 3087:
        -: 3088:    /* Setup */
        4: 3089:    ret = setup_sysdb_tests(&test_ctx);
        4: 3090:    if (ret != EOK) {
    #####: 3091:        fail("Could not set up the test");
        -: 3092:        return;
        -: 3093:    }
        -: 3094:
        4: 3095:    data = talloc_zero(test_ctx, struct test_data);
        4: 3096:    data->ctx = test_ctx;
        4: 3097:    data->ev = test_ctx->ev;
        4: 3098:    data->gid = _i;
        4: 3099:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 3100:
        4: 3101:    data->attrs = sysdb_new_attrs(data);
        4: 3102:    if (ret != EOK) {
    #####: 3103:        fail("Could not create the changeset");
        -: 3104:        return;
        -: 3105:    }
        -: 3106:
        -: 3107:    /* The test replaces the testghost%i attribute with testuser%i */
        4: 3108:    ghostname_del = talloc_asprintf(data, "testghost%d", _i - 1);
        4: 3109:    fail_unless(ghostname_del != NULL, "Out of memory\n");
        -: 3110:
        4: 3111:    ghostname_add = talloc_asprintf(data, "testuser%d", _i - 1);
        4: 3112:    fail_unless(ghostname_add != NULL, "Out of memory\n");
        4: 3113:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
        4: 3114:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 3115:
        4: 3116:    data->attrlist = talloc_array(data, const char *, 2);
        4: 3117:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
        4: 3118:    data->attrlist[0] = SYSDB_GHOST;
        4: 3119:    data->attrlist[1] = NULL;
        -: 3120:
        -: 3121:    /* Before the replace, the group has the testghost%_i as a member */
        8: 3122:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        4: 3123:                                    test_ctx->domain,
        -: 3124:                                    data->gid,
        -: 3125:                                    data->attrlist, &data->msg);
        4: 3126:    fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 3127:            (unsigned long long) data->gid);
        -: 3128:
        4: 3129:    gv.data = (uint8_t *) ghostname_del;
        4: 3130:    gv.length = strlen(ghostname_del);
        -: 3131:
        4: 3132:    el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
        4: 3133:    fail_if(el == NULL, "Cannot find ghost element\n");
        -: 3134:
        4: 3135:    test_gv = ldb_msg_find_val(el, &gv);
        4: 3136:    fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
        -: 3137:
        -: 3138:    /* Perform the replace operation */
        4: 3139:    ret =  sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 3140:                                data->groupname, data->attrs, SYSDB_MOD_REP);
        4: 3141:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 3142:
        -: 3143:    /* After the replace, the group has the testghost%_i as a member */
        8: 3144:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        4: 3145:                                    test_ctx->domain,
        -: 3146:                                    data->gid,
        -: 3147:                                    data->attrlist, &data->msg);
        4: 3148:    fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 3149:            (unsigned long long) data->gid);
        -: 3150:
        4: 3151:    gv.data = (uint8_t *) ghostname_add;
        4: 3152:    gv.length = strlen(ghostname_add);
        -: 3153:
        4: 3154:    el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
        4: 3155:    fail_if(el == NULL, "Cannot find ghost element\n");
        -: 3156:
        4: 3157:    test_gv = ldb_msg_find_val(el, &gv);
        4: 3158:    fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
        -: 3159:}
        -: 3160:END_TEST
        -: 3161:
        4: 3162:START_TEST (test_sysdb_memberof_ghost_replace_noop)
        -: 3163:{
        -: 3164:    struct sysdb_test_ctx *test_ctx;
        -: 3165:    struct test_data *data;
        -: 3166:    char *ghostname_del;
        -: 3167:    char *ghostname_add;
        -: 3168:    int ret;
        -: 3169:    struct ldb_message_element *el;
        -: 3170:    struct ldb_val gv, *test_gv;
        -: 3171:
        -: 3172:    /* Setup */
        4: 3173:    ret = setup_sysdb_tests(&test_ctx);
        4: 3174:    if (ret != EOK) {
    #####: 3175:        fail("Could not set up the test");
        -: 3176:        return;
        -: 3177:    }
        -: 3178:
        4: 3179:    data = talloc_zero(test_ctx, struct test_data);
        4: 3180:    data->ctx = test_ctx;
        4: 3181:    data->ev = test_ctx->ev;
        4: 3182:    data->gid = _i;
        4: 3183:    data->groupname = talloc_asprintf(data, "testgroup%d", data->gid);
        -: 3184:
        4: 3185:    data->attrs = sysdb_new_attrs(data);
        4: 3186:    if (ret != EOK) {
    #####: 3187:        fail("Could not create the changeset");
        -: 3188:        return;
        -: 3189:    }
        -: 3190:
        -: 3191:    /* The test replaces the testghost%i attribute with testuser%i */
        4: 3192:    ghostname_del = talloc_asprintf(data, "testuser%d", _i - 1);
        4: 3193:    fail_unless(ghostname_del != NULL, "Out of memory\n");
        -: 3194:
        4: 3195:    ghostname_add = talloc_asprintf(data, "testuser%d", _i - 1);
        4: 3196:    fail_unless(ghostname_add != NULL, "Out of memory\n");
        4: 3197:    ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
        4: 3198:    fail_unless(ret == EOK, "Cannot add attr\n");
        -: 3199:
        4: 3200:    data->attrlist = talloc_array(data, const char *, 2);
        4: 3201:    fail_unless(data->attrlist != NULL, "talloc_array failed.");
        4: 3202:    data->attrlist[0] = SYSDB_GHOST;
        4: 3203:    data->attrlist[1] = NULL;
        -: 3204:
        -: 3205:    /* Before the replace, the group has the testghost%_i as a member */
        8: 3206:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        4: 3207:                                    test_ctx->domain,
        -: 3208:                                    data->gid,
        -: 3209:                                    data->attrlist, &data->msg);
        4: 3210:    fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 3211:            (unsigned long long) data->gid);
        -: 3212:
        4: 3213:    gv.data = (uint8_t *) ghostname_del;
        4: 3214:    gv.length = strlen(ghostname_del);
        -: 3215:
        4: 3216:    el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
        4: 3217:    fail_if(el == NULL, "Cannot find ghost element\n");
        -: 3218:
        4: 3219:    test_gv = ldb_msg_find_val(el, &gv);
        4: 3220:    fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
        -: 3221:
        -: 3222:    /* Perform the replace operation */
        4: 3223:    ret =  sysdb_set_group_attr(test_ctx->sysdb, test_ctx->domain,
        -: 3224:                                data->groupname, data->attrs, SYSDB_MOD_REP);
        4: 3225:    fail_unless(ret == EOK, "Cannot set group attrs\n");
        -: 3226:
        -: 3227:    /* After the replace, the group has the testghost%_i as a member */
        8: 3228:    ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
        4: 3229:                                    test_ctx->domain,
        -: 3230:                                    data->gid,
        -: 3231:                                    data->attrlist, &data->msg);
        4: 3232:    fail_if(ret != EOK, "Cannot retrieve group %llu\n",
        -: 3233:            (unsigned long long) data->gid);
        -: 3234:
        4: 3235:    gv.data = (uint8_t *) ghostname_add;
        4: 3236:    gv.length = strlen(ghostname_add);
        -: 3237:
        4: 3238:    el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
        4: 3239:    fail_if(el == NULL, "Cannot find ghost element\n");
        -: 3240:
        4: 3241:    test_gv = ldb_msg_find_val(el, &gv);
        4: 3242:    fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
        -: 3243:}
        -: 3244:END_TEST
        -: 3245:
        5: 3246:START_TEST (test_sysdb_memberof_user_cleanup)
        -: 3247:{
        -: 3248:    struct sysdb_test_ctx *test_ctx;
        -: 3249:    struct test_data *data;
        -: 3250:    int ret;
        -: 3251:
        -: 3252:    /* Setup */
        5: 3253:    ret = setup_sysdb_tests(&test_ctx);
        5: 3254:    if (ret != EOK) {
    #####: 3255:        fail("Could not set up the test");
        5: 3256:        return;
        -: 3257:    }
        -: 3258:
        5: 3259:    data = talloc_zero(test_ctx, struct test_data);
        5: 3260:    data->ctx = test_ctx;
        5: 3261:    data->ev = test_ctx->ev;
        5: 3262:    data->uid = _i * 2;
        -: 3263:
        5: 3264:    ret = test_remove_user_by_uid(data);
        -: 3265:
        5: 3266:    fail_if(ret != EOK, "Could not remove user with uid %d", _i);
        5: 3267:    talloc_free(test_ctx);
        -: 3268:}
        -: 3269:END_TEST
        -: 3270:
        1: 3271:START_TEST (test_sysdb_attrs_to_list)
        -: 3272:{
        -: 3273:    struct sysdb_attrs *attrs_list[3];
        -: 3274:    char **list;
        -: 3275:    errno_t ret;
        -: 3276:
        1: 3277:    TALLOC_CTX *test_ctx = talloc_new(NULL);
        -: 3278:
        1: 3279:    attrs_list[0] = sysdb_new_attrs(test_ctx);
        1: 3280:    ret = sysdb_attrs_add_string(attrs_list[0], "test_attr", "attr1");
        1: 3281:    fail_if(ret, "Add string failed");
        1: 3282:    attrs_list[1] = sysdb_new_attrs(test_ctx);
        1: 3283:    ret = sysdb_attrs_add_string(attrs_list[1], "test_attr", "attr2");
        1: 3284:    fail_if(ret, "Add string failed");
        1: 3285:    attrs_list[2] = sysdb_new_attrs(test_ctx);
        1: 3286:    ret = sysdb_attrs_add_string(attrs_list[2], "nottest_attr", "attr3");
        1: 3287:    fail_if(ret, "Add string failed");
        -: 3288:
        1: 3289:    ret = sysdb_attrs_to_list(test_ctx, attrs_list, 3,
        -: 3290:                              "test_attr", &list);
        1: 3291:    fail_unless(ret == EOK, "sysdb_attrs_to_list failed with code %d", ret);
        -: 3292:
        1: 3293:    fail_unless(strcmp(list[0],"attr1") == 0, "Expected [attr1], got [%s]",
        -: 3294:                                              list[0]);
        1: 3295:    fail_unless(strcmp(list[1],"attr2") == 0, "Expected [attr2], got [%s]",
        -: 3296:                                              list[1]);
        1: 3297:    fail_unless(list[2] == NULL, "List should be NULL-terminated");
        -: 3298:
        1: 3299:    talloc_free(test_ctx);
        -: 3300:}
        1: 3301:END_TEST
        -: 3302:
        1: 3303:START_TEST(test_group_rename)
        -: 3304:{
        -: 3305:    struct sysdb_test_ctx *test_ctx;
        -: 3306:    errno_t ret;
        -: 3307:    gid_t gid;
        1: 3308:    const gid_t grgid = 38001;
        -: 3309:    const char *name;
        1: 3310:    const char *fromname = "fromgroup";
        1: 3311:    const char *toname = "togroup";
        -: 3312:    struct ldb_result *res;
        -: 3313:
        -: 3314:    /* Setup */
        1: 3315:    ret = setup_sysdb_tests(&test_ctx);
        1: 3316:    fail_unless(ret == EOK, "Could not set up the test");
        -: 3317:
        -: 3318:    /* Store and verify the first group */
        1: 3319:    ret = sysdb_store_group(test_ctx->sysdb, test_ctx->domain,
        -: 3320:                            fromname, grgid, NULL, 0, 0);
        1: 3321:    fail_unless(ret == EOK, "Could not add first group");
        -: 3322:
        1: 3323:    ret = sysdb_getgrnam(test_ctx, test_ctx->sysdb,
        1: 3324:                         test_ctx->domain, fromname, &res);
        1: 3325:    fail_unless(ret == EOK, "Could not retrieve the group from cache\n");
        1: 3326:    if (res->count != 1) {
    #####: 3327:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####: 3328:        goto done;
        -: 3329:    }
        -: 3330:
        1: 3331:    gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
        1: 3332:    fail_unless(gid == grgid,
        -: 3333:                "Did not find the expected GID (found %llu expected %llu)",
        -: 3334:                (unsigned long long) gid, (unsigned long long) grgid);
        1: 3335:    name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3336:    fail_unless(strcmp(fromname, name) == 0,
        -: 3337:                "Did not find the expected name (found %s expected %s)",
        -: 3338:                name, fromname);
        -: 3339:
        -: 3340:    /* Perform rename and check that GID is the same, but name changed */
        1: 3341:    ret = sysdb_add_group(test_ctx->sysdb, test_ctx->domain,
        -: 3342:                          toname, grgid, NULL, 0, 0);
        1: 3343:    fail_unless(ret == EEXIST, "Group renamed with a low level call?");
        -: 3344:
        1: 3345:    ret = sysdb_store_group(test_ctx->sysdb, test_ctx->domain,
        -: 3346:                            toname, grgid, NULL, 0, 0);
        1: 3347:    fail_unless(ret == EOK, "Could not add first group");
        -: 3348:
        1: 3349:    ret = sysdb_getgrnam(test_ctx, test_ctx->sysdb,
        1: 3350:                         test_ctx->domain, toname, &res);
        1: 3351:    fail_unless(ret == EOK, "Could not retrieve the group from cache\n");
        1: 3352:    if (res->count != 1) {
    #####: 3353:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####: 3354:        goto done;
        -: 3355:    }
        -: 3356:
        1: 3357:    gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
        1: 3358:    fail_unless(gid == grgid,
        -: 3359:                "Did not find the expected GID (found %llu expected %llu)",
        -: 3360:                (unsigned long long) gid, (unsigned long long) grgid);
        1: 3361:    name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3362:    fail_unless(strcmp(toname, name) == 0,
        -: 3363:                "Did not find the expected GID (found %s expected %s)",
        -: 3364:                name, toname);
        -: 3365:
        -: 3366:    /* Verify the first name is gone */
        1: 3367:    ret = sysdb_getgrnam(test_ctx, test_ctx->sysdb,
        1: 3368:                         test_ctx->domain, fromname, &res);
        1: 3369:    fail_unless(ret == EOK, "Could not retrieve the group from cache\n");
        1: 3370:    fail_unless(res->count == 0, "Unexpectedly found the original user\n");
        -: 3371:
        -: 3372:done:
        1: 3373:    talloc_free(test_ctx);
        -: 3374:}
        1: 3375:END_TEST
        -: 3376:
        1: 3377:START_TEST(test_user_rename)
        -: 3378:{
        -: 3379:    struct sysdb_test_ctx *test_ctx;
        -: 3380:    errno_t ret;
        -: 3381:    uid_t uid;
        1: 3382:    const uid_t userid = 38002;
        -: 3383:    const char *name;
        1: 3384:    const char *fromname = "fromuser";
        1: 3385:    const char *toname = "touser";
        -: 3386:    struct ldb_result *res;
        -: 3387:
        -: 3388:    /* Setup */
        1: 3389:    ret = setup_sysdb_tests(&test_ctx);
        1: 3390:    fail_unless(ret == EOK, "Could not set up the test");
        -: 3391:
        -: 3392:    /* Store and verify the first user */
        1: 3393:    ret = sysdb_store_user(test_ctx->sysdb, test_ctx->domain,
        -: 3394:                           fromname, NULL, userid, 0,
        -: 3395:                           fromname, "/", "/bin/sh",
        -: 3396:                           NULL, NULL, NULL, 0, 0);
        1: 3397:    fail_unless(ret == EOK, "Could not add first user");
        -: 3398:
        1: 3399:    ret = sysdb_getpwnam(test_ctx, test_ctx->sysdb,
        1: 3400:                         test_ctx->domain, fromname, &res);
        1: 3401:    fail_unless(ret == EOK, "Could not retrieve the user from cache\n");
        1: 3402:    if (res->count != 1) {
    #####: 3403:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####: 3404:        goto done;
        -: 3405:    }
        -: 3406:
        1: 3407:    uid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_UIDNUM, 0);
        1: 3408:    fail_unless(uid == userid,
        -: 3409:                "Did not find the expected UID (found %llu expected %llu)",
        -: 3410:                (unsigned long long) uid, (unsigned long long) userid);
        1: 3411:    name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3412:    fail_unless(strcmp(fromname, name) == 0,
        -: 3413:                "Did not find the expected name (found %s expected %s)",
        -: 3414:                name, fromname);
        -: 3415:
        -: 3416:    /* Perform rename and check that GID is the same, but name changed */
        1: 3417:    ret = sysdb_add_user(test_ctx->sysdb, test_ctx->domain, toname, userid, 0,
        -: 3418:                         fromname, "/", "/bin/sh", NULL, NULL, 0, 0);
        1: 3419:    fail_unless(ret == EEXIST, "A second user added with low level call?");
        -: 3420:
        1: 3421:    ret = sysdb_store_user(test_ctx->sysdb, test_ctx->domain, toname, NULL,
        -: 3422:                           userid, 0, fromname, "/", "/bin/sh",
        -: 3423:                           NULL, NULL, NULL, 0, 0);
        1: 3424:    fail_unless(ret == EOK, "Could not add second user");
        -: 3425:
        1: 3426:    ret = sysdb_getpwnam(test_ctx, test_ctx->sysdb,
        1: 3427:                         test_ctx->domain, toname, &res);
        1: 3428:    fail_unless(ret == EOK, "Could not retrieve the user from cache\n");
        1: 3429:    if (res->count != 1) {
    #####: 3430:        fail("Invalid number of replies. Expected 1, got %d", res->count);
    #####: 3431:        goto done;
        -: 3432:    }
        -: 3433:
        1: 3434:    uid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_UIDNUM, 0);
        1: 3435:    fail_unless(uid == userid,
        -: 3436:                "Did not find the expected UID (found %llu expected %llu)",
        -: 3437:                (unsigned long long) uid, (unsigned long long) userid);
        1: 3438:    name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3439:    fail_unless(strcmp(toname, name) == 0,
        -: 3440:                "Did not find the expected name (found %s expected %s)",
        -: 3441:                name, fromname);
        -: 3442:
        -: 3443:    /* Verify the first name is gone */
        1: 3444:    ret = sysdb_getpwnam(test_ctx, test_ctx->sysdb,
        1: 3445:                         test_ctx->domain, fromname, &res);
        1: 3446:    fail_unless(ret == EOK, "Could not retrieve the user from cache\n");
        1: 3447:    fail_unless(res->count == 0, "Unexpectedly found the original user\n");
        -: 3448:
        -: 3449:done:
        1: 3450:    talloc_free(test_ctx);
        -: 3451:}
        1: 3452:END_TEST
        -: 3453:
        1: 3454:START_TEST (test_sysdb_update_members)
        -: 3455:{
        -: 3456:    struct sysdb_test_ctx *test_ctx;
        -: 3457:    char **add_groups;
        -: 3458:    char **del_groups;
        1: 3459:    const char *user = "testuser27000";
        -: 3460:    errno_t ret;
        -: 3461:
        -: 3462:    /* Setup */
        1: 3463:    ret = setup_sysdb_tests(&test_ctx);
        1: 3464:    fail_unless(ret == EOK, "Could not set up the test");
        -: 3465:
        -: 3466:    /* Add a user to two groups */
        1: 3467:    add_groups = talloc_array(test_ctx, char *, 3);
        1: 3468:    add_groups[0] = talloc_strdup(add_groups, "testgroup28001");
        1: 3469:    add_groups[1] = talloc_strdup(add_groups, "testgroup28002");
        1: 3470:    add_groups[2] = NULL;
        -: 3471:
        1: 3472:    ret = sysdb_update_members(test_ctx->sysdb, test_ctx->domain,
        -: 3473:                               user, SYSDB_MEMBER_USER,
        -: 3474:                               (const char *const *)add_groups, NULL);
        1: 3475:    fail_unless(ret == EOK, "Could not add groups");
        1: 3476:    talloc_zfree(add_groups);
        -: 3477:
        -: 3478:    /* Remove a user from one group and add to another */
        1: 3479:    del_groups = talloc_array(test_ctx, char *, 2);
        1: 3480:    del_groups[0] = talloc_strdup(del_groups, "testgroup28001");
        1: 3481:    del_groups[1] = NULL;
        1: 3482:    add_groups = talloc_array(test_ctx, char *, 2);
        1: 3483:    add_groups[0] = talloc_strdup(add_groups, "testgroup28003");
        1: 3484:    add_groups[1] = NULL;
        -: 3485:
        1: 3486:    ret = sysdb_update_members(test_ctx->sysdb, test_ctx->domain,
        -: 3487:                               user, SYSDB_MEMBER_USER,
        -: 3488:                               (const char *const *)add_groups,
        -: 3489:                               (const char *const *)del_groups);
        1: 3490:    fail_unless(ret == EOK, "Group replace failed");
        1: 3491:    talloc_zfree(add_groups);
        1: 3492:    talloc_zfree(del_groups);
        -: 3493:
        -: 3494:    /* Remove a user from two groups */
        1: 3495:    del_groups = talloc_array(test_ctx, char *, 3);
        1: 3496:    del_groups[0] = talloc_strdup(del_groups, "testgroup28002");
        1: 3497:    del_groups[1] = talloc_strdup(del_groups, "testgroup28003");
        1: 3498:    del_groups[2] = NULL;
        -: 3499:
        1: 3500:    ret = sysdb_update_members(test_ctx->sysdb, test_ctx->domain,
        -: 3501:                               user, SYSDB_MEMBER_USER,
        -: 3502:                               NULL, (const char *const *)del_groups);
        1: 3503:    fail_unless(ret == EOK, "Could not remove groups");
        -: 3504:
        1: 3505:    talloc_zfree(test_ctx);
        -: 3506:}
        1: 3507:END_TEST
        -: 3508:
        -: 3509:
       10: 3510:START_TEST (test_sysdb_group_dn_name)
        -: 3511:{
        -: 3512:    struct sysdb_test_ctx *test_ctx;
        -: 3513:    int ret;
        -: 3514:    struct ldb_dn *group_dn;
        -: 3515:    const char *groupname;
        -: 3516:    char *parsed;
        -: 3517:
        -: 3518:    /* Setup */
       10: 3519:    ret = setup_sysdb_tests(&test_ctx);
       10: 3520:    if (ret != EOK) {
    #####: 3521:        fail("Could not set up the test");
        -: 3522:        return;
        -: 3523:    }
        -: 3524:
       10: 3525:    groupname = talloc_asprintf(test_ctx, "testgroup%d", _i);
       10: 3526:    group_dn = sysdb_group_dn(test_ctx->sysdb, test_ctx,
       10: 3527:                              test_ctx->domain, groupname);
       10: 3528:    if (!group_dn || !groupname) {
    #####: 3529:        fail("Out of memory");
        -: 3530:        return;
        -: 3531:    }
        -: 3532:
       10: 3533:    ret = sysdb_group_dn_name(test_ctx->sysdb, test_ctx,
        -: 3534:                              ldb_dn_get_linearized(group_dn), &parsed);
       10: 3535:    fail_if(ret != EOK, "Cannot get the group name from DN");
        -: 3536:
       10: 3537:    fail_if(strcmp(groupname, parsed) != 0,
        -: 3538:            "Names don't match (got %s)", parsed);
       10: 3539:    talloc_free(test_ctx);
        -: 3540:}
        -: 3541:END_TEST
        -: 3542:
       10: 3543:START_TEST (test_sysdb_add_basic_netgroup)
        -: 3544:{
        -: 3545:    struct sysdb_test_ctx *test_ctx;
        -: 3546:    struct test_data *data;
        -: 3547:    int ret;
        -: 3548:
        -: 3549:    /* Setup */
       10: 3550:    ret = setup_sysdb_tests(&test_ctx);
       10: 3551:    if (ret != EOK) {
    #####: 3552:        fail("Could not set up the test");
       10: 3553:        return;
        -: 3554:    }
        -: 3555:
       10: 3556:    data = talloc_zero(test_ctx, struct test_data);
       10: 3557:    data->ctx = test_ctx;
       10: 3558:    data->ev = test_ctx->ev;
       10: 3559:    data->uid = _i;         /* This is kinda abuse of uid, though */
       10: 3560:    data->netgrname = talloc_asprintf(data, "testnetgr%d", _i);
        -: 3561:
       10: 3562:    ret = test_add_basic_netgroup(data);
        -: 3563:
       10: 3564:    fail_if(ret != EOK, "Could not add netgroup %s", data->netgrname);
       10: 3565:    talloc_free(test_ctx);
        -: 3566:}
        -: 3567:END_TEST
        -: 3568:
       10: 3569:START_TEST (test_sysdb_search_netgroup_by_name)
        -: 3570:{
        -: 3571:    struct sysdb_test_ctx *test_ctx;
        -: 3572:    int ret;
        -: 3573:    const char *netgrname;
        -: 3574:    struct ldb_message *msg;
        -: 3575:    struct ldb_dn *netgroup_dn;
        -: 3576:
        -: 3577:    /* Setup */
       10: 3578:    ret = setup_sysdb_tests(&test_ctx);
       10: 3579:    if (ret != EOK) {
    #####: 3580:        fail("Could not set up the test");
       10: 3581:        return;
        -: 3582:    }
        -: 3583:
       10: 3584:    netgrname = talloc_asprintf(test_ctx, "testnetgr%d", _i);
        -: 3585:
       10: 3586:    ret = sysdb_search_netgroup_by_name(test_ctx, test_ctx->sysdb,
       10: 3587:                                        test_ctx->domain,
        -: 3588:                                        netgrname, NULL, &msg);
       10: 3589:    fail_if(ret != EOK, "Could not find netgroup with name %s", netgrname);
        -: 3590:
       10: 3591:    netgroup_dn = sysdb_netgroup_dn(test_ctx->sysdb, test_ctx,
       10: 3592:                                    test_ctx->domain, netgrname);
       10: 3593:    fail_if(netgroup_dn == NULL);
       10: 3594:    fail_if(ldb_dn_compare(msg->dn, netgroup_dn) != 0, "Found wrong netgroup!\n");
       10: 3595:    talloc_free(test_ctx);
        -: 3596:}
        -: 3597:END_TEST
        -: 3598:
        5: 3599:START_TEST (test_sysdb_remove_netgroup_entry)
        -: 3600:{
        -: 3601:    struct sysdb_test_ctx *test_ctx;
        -: 3602:    struct test_data *data;
        -: 3603:    int ret;
        -: 3604:
        -: 3605:    /* Setup */
        5: 3606:    ret = setup_sysdb_tests(&test_ctx);
        5: 3607:    if (ret != EOK) {
    #####: 3608:        fail("Could not set up the test");
        5: 3609:        return;
        -: 3610:    }
        -: 3611:
        5: 3612:    data = talloc_zero(test_ctx, struct test_data);
        5: 3613:    data->ctx = test_ctx;
        5: 3614:    data->ev = test_ctx->ev;
        5: 3615:    data->netgrname = talloc_asprintf(data, "testnetgr%d", _i);
        -: 3616:
        5: 3617:    ret = test_remove_netgroup_entry(data);
        -: 3618:
        5: 3619:    fail_if(ret != EOK, "Could not remove netgroup %s", data->netgrname);
        5: 3620:    talloc_free(test_ctx);
        -: 3621:}
        -: 3622:END_TEST
        -: 3623:
        5: 3624:START_TEST (test_sysdb_remove_netgroup_by_name)
        -: 3625:{
        -: 3626:    struct sysdb_test_ctx *test_ctx;
        -: 3627:    struct test_data *data;
        -: 3628:    int ret;
        -: 3629:
        -: 3630:    /* Setup */
        5: 3631:    ret = setup_sysdb_tests(&test_ctx);
        5: 3632:    if (ret != EOK) {
    #####: 3633:        fail("Could not set up the test");
        5: 3634:        return;
        -: 3635:    }
        -: 3636:
        5: 3637:    data = talloc_zero(test_ctx, struct test_data);
        5: 3638:    data->ctx = test_ctx;
        5: 3639:    data->ev = test_ctx->ev;
        5: 3640:    data->netgrname = talloc_asprintf(data, "testnetgr%d", _i);
        -: 3641:
        5: 3642:    ret = test_remove_netgroup_by_name(data);
        -: 3643:
        5: 3644:    fail_if(ret != EOK, "Could not remove netgroup with name %s", data->netgrname);
        5: 3645:    talloc_free(test_ctx);
        -: 3646:}
        -: 3647:END_TEST
        -: 3648:
       10: 3649:START_TEST (test_sysdb_set_netgroup_attr)
        -: 3650:{
        -: 3651:    struct sysdb_test_ctx *test_ctx;
        -: 3652:    struct test_data *data;
        -: 3653:    int ret;
        -: 3654:
        -: 3655:    /* Setup */
       10: 3656:    ret = setup_sysdb_tests(&test_ctx);
       10: 3657:    if (ret != EOK) {
    #####: 3658:        fail("Could not set up the test");
       10: 3659:        return;
        -: 3660:    }
        -: 3661:
       10: 3662:    data = talloc_zero(test_ctx, struct test_data);
       10: 3663:    data->ctx = test_ctx;
       10: 3664:    data->ev = test_ctx->ev;
       10: 3665:    data->uid = _i;         /* This is kinda abuse of uid, though */
       10: 3666:    data->netgrname = talloc_asprintf(data, "testnetgr%d", _i);
        -: 3667:
       10: 3668:    ret = test_set_netgroup_attr(data);
        -: 3669:
       10: 3670:    fail_if(ret != EOK, "Could not set netgroup attribute %s", data->netgrname);
       10: 3671:    talloc_free(test_ctx);
        -: 3672:}
        -: 3673:END_TEST
        -: 3674:
       10: 3675:START_TEST (test_sysdb_get_netgroup_attr)
        -: 3676:{
        -: 3677:    struct sysdb_test_ctx *test_ctx;
        -: 3678:    int ret;
        -: 3679:    const char *description;
        -: 3680:    const char *netgrname;
        -: 3681:    struct ldb_result *res;
       10: 3682:    const char *attrs[] = { SYSDB_DESCRIPTION, NULL };
        -: 3683:    const char *attrval;
        -: 3684:
        -: 3685:    /* Setup */
       10: 3686:    ret = setup_sysdb_tests(&test_ctx);
       10: 3687:    if (ret != EOK) {
    #####: 3688:        fail("Could not set up the test");
       10: 3689:        return;
        -: 3690:    }
        -: 3691:
       10: 3692:    description = talloc_asprintf(test_ctx, "Sysdb Netgroup %d", _i);
       10: 3693:    netgrname = talloc_asprintf(test_ctx, "testnetgr%d", _i);
        -: 3694:
       10: 3695:    ret = sysdb_get_netgroup_attr(test_ctx, test_ctx->sysdb,
       10: 3696:                                  test_ctx->domain, netgrname, attrs, &res);
        -: 3697:
       10: 3698:    fail_if(ret != EOK, "Could not get netgroup attributes");
       10: 3699:    fail_if(res->count != 1,
        -: 3700:            "Invalid number of entries, expected 1, got %d", res->count);
        -: 3701:
       10: 3702:    attrval = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_DESCRIPTION, 0);
       10: 3703:    fail_if(strcmp(attrval, description),
        -: 3704:            "Got bad attribute value for netgroup %s", netgrname);
       10: 3705:    talloc_free(test_ctx);
        -: 3706:}
        -: 3707:END_TEST
        -: 3708:
        1: 3709:START_TEST(test_odd_characters)
        -: 3710:{
        -: 3711:    errno_t ret;
        -: 3712:    struct sysdb_test_ctx *test_ctx;
        -: 3713:    struct ldb_result *res;
        -: 3714:    struct ldb_message *msg;
        -: 3715:    const struct ldb_val *val;
        1: 3716:    const char odd_username[] = "*(odd)\\user,name";
        1: 3717:    const char odd_groupname[] = "*(odd\\*)\\group,name";
        1: 3718:    const char odd_netgroupname[] = "*(odd\\*)\\netgroup,name";
        -: 3719:    const char *received_user;
        -: 3720:    const char *received_group;
        -: 3721:    static const char *user_attrs[] = SYSDB_PW_ATTRS;
        -: 3722:    static const char *netgr_attrs[] = SYSDB_NETGR_ATTRS;
        -: 3723:
        -: 3724:    /* Setup */
        1: 3725:    ret = setup_sysdb_tests(&test_ctx);
        1: 3726:    if (ret != EOK) {
    #####: 3727:        fail("Could not set up the test");
        1: 3728:        return;
        -: 3729:    }
        -: 3730:
        -: 3731:    /* ===== Groups ===== */
        -: 3732:
        -: 3733:    /* Add */
        1: 3734:    ret = sysdb_add_incomplete_group(test_ctx->sysdb, test_ctx->domain,
        -: 3735:                                     odd_groupname, 20000, NULL, true, 0);
        1: 3736:    fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
        -: 3737:                            ret, strerror(ret));
        -: 3738:
        -: 3739:    /* Retrieve */
        1: 3740:    ret = sysdb_search_group_by_name(test_ctx, test_ctx->sysdb,
        1: 3741:                                     test_ctx->domain,
        -: 3742:                                     odd_groupname, NULL, &msg);
        1: 3743:    fail_unless(ret == EOK, "sysdb_search_group_by_name error [%d][%s]",
        -: 3744:                            ret, strerror(ret));
        1: 3745:    talloc_zfree(msg);
        -: 3746:
        1: 3747:    ret = sysdb_getgrnam(test_ctx, test_ctx->sysdb,
        1: 3748:                         test_ctx->domain, odd_groupname, &res);
        1: 3749:    fail_unless(ret == EOK, "sysdb_getgrnam error [%d][%s]",
        -: 3750:                            ret, strerror(ret));
        1: 3751:    fail_unless(res->count == 1, "Received [%d] responses",
        -: 3752:                                 res->count);
        1: 3753:    received_group = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3754:    fail_unless(strcmp(received_group, odd_groupname) == 0,
        -: 3755:                "Expected [%s], got [%s]",
        -: 3756:                odd_groupname, received_group);
        1: 3757:    talloc_free(res);
        -: 3758:
        -: 3759:
        -: 3760:    /* ===== Users ===== */
        -: 3761:
        -: 3762:    /* Add */
        1: 3763:    ret = sysdb_add_basic_user(test_ctx->sysdb,
        1: 3764:                               test_ctx->domain,
        -: 3765:                               odd_username,
        -: 3766:                               10000, 10000,
        -: 3767:                               "","","");
        1: 3768:    fail_unless(ret == EOK, "sysdb_add_basic_user error [%d][%s]",
        -: 3769:                            ret, strerror(ret));
        -: 3770:
        -: 3771:    /* Retrieve */
        2: 3772:    ret = sysdb_search_user_by_name(test_ctx,
        2: 3773:                                    test_ctx->sysdb, test_ctx->domain,
        -: 3774:                                    odd_username, NULL, &msg);
        1: 3775:    fail_unless(ret == EOK, "sysdb_search_user_by_name error [%d][%s]",
        -: 3776:                            ret, strerror(ret));
        1: 3777:    val = ldb_dn_get_component_val(msg->dn, 0);
        1: 3778:    fail_unless(strcmp((char *)val->data, odd_username)==0,
        -: 3779:                "Expected [%s] got [%s]\n",
        -: 3780:                odd_username, (char *)val->data);
        1: 3781:    talloc_zfree(msg);
        -: 3782:
        -: 3783:    /* Add to the group */
        1: 3784:    ret = sysdb_add_group_member(test_ctx->sysdb, test_ctx->domain,
        -: 3785:                                 odd_groupname, odd_username,
        -: 3786:                                 SYSDB_MEMBER_USER);
        1: 3787:    fail_unless(ret == EOK, "sysdb_add_group_member error [%d][%s]",
        -: 3788:                            ret, strerror(ret));
        -: 3789:
        1: 3790:    ret = sysdb_getpwnam(test_ctx, test_ctx->sysdb,
        1: 3791:                         test_ctx->domain, odd_username, &res);
        1: 3792:    fail_unless(ret == EOK, "sysdb_getpwnam error [%d][%s]",
        -: 3793:                            ret, strerror(ret));
        1: 3794:    fail_unless(res->count == 1, "Received [%d] responses",
        -: 3795:                                 res->count);
        1: 3796:    received_user = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        1: 3797:    fail_unless(strcmp(received_user, odd_username) == 0,
        -: 3798:                "Expected [%s], got [%s]",
        -: 3799:                odd_username, received_user);
        1: 3800:    talloc_zfree(res);
        -: 3801:
        -: 3802:    /* Attributes */
        1: 3803:    ret = sysdb_get_user_attr(test_ctx, test_ctx->sysdb, test_ctx->domain,
        -: 3804:                              odd_username, user_attrs, &res);
        1: 3805:    fail_unless(ret == EOK, "sysdb_get_user_attr error [%d][%s]",
        -: 3806:                            ret, strerror(ret));
        1: 3807:    talloc_free(res);
        -: 3808:
        -: 3809:    /* Delete User */
        1: 3810:    ret = sysdb_delete_user(test_ctx->sysdb, test_ctx->domain,
        -: 3811:                            odd_username, 10000);
        1: 3812:    fail_unless(ret == EOK, "sysdb_delete_user error [%d][%s]",
        -: 3813:                            ret, strerror(ret));
        -: 3814:
        -: 3815:
        -: 3816:    /* Delete Group */
        1: 3817:    ret = sysdb_delete_group(test_ctx->sysdb, test_ctx->domain,
        -: 3818:                             odd_groupname, 20000);
        1: 3819:    fail_unless(ret == EOK, "sysdb_delete_group error [%d][%s]",
        -: 3820:                            ret, strerror(ret));
        -: 3821:
        -: 3822:    /* ===== Netgroups ===== */
        -: 3823:    /* Add */
        1: 3824:    ret = sysdb_add_netgroup(test_ctx->sysdb, test_ctx->domain,
        -: 3825:                             odd_netgroupname, "No description",
        -: 3826:                             NULL, NULL, 30, 0);
        1: 3827:    fail_unless(ret == EOK, "sysdb_add_netgroup error [%d][%s]",
        -: 3828:                            ret, strerror(ret));
        -: 3829:
        -: 3830:    /* Retrieve */
        1: 3831:    ret = sysdb_getnetgr(test_ctx, test_ctx->sysdb,
        1: 3832:                         test_ctx->domain, odd_netgroupname, &res);
        1: 3833:    fail_unless(ret == EOK, "sysdb_getnetgr error [%d][%s]",
        -: 3834:                            ret, strerror(ret));
        1: 3835:    fail_unless(res->count == 1, "Received [%d] responses",
        -: 3836:                                 res->count);
        1: 3837:    talloc_zfree(res);
        -: 3838:
        1: 3839:    ret = sysdb_get_netgroup_attr(test_ctx, test_ctx->sysdb, test_ctx->domain,
        -: 3840:                                  odd_netgroupname, netgr_attrs, &res);
        1: 3841:    fail_unless(ret == EOK, "sysdb_get_netgroup_attr error [%d][%s]",
        -: 3842:                            ret, strerror(ret));
        1: 3843:    fail_unless(res->count == 1, "Received [%d] responses",
        -: 3844:                                 res->count);
        1: 3845:    talloc_zfree(res);
        -: 3846:
        -: 3847:    /* ===== Arbitrary Entries ===== */
        -: 3848:
        1: 3849:    talloc_free(test_ctx);
        -: 3850:}
        -: 3851:END_TEST
        -: 3852:
        -: 3853:/* == SERVICE TESTS == */
       12: 3854:void services_check_match(struct sysdb_test_ctx *test_ctx,
        -: 3855:                          bool by_name,
        -: 3856:                          const char *primary_name,
        -: 3857:                          int port,
        -: 3858:                          const char **aliases,
        -: 3859:                          const char **protocols)
        -: 3860:{
        -: 3861:    errno_t ret;
        -: 3862:    unsigned int i, j;
        -: 3863:    bool matched;
        -: 3864:    const char *ret_name;
        -: 3865:    int ret_port;
        -: 3866:    struct ldb_result *res;
        -: 3867:    struct ldb_message *msg;
        -: 3868:    struct ldb_message_element *el;
        -: 3869:
       12: 3870:    if (by_name) {
        -: 3871:        /* Look up the service by name */
        6: 3872:        ret = sysdb_getservbyname(test_ctx, test_ctx->sysdb,
        -: 3873:                                  test_ctx->domain, primary_name,
        -: 3874:                                  NULL, &res);
        6: 3875:        fail_if(ret != EOK, "sysdb_getservbyname error [%s]\n",
        -: 3876:                             strerror(ret));
        -: 3877:    } else {
        -: 3878:        /* Look up the newly-added service by port */
        6: 3879:        ret = sysdb_getservbyport(test_ctx, test_ctx->sysdb,
        -: 3880:                                  test_ctx->domain, port, NULL, &res);
        6: 3881:        fail_if(ret != EOK, "sysdb_getservbyport error [%s]\n",
        -: 3882:                             strerror(ret));
        -: 3883:    }
       12: 3884:    fail_if(res == NULL, "ENOMEM");
       12: 3885:    fail_if(res->count != 1);
        -: 3886:
        -: 3887:    /* Make sure the returned entry matches */
       12: 3888:    msg = res->msgs[0];
       12: 3889:    ret_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
       12: 3890:    fail_if(ret_name == NULL);
       12: 3891:    fail_unless(strcmp(ret_name, primary_name) == 0);
        -: 3892:
       12: 3893:    ret_port = ldb_msg_find_attr_as_int(msg, SYSDB_SVC_PORT, 0);
       12: 3894:    fail_if (ret_port != port);
        -: 3895:
       12: 3896:    el = ldb_msg_find_element(msg, SYSDB_NAME_ALIAS);
       34: 3897:    for (i = 0; i < el->num_values; i++) {
       22: 3898:        matched = false;
       64: 3899:        for (j = 0; aliases[j]; j++) {
       42: 3900:            if (strcmp(aliases[j], (const char *)el->values[i].data) == 0) {
       22: 3901:                matched = true;
        -: 3902:            }
        -: 3903:        }
       22: 3904:        fail_if(!matched, "Unexpected value in LDB entry: [%s]",
        -: 3905:                (const char *)el->values[i].data);
        -: 3906:    }
        -: 3907:
       12: 3908:    el = ldb_msg_find_element(msg, SYSDB_SVC_PROTO);
       36: 3909:    for (i = 0; i < el->num_values; i++) {
       24: 3910:        matched = false;
       72: 3911:        for (j = 0; protocols[j]; j++) {
       48: 3912:            if (strcmp(protocols[j], (const char *)el->values[i].data) == 0) {
       24: 3913:                matched = true;
        -: 3914:            }
        -: 3915:        }
       24: 3916:        fail_if(!matched, "Unexpected value in LDB entry: [%s]",
        -: 3917:                (const char *)el->values[i].data);
        -: 3918:    }
       12: 3919:}
        -: 3920:
        -: 3921:#define services_check_match_name(test_ctx, primary_name, port, aliases, protocols) \
        -: 3922:    do { \
        -: 3923:        services_check_match(test_ctx, true, primary_name, port, aliases, protocols); \
        -: 3924:    } while(0);
        -: 3925:
        -: 3926:#define services_check_match_port(test_ctx, primary_name, port, aliases, protocols) \
        -: 3927:    do { \
        -: 3928:        services_check_match(test_ctx, false, primary_name, port, aliases, protocols); \
        -: 3929:    } while(0);
        -: 3930:
        1: 3931:START_TEST(test_sysdb_add_services)
        -: 3932:{
        -: 3933:    errno_t ret;
        -: 3934:    struct sysdb_test_ctx *test_ctx;
        -: 3935:    char *primary_name;
        -: 3936:    const char **aliases;
        -: 3937:    const char **protocols;
        1: 3938:    int port = 3890;
        -: 3939:
        -: 3940:    /* Setup */
        1: 3941:    ret = setup_sysdb_tests(&test_ctx);
        1: 3942:    fail_if(ret != EOK, "Could not set up the test");
        -: 3943:
        1: 3944:    primary_name = talloc_asprintf(test_ctx, "test_service");
        1: 3945:    fail_if(primary_name == NULL);
        -: 3946:
        1: 3947:    aliases = talloc_array(test_ctx, const char *, 3);
        1: 3948:    fail_if(aliases == NULL);
        -: 3949:
        1: 3950:    aliases[0] = talloc_asprintf(aliases, "test_service_alias1");
        1: 3951:    fail_if(aliases[0] == NULL);
        -: 3952:
        1: 3953:    aliases[1] = talloc_asprintf(aliases, "test_service_alias2");
        1: 3954:    fail_if(aliases[1] == NULL);
        -: 3955:
        1: 3956:    aliases[2] = NULL;
        -: 3957:
        1: 3958:    protocols = talloc_array(test_ctx, const char *, 3);
        1: 3959:    fail_if(protocols == NULL);
        -: 3960:
        1: 3961:    protocols[0] = talloc_asprintf(protocols, "tcp");
        1: 3962:    fail_if(protocols[0] == NULL);
        -: 3963:
        1: 3964:    protocols[1] = talloc_asprintf(protocols, "udp");
        1: 3965:    fail_if(protocols[1] == NULL);
        -: 3966:
        1: 3967:    protocols[2] = NULL;
        -: 3968:
        1: 3969:    ret = sysdb_transaction_start(test_ctx->sysdb);
        1: 3970:    fail_if(ret != EOK);
        -: 3971:
        1: 3972:    ret = sysdb_svc_add(NULL, test_ctx->sysdb, test_ctx->domain,
        -: 3973:                        primary_name, port,
        -: 3974:                        aliases, protocols,
        -: 3975:                        NULL);
        1: 3976:    fail_unless(ret == EOK, "sysdb_svc_add error [%s]\n", strerror(ret));
        -: 3977:
        -: 3978:    /* Search by name and make sure the results match */
        1: 3979:    services_check_match_name(test_ctx,
        -: 3980:                              primary_name, port,
        -: 3981:                              aliases, protocols);
        -: 3982:
        -: 3983:    /* Search by port and make sure the results match */
        1: 3984:    services_check_match_port(test_ctx,
        -: 3985:                              primary_name, port,
        -: 3986:                              aliases, protocols);
        -: 3987:
        1: 3988:    ret = sysdb_transaction_commit(test_ctx->sysdb);
        1: 3989:    fail_if (ret != EOK);
        -: 3990:
        -: 3991:    /* Clean up after ourselves (and test deleting by name)
        -: 3992:     *
        -: 3993:     * We have to do this after the transaction, because LDB
        -: 3994:     * doesn't like adding and deleting the same entry in a
        -: 3995:     * single transaction.
        -: 3996:     */
        1: 3997:    ret = sysdb_svc_delete(test_ctx->sysdb, test_ctx->domain,
        -: 3998:                           primary_name, 0, NULL);
        1: 3999:    fail_if(ret != EOK);
        -: 4000:
        1: 4001:    talloc_free(test_ctx);
        -: 4002:}
        1: 4003:END_TEST
        -: 4004:
        1: 4005:START_TEST(test_sysdb_store_services)
        -: 4006:{
        -: 4007:    errno_t ret;
        -: 4008:    struct sysdb_test_ctx *test_ctx;
        1: 4009:    const char *primary_name = "test_store_service";
        1: 4010:    const char *alt_primary_name = "alt_test_store_service";
        -: 4011:    const char **aliases;
        -: 4012:    const char **protocols;
        1: 4013:    int port = 3890;
        1: 4014:    int altport = 3891;
        -: 4015:
        -: 4016:    /* Setup */
        1: 4017:    ret = setup_sysdb_tests(&test_ctx);
        1: 4018:    fail_if(ret != EOK, "Could not set up the test");
        -: 4019:
        1: 4020:    aliases = talloc_array(test_ctx, const char *, 3);
        1: 4021:    fail_if(aliases == NULL);
        -: 4022:
        1: 4023:    aliases[0] = talloc_asprintf(aliases, "test_service_alias1");
        1: 4024:    fail_if(aliases[0] == NULL);
        -: 4025:
        1: 4026:    aliases[1] = talloc_asprintf(aliases, "test_service_alias2");
        1: 4027:    fail_if(aliases[1] == NULL);
        -: 4028:
        1: 4029:    aliases[2] = NULL;
        -: 4030:
        1: 4031:    protocols = talloc_array(test_ctx, const char *, 3);
        1: 4032:    fail_if(protocols == NULL);
        -: 4033:
        1: 4034:    protocols[0] = talloc_asprintf(protocols, "tcp");
        1: 4035:    fail_if(protocols[0] == NULL);
        -: 4036:
        1: 4037:    protocols[1] = talloc_asprintf(protocols, "udp");
        1: 4038:    fail_if(protocols[1] == NULL);
        -: 4039:
        1: 4040:    protocols[2] = NULL;
        -: 4041:
        1: 4042:    ret = sysdb_transaction_start(test_ctx->sysdb);
        1: 4043:    fail_if(ret != EOK);
        -: 4044:
        -: 4045:    /* Store this group (which will add it) */
        1: 4046:    ret = sysdb_store_service(test_ctx->sysdb, test_ctx->domain,
        -: 4047:                              primary_name, port,
        -: 4048:                              aliases, protocols,
        -: 4049:                              NULL, NULL, 1, 1);
        1: 4050:    fail_if (ret != EOK);
        -: 4051:
        -: 4052:    /* Search by name and make sure the results match */
        1: 4053:    services_check_match_name(test_ctx,
        -: 4054:                              primary_name, port,
        -: 4055:                              aliases, protocols);
        -: 4056:
        -: 4057:    /* Search by port and make sure the results match */
        1: 4058:    services_check_match_port(test_ctx,
        -: 4059:                              primary_name, port,
        -: 4060:                              aliases, protocols);
        -: 4061:
        -: 4062:    /* Change the service name */
        1: 4063:    ret = sysdb_store_service(test_ctx->sysdb, test_ctx->domain,
        -: 4064:                              alt_primary_name, port,
        -: 4065:                              aliases, protocols,
        -: 4066:                              NULL, NULL, 1, 1);
        1: 4067:    fail_if (ret != EOK, "[%s]", strerror(ret));
        -: 4068:
        1: 4069:    services_check_match_name(test_ctx,
        -: 4070:                              alt_primary_name, port,
        -: 4071:                              aliases, protocols);
        -: 4072:
        -: 4073:    /* Search by port and make sure the results match */
        1: 4074:    services_check_match_port(test_ctx,
        -: 4075:                              alt_primary_name, port,
        -: 4076:                              aliases, protocols);
        -: 4077:
        -: 4078:
        -: 4079:    /* Change it back */
        1: 4080:    ret = sysdb_store_service(test_ctx->sysdb, test_ctx->domain,
        -: 4081:                              primary_name, port,
        -: 4082:                              aliases, protocols,
        -: 4083:                              NULL, NULL, 1, 1);
        1: 4084:    fail_if (ret != EOK, "[%s]", strerror(ret));
        -: 4085:
        -: 4086:    /* Change the port number */
        1: 4087:    ret = sysdb_store_service(test_ctx->sysdb, test_ctx->domain,
        -: 4088:                              primary_name, altport,
        -: 4089:                              aliases, protocols,
        -: 4090:                              NULL, NULL, 1, 1);
        1: 4091:    fail_if (ret != EOK, "[%s]", strerror(ret));
        -: 4092:
        -: 4093:    /* Search by name and make sure the results match */
        1: 4094:    services_check_match_name(test_ctx,
        -: 4095:                              primary_name, altport,
        -: 4096:                              aliases, protocols);
        -: 4097:
        -: 4098:    /* Search by port and make sure the results match */
        1: 4099:    services_check_match_port(test_ctx,
        -: 4100:                              primary_name, altport,
        -: 4101:                              aliases, protocols);
        -: 4102:
        -: 4103:    /* TODO: Test changing aliases and protocols */
        -: 4104:
        1: 4105:    ret = sysdb_transaction_commit(test_ctx->sysdb);
        1: 4106:    fail_if(ret != EOK, "[%s]", strerror(ret));
        -: 4107:
        -: 4108:    /* Clean up after ourselves (and test deleting by port)
        -: 4109:     *
        -: 4110:     * We have to do this after the transaction, because LDB
        -: 4111:     * doesn't like adding and deleting the same entry in a
        -: 4112:     * single transaction.
        -: 4113:     */
        1: 4114:    ret = sysdb_svc_delete(test_ctx->sysdb, test_ctx->domain,
        -: 4115:                           NULL, altport, NULL);
        1: 4116:    fail_if(ret != EOK);
        -: 4117:
        1: 4118:    talloc_free(test_ctx);
        -: 4119:}
        1: 4120:END_TEST
        -: 4121:
        -: 4122:errno_t
        -: 4123:sysdb_svc_remove_alias(struct sysdb_ctx *sysdb,
        -: 4124:                       struct ldb_dn *dn,
        -: 4125:                       const char *alias);
        -: 4126:
        1: 4127:START_TEST(test_sysdb_svc_remove_alias)
        -: 4128:{
        -: 4129:    errno_t ret;
        -: 4130:    struct sysdb_test_ctx *test_ctx;
        1: 4131:    const char *primary_name = "remove_alias_test";
        -: 4132:    const char **aliases;
        -: 4133:    const char **protocols;
        1: 4134:    int port = 3990;
        -: 4135:    struct ldb_dn *dn;
        -: 4136:
        -: 4137:    /* Setup */
        1: 4138:    ret = setup_sysdb_tests(&test_ctx);
        1: 4139:    fail_if(ret != EOK, "Could not set up the test");
        -: 4140:
        1: 4141:    aliases = talloc_array(test_ctx, const char *, 3);
        1: 4142:    fail_if(aliases == NULL);
        -: 4143:
        1: 4144:    aliases[0] = talloc_asprintf(aliases, "remove_alias_alias1");
        1: 4145:    fail_if(aliases[0] == NULL);
        -: 4146:
        1: 4147:    aliases[1] = talloc_asprintf(aliases, "remove_alias_alias2");
        1: 4148:    fail_if(aliases[1] == NULL);
        -: 4149:
        1: 4150:    aliases[2] = NULL;
        -: 4151:
        1: 4152:    protocols = talloc_array(test_ctx, const char *, 3);
        1: 4153:    fail_if(protocols == NULL);
        -: 4154:
        1: 4155:    protocols[0] = talloc_asprintf(protocols, "tcp");
        1: 4156:    fail_if(protocols[0] == NULL);
        -: 4157:
        1: 4158:    protocols[1] = talloc_asprintf(protocols, "udp");
        1: 4159:    fail_if(protocols[1] == NULL);
        -: 4160:
        1: 4161:    protocols[2] = NULL;
        -: 4162:
        1: 4163:    ret = sysdb_transaction_start(test_ctx->sysdb);
        1: 4164:    fail_if(ret != EOK);
        -: 4165:
        1: 4166:    ret = sysdb_svc_add(NULL, test_ctx->sysdb, test_ctx->domain,
        -: 4167:                        primary_name, port,
        -: 4168:                        aliases, protocols,
        -: 4169:                        NULL);
        1: 4170:    fail_unless(ret == EOK, "sysdb_svc_add error [%s]\n", strerror(ret));
        -: 4171:
        -: 4172:    /* Search by name and make sure the results match */
        1: 4173:    services_check_match_name(test_ctx,
        -: 4174:                              primary_name, port,
        -: 4175:                              aliases, protocols);
        -: 4176:
        -: 4177:    /* Search by port and make sure the results match */
        1: 4178:    services_check_match_port(test_ctx,
        -: 4179:                              primary_name, port,
        -: 4180:                              aliases, protocols);
        -: 4181:
        -: 4182:    /* Now remove an alias */
        1: 4183:    dn = sysdb_svc_dn(test_ctx->sysdb, test_ctx, test_ctx->domain->name, primary_name);
        1: 4184:    fail_if (dn == NULL);
        -: 4185:
        1: 4186:    ret = sysdb_svc_remove_alias(test_ctx->sysdb, dn, aliases[1]);
        1: 4187:    fail_if (ret != EOK, "[%s]", strerror(ret));
        1: 4188:    sysdb_transaction_commit(test_ctx->sysdb);
        1: 4189:    sysdb_transaction_start(test_ctx->sysdb);
        -: 4190:
        -: 4191:    /* Set aliases[1] to NULL to perform validation checks */
        1: 4192:    aliases[1] = NULL;
        -: 4193:
        -: 4194:    /* Search by name and make sure the results match */
        1: 4195:    services_check_match_name(test_ctx,
        -: 4196:                              primary_name, port,
        -: 4197:                              aliases, protocols);
        -: 4198:
        -: 4199:    /* Search by port and make sure the results match */
        1: 4200:    services_check_match_port(test_ctx,
        -: 4201:                              primary_name, port,
        -: 4202:                              aliases, protocols);
        -: 4203:
        1: 4204:    ret = sysdb_transaction_commit(test_ctx->sysdb);
        1: 4205:    fail_if(ret != EOK);
        -: 4206:
        1: 4207:    talloc_free(test_ctx);
        -: 4208:}
        1: 4209:END_TEST
        -: 4210:
        1: 4211:START_TEST(test_sysdb_has_enumerated)
        -: 4212:{
        -: 4213:    errno_t ret;
        -: 4214:    struct sysdb_test_ctx *test_ctx;
        -: 4215:    bool enumerated;
        -: 4216:
        -: 4217:    /* Setup */
        1: 4218:    ret = setup_sysdb_tests(&test_ctx);
        1: 4219:    fail_if(ret != EOK, "Could not set up the test");
        -: 4220:
        1: 4221:    ret = sysdb_has_enumerated(test_ctx->sysdb, test_ctx->domain, &enumerated);
        1: 4222:    fail_if(ret != EOK, "Error [%d][%s] checking enumeration",
        -: 4223:                        ret, strerror(ret));
        -: 4224:
        1: 4225:    fail_if(enumerated, "Enumeration should default to false");
        -: 4226:
        1: 4227:    ret = sysdb_set_enumerated(test_ctx->sysdb, test_ctx->domain, true);
        1: 4228:    fail_if(ret != EOK, "Error [%d][%s] setting enumeration",
        -: 4229:                        ret, strerror(ret));
        -: 4230:
        -: 4231:    /* Recheck enumeration status */
        1: 4232:    ret = sysdb_has_enumerated(test_ctx->sysdb, test_ctx->domain, &enumerated);
        1: 4233:    fail_if(ret != EOK, "Error [%d][%s] checking enumeration",
        -: 4234:                        ret, strerror(ret));
        -: 4235:
        1: 4236:    fail_unless(enumerated, "Enumeration should have been set to true");
        -: 4237:
        1: 4238:    talloc_free(test_ctx);
        -: 4239:}
        1: 4240:END_TEST
        -: 4241:
        1: 4242:START_TEST(test_sysdb_original_dn_case_insensitive)
        -: 4243:{
        -: 4244:    errno_t ret;
        -: 4245:    struct sysdb_test_ctx *test_ctx;
        -: 4246:    const char *filter;
        -: 4247:    struct ldb_dn *base_dn;
        1: 4248:    const char *no_attrs[] = { NULL };
        -: 4249:    struct ldb_message **msgs;
        -: 4250:    size_t num_msgs;
        -: 4251:
        -: 4252:    /* Setup */
        1: 4253:    ret = setup_sysdb_tests(&test_ctx);
        1: 4254:    fail_if(ret != EOK, "Could not set up the test");
        -: 4255:
        1: 4256:    ret = sysdb_add_incomplete_group(test_ctx->sysdb, test_ctx->domain,
        -: 4257:                                     "case_sensitive_group1", 29000,
        -: 4258:                                     "cn=case_sensitive_group1,cn=example,cn=com",
        -: 4259:                                     true, 0);
        1: 4260:    fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
        -: 4261:                            ret, strerror(ret));
        -: 4262:
        1: 4263:    ret = sysdb_add_incomplete_group(test_ctx->sysdb, test_ctx->domain,
        -: 4264:                                     "case_sensitive_group2", 29001,
        -: 4265:                                     "cn=CASE_SENSITIVE_GROUP1,cn=EXAMPLE,cn=COM",
        -: 4266:                                     true, 0);
        1: 4267:    fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
        -: 4268:                            ret, strerror(ret));
        -: 4269:
        -: 4270:    /* Search by originalDN should yield 2 entries */
        1: 4271:    filter = talloc_asprintf(test_ctx, "%s=%s", SYSDB_ORIG_DN,
        -: 4272:                             "cn=case_sensitive_group1,cn=example,cn=com");
        1: 4273:    fail_if(filter == NULL, "Cannot construct filter\n");
        -: 4274:
        1: 4275:    base_dn = sysdb_domain_dn(test_ctx->sysdb, test_ctx, test_ctx->domain);
        1: 4276:    fail_if(base_dn == NULL, "Cannot construct basedn\n");
        -: 4277:
        1: 4278:    ret = sysdb_search_entry(test_ctx, test_ctx->sysdb,
        -: 4279:                             base_dn, LDB_SCOPE_SUBTREE, filter, no_attrs,
        -: 4280:                             &num_msgs, &msgs);
        1: 4281:    fail_unless(ret == EOK, "cache search error [%d][%s]",
        -: 4282:                            ret, strerror(ret));
        1: 4283:    fail_unless(num_msgs == 2, "Did not find the expected number of entries using "
        -: 4284:                               "case insensitive originalDN search");
        -: 4285:}
        1: 4286:END_TEST
        -: 4287:
        -: 4288:struct sysdb_subdom dom1 =  { "DOM1.SUB", "dom1.sub", "dom1", "S-1" };
        -: 4289:struct sysdb_subdom dom2 =  { "DOM2.SUB", "dom2.sub", "dom2", "S-2" };
        -: 4290:struct sysdb_subdom dom_t = { "TEST.SUB", "test.sub", "test", "S-3" };
        -: 4291:
        1: 4292:START_TEST(test_sysdb_subdomain_create)
        -: 4293:{
        -: 4294:    struct sysdb_test_ctx *test_ctx;
        -: 4295:    errno_t ret;
        1: 4296:    struct sysdb_subdom **cur_subdomains = NULL;
        -: 4297:    size_t cur_subdomains_count;
        1: 4298:    struct sysdb_subdom *new_subdom1 = &dom1;
        1: 4299:    struct sysdb_subdom *new_subdom2 = &dom2;
        1: 4300:    int num_subdom1 = 1;
        1: 4301:    int num_subdom2 = 1;
        -: 4302:
        1: 4303:    ret = setup_sysdb_tests(&test_ctx);
        1: 4304:    fail_if(ret != EOK, "Could not set up the test");
        -: 4305:
        1: 4306:    ret = sysdb_get_subdomains(test_ctx, test_ctx->sysdb,
        -: 4307:                               &cur_subdomains_count, &cur_subdomains);
        1: 4308:    fail_unless(ret == EOK, "sysdb_get_subdomains failed with [%d][%s]",
        -: 4309:                            ret, strerror(ret));
        1: 4310:    fail_unless(cur_subdomains != NULL, "No sub-domains returned.");
        1: 4311:    fail_unless(cur_subdomains[0] == NULL, "No empty sub-domain list returned.");
        -: 4312:
        1: 4313:    ret = sysdb_update_subdomains(test_ctx->sysdb, num_subdom1, new_subdom1);
        1: 4314:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4315:                            ret, strerror(ret));
        -: 4316:
        1: 4317:    ret = sysdb_get_subdomains(test_ctx, test_ctx->sysdb,
        -: 4318:                               &cur_subdomains_count, &cur_subdomains);
        1: 4319:    fail_unless(ret == EOK, "sysdb_get_subdomains failed with [%d][%s]",
        -: 4320:                            ret, strerror(ret));
        1: 4321:    fail_unless(cur_subdomains != NULL, "No sub-domains returned.");
        1: 4322:    fail_unless(cur_subdomains[0] != NULL, "Empyt sub-domain list returned.");
        1: 4323:    fail_unless(strcmp(cur_subdomains[0]->name, new_subdom1[0].name) == 0,
        -: 4324:                "Unexpected sub-domain found, expected [%s], got [%s]",
        -: 4325:                new_subdom1[0].name, cur_subdomains[0]->name);
        -: 4326:
        1: 4327:    ret = sysdb_update_subdomains(test_ctx->sysdb, num_subdom2, new_subdom2);
        1: 4328:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4329:                            ret, strerror(ret));
        -: 4330:
        1: 4331:    ret = sysdb_get_subdomains(test_ctx, test_ctx->sysdb,
        -: 4332:                               &cur_subdomains_count, &cur_subdomains);
        1: 4333:    fail_unless(ret == EOK, "sysdb_get_subdomains failed with [%d][%s]",
        -: 4334:                            ret, strerror(ret));
        1: 4335:    fail_unless(cur_subdomains != NULL, "No sub-domains returned.");
        1: 4336:    fail_unless(cur_subdomains[0] != NULL, "Empyt sub-domain list returned.");
        1: 4337:    fail_unless(strcmp(cur_subdomains[0]->name, new_subdom2[0].name) == 0,
        -: 4338:                "Unexpected sub-domain found, expected [%s], got [%s]",
        -: 4339:                new_subdom2[0].name, cur_subdomains[0]->name);
        -: 4340:
        1: 4341:    ret = sysdb_update_subdomains(test_ctx->sysdb, 0, NULL);
        1: 4342:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4343:                            ret, strerror(ret));
        -: 4344:
        1: 4345:    ret = sysdb_get_subdomains(test_ctx, test_ctx->sysdb,
        -: 4346:                               &cur_subdomains_count, &cur_subdomains);
        1: 4347:    fail_unless(ret == EOK, "sysdb_get_subdomains failed with [%d][%s]",
        -: 4348:                            ret, strerror(ret));
        1: 4349:    fail_unless(cur_subdomains != NULL, "No sub-domains returned.");
        1: 4350:    fail_unless(cur_subdomains[0] == NULL, "No empty sub-domain list returned.");
        -: 4351:}
        1: 4352:END_TEST
        -: 4353:
        1: 4354:START_TEST(test_sysdb_subdomain_store_user)
        -: 4355:{
        -: 4356:    struct sysdb_test_ctx *test_ctx;
        -: 4357:    errno_t ret;
        1: 4358:    struct sysdb_subdom *test_subdom = &dom_t;
        1: 4359:    int num_subdom = 1;
        1: 4360:    struct sss_domain_info *subdomain = NULL;
        1: 4361:    struct ldb_result *results = NULL;
        1: 4362:    struct ldb_dn *base_dn = NULL;
        1: 4363:    struct ldb_dn *check_dn = NULL;
        -: 4364:
        1: 4365:    ret = setup_sysdb_tests(&test_ctx);
        1: 4366:    fail_if(ret != EOK, "Could not set up the test");
        -: 4367:
        1: 4368:    ret = sysdb_update_subdomains(test_ctx->sysdb, num_subdom, test_subdom);
        1: 4369:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4370:                            ret, strerror(ret));
        -: 4371:
        1: 4372:    subdomain = new_subdomain(test_ctx, test_ctx->domain, "test.sub",
        -: 4373:                              NULL, NULL);
        1: 4374:    fail_unless(subdomain != NULL, "new_subdomain failed.");
        -: 4375:
        1: 4376:    ret = sysdb_store_user(subdomain->sysdb, subdomain, "subdomuser",
        -: 4377:                           NULL, 12345, 0, "Sub Domain User",
        -: 4378:                           "/home/subdomuser", "/bin/bash",
        -: 4379:                           NULL, NULL, NULL, -1, 0);
        1: 4380:    fail_unless(ret == EOK, "sysdb_store_user failed.");
        -: 4381:
        1: 4382:    base_dn =ldb_dn_new(test_ctx, test_ctx->sysdb->ldb, "cn=sysdb");
        1: 4383:    fail_unless(base_dn != NULL);
        -: 4384:
        1: 4385:    check_dn = ldb_dn_new(test_ctx, test_ctx->sysdb->ldb,
        -: 4386:                          "name=subdomuser,cn=users,cn=test.sub,cn=sysdb");
        1: 4387:    fail_unless(check_dn != NULL);
        -: 4388:
        1: 4389:    ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, &results, base_dn,
        -: 4390:                     LDB_SCOPE_SUBTREE, NULL, "name=subdomuser");
        1: 4391:    fail_unless(ret == EOK, "ldb_search failed.");
        1: 4392:    fail_unless(results->count == 1, "Unexpected number of results, "
        -: 4393:                                     "expected [%d], got [%d]",
        -: 4394:                                     1, results->count);
        1: 4395:    fail_unless(ldb_dn_compare(results->msgs[0]->dn, check_dn) == 0,
        -: 4396:                "Unexpedted DN returned");
        -: 4397:
        1: 4398:    ret = sysdb_delete_user(subdomain->sysdb, subdomain, "subdomuser", 0);
        1: 4399:    fail_unless(ret == EOK, "sysdb_delete_user failed [%d][%s].",
        -: 4400:                            ret, strerror(ret));
        -: 4401:
        1: 4402:    ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, &results, base_dn,
        -: 4403:                     LDB_SCOPE_SUBTREE, NULL, "name=subdomuser");
        1: 4404:    fail_unless(ret == EOK, "ldb_search failed.");
        1: 4405:    fail_unless(results->count == 0, "Unexpected number of results, "
        -: 4406:                                     "expected [%d], got [%d]",
        -: 4407:                                     0, results->count);
        -: 4408:}
        1: 4409:END_TEST
        -: 4410:
        1: 4411:START_TEST(test_sysdb_subdomain_user_ops)
        -: 4412:{
        -: 4413:    struct sysdb_test_ctx *test_ctx;
        -: 4414:    errno_t ret;
        1: 4415:    struct sysdb_subdom *test_subdom = &dom_t;
        1: 4416:    int num_subdom = 1;
        1: 4417:    struct sss_domain_info *subdomain = NULL;
        1: 4418:    struct ldb_message *msg = NULL;
        1: 4419:    struct ldb_dn *check_dn = NULL;
        -: 4420:
        1: 4421:    ret = setup_sysdb_tests(&test_ctx);
        1: 4422:    fail_if(ret != EOK, "Could not set up the test");
        -: 4423:
        1: 4424:    ret = sysdb_update_subdomains(test_ctx->sysdb, num_subdom, test_subdom);
        1: 4425:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4426:                            ret, strerror(ret));
        -: 4427:
        1: 4428:    subdomain = new_subdomain(test_ctx, test_ctx->domain, "test.sub",
        -: 4429:                              NULL, NULL);
        1: 4430:    fail_unless(subdomain != NULL, "new_subdomain failed.");
        -: 4431:
        1: 4432:    ret = sysdb_store_user(subdomain->sysdb, subdomain, "subdomuser",
        -: 4433:                           NULL, 12345, 0, "Sub Domain User",
        -: 4434:                           "/home/subdomuser", "/bin/bash",
        -: 4435:                           NULL, NULL, NULL, -1, 0);
        1: 4436:    fail_unless(ret == EOK, "sysdb_store_domuser failed.");
        -: 4437:
        1: 4438:    check_dn = ldb_dn_new(test_ctx, test_ctx->sysdb->ldb,
        -: 4439:                          "name=subdomuser,cn=users,cn=test.sub,cn=sysdb");
        1: 4440:    fail_unless(check_dn != NULL);
        -: 4441:
        1: 4442:    ret = sysdb_search_user_by_name(test_ctx, subdomain->sysdb, subdomain,
        -: 4443:                                    "subdomuser", NULL, &msg);
        1: 4444:    fail_unless(ret == EOK, "sysdb_search_domuser_by_name failed with [%d][%s].",
        -: 4445:                            ret, strerror(ret));
        1: 4446:    fail_unless(ldb_dn_compare(msg->dn, check_dn) == 0,
        -: 4447:                "Unexpedted DN returned");
        -: 4448:
        1: 4449:    ret = sysdb_search_user_by_uid(test_ctx, subdomain->sysdb, subdomain,
        -: 4450:                                   12345, NULL, &msg);
        1: 4451:    fail_unless(ret == EOK, "sysdb_search_domuser_by_uid failed with [%d][%s].",
        -: 4452:                            ret, strerror(ret));
        1: 4453:    fail_unless(ldb_dn_compare(msg->dn, check_dn) == 0,
        -: 4454:                "Unexpedted DN returned");
        -: 4455:
        1: 4456:    ret = sysdb_delete_user(subdomain->sysdb, subdomain, "subdomuser", 12345);
        1: 4457:    fail_unless(ret == EOK, "sysdb_delete_domuser failed with [%d][%s].",
        -: 4458:                            ret, strerror(ret));
        -: 4459:
        -: 4460:}
        1: 4461:END_TEST
        -: 4462:
        1: 4463:START_TEST(test_sysdb_subdomain_group_ops)
        -: 4464:{
        -: 4465:    struct sysdb_test_ctx *test_ctx;
        -: 4466:    errno_t ret;
        1: 4467:    struct sysdb_subdom *test_subdom = &dom_t;
        1: 4468:    int num_subdom = 1;
        1: 4469:    struct sss_domain_info *subdomain = NULL;
        1: 4470:    struct ldb_message *msg = NULL;
        1: 4471:    struct ldb_dn *check_dn = NULL;
        -: 4472:
        1: 4473:    ret = setup_sysdb_tests(&test_ctx);
        1: 4474:    fail_if(ret != EOK, "Could not set up the test");
        -: 4475:
        1: 4476:    ret = sysdb_update_subdomains(test_ctx->sysdb, num_subdom, test_subdom);
        1: 4477:    fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]",
        -: 4478:                            ret, strerror(ret));
        -: 4479:
        1: 4480:    subdomain = new_subdomain(test_ctx, test_ctx->domain, "test.sub",
        -: 4481:                              NULL, NULL);
        1: 4482:    fail_unless(subdomain != NULL, "new_subdomain failed.");
        -: 4483:
        1: 4484:    ret = sysdb_store_group(subdomain->sysdb, subdomain,
        -: 4485:                            "subdomgroup", 12345, NULL, -1, 0);
        1: 4486:    fail_unless(ret == EOK, "sysdb_store_domgroup failed.");
        -: 4487:
        1: 4488:    check_dn = ldb_dn_new(test_ctx, test_ctx->sysdb->ldb,
        -: 4489:                          "name=subdomgroup,cn=groups,cn=test.sub,cn=sysdb");
        1: 4490:    fail_unless(check_dn != NULL);
        -: 4491:
        1: 4492:    ret = sysdb_search_group_by_name(test_ctx, subdomain->sysdb, subdomain,
        -: 4493:                                     "subdomgroup", NULL, &msg);
        1: 4494:    fail_unless(ret == EOK, "sysdb_search_domgroup_by_name failed with [%d][%s].",
        -: 4495:                            ret, strerror(ret));
        1: 4496:    fail_unless(ldb_dn_compare(msg->dn, check_dn) == 0,
        -: 4497:                "Unexpedted DN returned");
        -: 4498:
        1: 4499:    ret = sysdb_search_group_by_gid(test_ctx, subdomain->sysdb, subdomain,
        -: 4500:                                    12345, NULL, &msg);
        1: 4501:    fail_unless(ret == EOK, "sysdb_search_domgroup_by_gid failed with [%d][%s].",
        -: 4502:                            ret, strerror(ret));
        1: 4503:    fail_unless(ldb_dn_compare(msg->dn, check_dn) == 0,
        -: 4504:                "Unexpedted DN returned");
        -: 4505:
        1: 4506:    ret = sysdb_delete_group(subdomain->sysdb, subdomain, "subdomgroup", 12345);
        1: 4507:    fail_unless(ret == EOK, "sysdb_delete_domgroup failed with [%d][%s].",
        -: 4508:                            ret, strerror(ret));
        -: 4509:
        -: 4510:}
        1: 4511:END_TEST
        -: 4512:
        -: 4513:#ifdef BUILD_AUTOFS
       10: 4514:START_TEST(test_autofs_create_map)
        -: 4515:{
        -: 4516:    struct sysdb_test_ctx *test_ctx;
        -: 4517:    const char *autofsmapname;
        -: 4518:    errno_t ret;
        -: 4519:
       10: 4520:    ret = setup_sysdb_tests(&test_ctx);
       10: 4521:    fail_if(ret != EOK, "Could not set up the test");
        -: 4522:
       10: 4523:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4524:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4525:
       10: 4526:    ret = sysdb_save_autofsmap(test_ctx->sysdb,
       10: 4527:                               test_ctx->domain, autofsmapname,
        -: 4528:                               autofsmapname, NULL, 0, 0);
       10: 4529:    fail_if(ret != EOK, "Could not store autofs map %s", autofsmapname);
       10: 4530:    talloc_free(test_ctx);
        -: 4531:}
       10: 4532:END_TEST
        -: 4533:
       10: 4534:START_TEST(test_autofs_retrieve_map)
        -: 4535:{
        -: 4536:    struct sysdb_test_ctx *test_ctx;
        -: 4537:    const char *autofsmapname;
        -: 4538:    errno_t ret;
       10: 4539:    struct ldb_message *map = NULL;
        -: 4540:
       10: 4541:    ret = setup_sysdb_tests(&test_ctx);
       10: 4542:    fail_if(ret != EOK, "Could not set up the test");
        -: 4543:
       10: 4544:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4545:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4546:
       10: 4547:    ret = sysdb_get_map_byname(test_ctx, test_ctx->sysdb, test_ctx->domain,
        -: 4548:                               autofsmapname, &map);
       10: 4549:    fail_if(ret != EOK, "Could not retrieve autofs map %s", autofsmapname);
       10: 4550:    fail_if(map == NULL, "No map retrieved?\n");
       10: 4551:    talloc_free(test_ctx);
        -: 4552:}
       10: 4553:END_TEST
        -: 4554:
       10: 4555:START_TEST(test_autofs_delete_map)
        -: 4556:{
        -: 4557:    struct sysdb_test_ctx *test_ctx;
        -: 4558:    const char *autofsmapname;
        -: 4559:    errno_t ret;
        -: 4560:
       10: 4561:    ret = setup_sysdb_tests(&test_ctx);
       10: 4562:    fail_if(ret != EOK, "Could not set up the test");
        -: 4563:
       10: 4564:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4565:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4566:
       10: 4567:    ret = sysdb_delete_autofsmap(test_ctx->sysdb,
       10: 4568:                                 test_ctx->domain, autofsmapname);
       10: 4569:    fail_if(ret != EOK, "Could not retrieve autofs map %s", autofsmapname);
       10: 4570:    talloc_free(test_ctx);
        -: 4571:}
       10: 4572:END_TEST
        -: 4573:
       10: 4574:START_TEST(test_autofs_retrieve_map_neg)
        -: 4575:{
        -: 4576:    struct sysdb_test_ctx *test_ctx;
        -: 4577:    const char *autofsmapname;
        -: 4578:    errno_t ret;
       10: 4579:    struct ldb_message *map = NULL;
        -: 4580:
       10: 4581:    ret = setup_sysdb_tests(&test_ctx);
       10: 4582:    fail_if(ret != EOK, "Could not set up the test");
        -: 4583:
       10: 4584:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4585:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4586:
       10: 4587:    ret = sysdb_get_map_byname(test_ctx, test_ctx->sysdb, test_ctx->domain,
        -: 4588:                               autofsmapname, &map);
       10: 4589:    fail_if(ret != ENOENT, "Expected ENOENT, got %d instead\n", ret);
       10: 4590:    fail_if(map != NULL, "Unexpected map found\n");
       10: 4591:    talloc_free(test_ctx);
        -: 4592:}
       10: 4593:END_TEST
        -: 4594:
       10: 4595:START_TEST(test_autofs_store_entry_in_map)
        -: 4596:{
        -: 4597:    struct sysdb_test_ctx *test_ctx;
        -: 4598:    const char *autofsmapname;
        -: 4599:    const char *autofskey;
        -: 4600:    const char *autofsval;
        -: 4601:    errno_t ret;
        -: 4602:    int ii;
       10: 4603:    const int limit = 10;
        -: 4604:
       10: 4605:    ret = setup_sysdb_tests(&test_ctx);
       10: 4606:    fail_if(ret != EOK, "Could not set up the test");
        -: 4607:
       10: 4608:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4609:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4610:
      110: 4611:    for (ii=0; ii < limit; ii++) {
      100: 4612:        autofskey = talloc_asprintf(test_ctx, "%s_testkey%d",
        -: 4613:                                    autofsmapname, ii);
      100: 4614:        fail_if(autofskey == NULL, "Out of memory\n");
        -: 4615:
      100: 4616:        autofsval = talloc_asprintf(test_ctx, "testserver:/testval%d", ii);
      100: 4617:        fail_if(autofsval == NULL, "Out of memory\n");
        -: 4618:
      100: 4619:        ret = sysdb_save_autofsentry(test_ctx->sysdb, test_ctx->domain,
        -: 4620:                                     autofsmapname, autofskey,
        -: 4621:                                     autofsval, NULL);
      100: 4622:        fail_if(ret != EOK, "Could not save autofs entry %s", autofskey);
        -: 4623:    }
        -: 4624:
       10: 4625:    talloc_free(test_ctx);
        -: 4626:}
       10: 4627:END_TEST
        -: 4628:
       10: 4629:START_TEST(test_autofs_retrieve_keys_by_map)
        -: 4630:{
        -: 4631:    struct sysdb_test_ctx *test_ctx;
        -: 4632:    const char *autofsmapname;
        -: 4633:    errno_t ret;
        -: 4634:    size_t count;
        -: 4635:    struct ldb_message **entries;
       10: 4636:    const int expected = 10;
        -: 4637:
       10: 4638:    ret = setup_sysdb_tests(&test_ctx);
       10: 4639:    fail_if(ret != EOK, "Could not set up the test");
        -: 4640:
       10: 4641:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4642:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4643:
       20: 4644:    ret = sysdb_autofs_entries_by_map(test_ctx,
       20: 4645:                                      test_ctx->sysdb, test_ctx->domain,
        -: 4646:                                      autofsmapname, &count, &entries);
       10: 4647:    fail_if(ret != EOK, "Cannot get autofs entries for map %s\n",
        -: 4648:            autofsmapname);
       10: 4649:    fail_if(count != expected, "Expected to find %d entries, got %d\n",
        -: 4650:            expected, count);
       10: 4651:    talloc_free(test_ctx);
        -: 4652:}
       10: 4653:END_TEST
        -: 4654:
       10: 4655:START_TEST(test_autofs_key_duplicate)
        -: 4656:{
        -: 4657:    struct sysdb_test_ctx *test_ctx;
        -: 4658:    const char *autofsmapname;
        -: 4659:    const char *autofskey;
        -: 4660:    const char *autofsval;
        -: 4661:    errno_t ret;
        -: 4662:
       10: 4663:    ret = setup_sysdb_tests(&test_ctx);
       10: 4664:    fail_if(ret != EOK, "Could not set up the test");
        -: 4665:
       10: 4666:    autofsmapname = talloc_asprintf(test_ctx, "testmap%d", _i);
       10: 4667:    fail_if(autofsmapname == NULL, "Out of memory\n");
        -: 4668:
       10: 4669:    autofskey = talloc_asprintf(test_ctx, "testkey");
       10: 4670:    fail_if(autofskey == NULL, "Out of memory\n");
        -: 4671:
       10: 4672:    autofsval = talloc_asprintf(test_ctx, "testserver:/testval%d", _i);
       10: 4673:    fail_if(autofsval == NULL, "Out of memory\n");
        -: 4674:
       10: 4675:    ret = sysdb_save_autofsentry(test_ctx->sysdb, test_ctx->domain,
        -: 4676:                                 autofsmapname, autofskey,
        -: 4677:                                 autofsval, NULL);
       10: 4678:    fail_if(ret != EOK, "Could not save autofs entry %s", autofskey);
       10: 4679:    talloc_free(test_ctx);
        -: 4680:}
       10: 4681:END_TEST
        -: 4682:
        1: 4683:START_TEST(test_autofs_get_duplicate_keys)
        -: 4684:{
        -: 4685:    struct sysdb_test_ctx *test_ctx;
        -: 4686:    const char *autofskey;
        -: 4687:    errno_t ret;
        1: 4688:    const char *attrs[] = { SYSDB_AUTOFS_ENTRY_KEY,
        -: 4689:                            SYSDB_AUTOFS_ENTRY_VALUE,
        -: 4690:                            NULL };
        -: 4691:    size_t count;
        -: 4692:    struct ldb_message **msgs;
        -: 4693:    struct ldb_dn *dn;
        -: 4694:    const char *filter;
        1: 4695:    const int expected = 10;
        -: 4696:
        1: 4697:    ret = setup_sysdb_tests(&test_ctx);
        1: 4698:    fail_if(ret != EOK, "Could not set up the test");
        -: 4699:
        1: 4700:    autofskey = talloc_asprintf(test_ctx, "testkey");
        1: 4701:    fail_if(autofskey == NULL, "Out of memory\n");
        -: 4702:
        1: 4703:    filter = talloc_asprintf(test_ctx, "(&(objectclass=%s)(%s=%s))",
        -: 4704:                             SYSDB_AUTOFS_ENTRY_OC, SYSDB_AUTOFS_ENTRY_KEY, autofskey);
        1: 4705:    fail_if(filter == NULL, "Out of memory\n");
        -: 4706:
        1: 4707:    dn = ldb_dn_new_fmt(test_ctx, test_ctx->sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
        1: 4708:                        AUTOFS_MAP_SUBDIR, test_ctx->domain->name);
        1: 4709:    fail_if(dn == NULL, "Out of memory\n");
        -: 4710:
        1: 4711:    ret = sysdb_search_entry(test_ctx, test_ctx->sysdb, dn, LDB_SCOPE_SUBTREE,
        -: 4712:                             filter, attrs, &count, &msgs);
        1: 4713:    fail_if(count != expected, "Found %d entries with name %s, expected %d\n",
        -: 4714:            count, autofskey, expected);
        1: 4715:    talloc_free(test_ctx);
        -: 4716:}
        1: 4717:END_TEST
        -: 4718:
        -: 4719:#endif /* BUILD_AUTOFS */
        -: 4720:
        1: 4721:Suite *create_sysdb_suite(void)
        -: 4722:{
        1: 4723:    Suite *s = suite_create("sysdb");
        -: 4724:
        1: 4725:    TCase *tc_sysdb = tcase_create("SYSDB Tests");
        -: 4726:
        -: 4727:    /* Create a new user */
        1: 4728:    tcase_add_loop_test(tc_sysdb, test_sysdb_add_user,27000,27010);
        -: 4729:
        -: 4730:    /* Verify the users were added */
        1: 4731:    tcase_add_loop_test(tc_sysdb, test_sysdb_getpwnam, 27000, 27010);
        -: 4732:
        -: 4733:    /* Create a new group */
        1: 4734:    tcase_add_loop_test(tc_sysdb, test_sysdb_add_group, 28000, 28010);
        -: 4735:
        -: 4736:    /* Verify the groups were added */
        1: 4737:    tcase_add_loop_test(tc_sysdb, test_sysdb_getgrnam, 28000, 28010);
        -: 4738:
        -: 4739:    /* sysdb_group_dn_name returns the name of the group in question */
        1: 4740:    tcase_add_loop_test(tc_sysdb, test_sysdb_group_dn_name, 28000, 28010);
        -: 4741:
        -: 4742:    /* sysdb_store_user allows setting attributes for existing users */
        1: 4743:    tcase_add_loop_test(tc_sysdb, test_sysdb_store_user_existing, 27000, 27010);
        -: 4744:
        -: 4745:    /* test the change */
        1: 4746:    tcase_add_loop_test(tc_sysdb, test_sysdb_get_user_attr, 27000, 27010);
        -: 4747:
        -: 4748:    /* Add and remove users in a group with sysdb_update_members */
        1: 4749:    tcase_add_test(tc_sysdb, test_sysdb_update_members);
        -: 4750:
        -: 4751:    /* Remove the other half by gid */
        1: 4752:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group_by_gid, 28000, 28010);
        -: 4753:
        -: 4754:    /* Remove the other half by uid */
        1: 4755:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_user_by_uid, 27000, 27010);
        -: 4756:
        -: 4757:    /* Create a new user */
        1: 4758:    tcase_add_loop_test(tc_sysdb, test_sysdb_store_user, 27010, 27020);
        -: 4759:
        -: 4760:    /* Verify the users were added */
        1: 4761:    tcase_add_loop_test(tc_sysdb, test_sysdb_getpwnam, 27010, 27020);
        -: 4762:
        -: 4763:    /* Verify the users can be queried by UID */
        1: 4764:    tcase_add_loop_test(tc_sysdb, test_sysdb_getpwuid, 27010, 27020);
        -: 4765:
        -: 4766:    /* Enumerate the users */
        1: 4767:    tcase_add_test(tc_sysdb, test_sysdb_enumpwent);
        -: 4768:
        -: 4769:    /* Change their attribute */
        1: 4770:    tcase_add_loop_test(tc_sysdb, test_sysdb_set_user_attr, 27010, 27020);
        -: 4771:
        -: 4772:    /* Verify the change */
        1: 4773:    tcase_add_loop_test(tc_sysdb, test_sysdb_get_user_attr, 27010, 27020);
        -: 4774:
        -: 4775:    /* Create a new group */
        1: 4776:    tcase_add_loop_test(tc_sysdb, test_sysdb_store_group, 28010, 28020);
        -: 4777:
        -: 4778:    /* Verify the groups were added */
        -: 4779:
        -: 4780:    /* Verify the groups can be queried by GID */
        1: 4781:    tcase_add_loop_test(tc_sysdb, test_sysdb_getgrgid, 28010, 28020);
        -: 4782:
        -: 4783:    /* Enumerate the groups */
        1: 4784:    tcase_add_test(tc_sysdb, test_sysdb_enumgrent);
        -: 4785:
        -: 4786:    /* Add some members to the groups */
        1: 4787:    tcase_add_loop_test(tc_sysdb, test_sysdb_add_group_member, 28010, 28020);
        -: 4788:
        -: 4789:    /* Authenticate with missing cached password */
        1: 4790:    tcase_add_loop_test(tc_sysdb, test_sysdb_cached_authentication_missing_password,
        -: 4791:                        27010, 27011);
        -: 4792:
        -: 4793:    /* Add a cached password */
        1: 4794:    tcase_add_loop_test(tc_sysdb, test_sysdb_cache_password, 27010, 27011);
        -: 4795:
        -: 4796:    /* Authenticate against cached password */
        1: 4797:    tcase_add_loop_test(tc_sysdb, test_sysdb_cached_authentication_wrong_password,
        -: 4798:                        27010, 27011);
        1: 4799:    tcase_add_loop_test(tc_sysdb, test_sysdb_cached_authentication, 27010, 27011);
        -: 4800:
        -: 4801:    /* ASQ search test */
        1: 4802:    tcase_add_loop_test(tc_sysdb, test_sysdb_prepare_asq_test_user, 28011, 28020);
        1: 4803:    tcase_add_test(tc_sysdb, test_sysdb_asq_search);
        -: 4804:
        -: 4805:    /* Test search with more than one result */
        1: 4806:    tcase_add_test(tc_sysdb, test_sysdb_search_all_users);
        -: 4807:
        -: 4808:    /* Remove the members from the groups */
        1: 4809:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_group_member, 28010, 28020);
        -: 4810:
        -: 4811:    /* Remove the users by name */
        1: 4812:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_user, 27010, 27020);
        -: 4813:
        -: 4814:    /* Remove the groups by name */
        1: 4815:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group, 28010, 28020);
        -: 4816:
        -: 4817:    /* test the ignore_not_found parameter for users */
        1: 4818:    tcase_add_test(tc_sysdb, test_sysdb_remove_nonexistent_user);
        -: 4819:
        -: 4820:    /* test the ignore_not_found parameter for groups */
        1: 4821:    tcase_add_test(tc_sysdb, test_sysdb_remove_nonexistent_group);
        -: 4822:
        -: 4823:    /* Create incomplete groups - remove will fail if the LDB objects don't exist */
        1: 4824:    tcase_add_loop_test(tc_sysdb, test_sysdb_add_incomplete_group, 28000, 28010);
        1: 4825:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group_by_gid, 28000, 28010);
        -: 4826:
        -: 4827:    /* test custom operations */
        1: 4828:    tcase_add_loop_test(tc_sysdb, test_sysdb_store_custom, 29010, 29020);
        1: 4829:    tcase_add_test(tc_sysdb, test_sysdb_search_custom_by_name);
        1: 4830:    tcase_add_test(tc_sysdb, test_sysdb_update_custom);
        1: 4831:    tcase_add_test(tc_sysdb, test_sysdb_search_custom_update);
        1: 4832:    tcase_add_test(tc_sysdb, test_sysdb_search_custom);
        1: 4833:    tcase_add_test(tc_sysdb, test_sysdb_delete_custom);
        -: 4834:
        -: 4835:    /* test recursive delete */
        1: 4836:    tcase_add_test(tc_sysdb, test_sysdb_delete_recursive);
        -: 4837:
        1: 4838:    tcase_add_test(tc_sysdb, test_sysdb_attrs_replace_name);
        -: 4839:
        1: 4840:    tcase_add_test(tc_sysdb, test_sysdb_attrs_to_list);
        -: 4841:
        -: 4842:    /* Test unusual characters */
        1: 4843:    tcase_add_test(tc_sysdb, test_odd_characters);
        -: 4844:
        -: 4845:    /* Test sysdb enumerated flag */
        1: 4846:    tcase_add_test(tc_sysdb, test_sysdb_has_enumerated);
        -: 4847:
        -: 4848:    /* Test originalDN searches */
        1: 4849:    tcase_add_test(tc_sysdb, test_sysdb_original_dn_case_insensitive);
        -: 4850:
        -: 4851:    /* Test user and group renames */
        1: 4852:    tcase_add_test(tc_sysdb, test_group_rename);
        1: 4853:    tcase_add_test(tc_sysdb, test_user_rename);
        -: 4854:
        -: 4855:/* ===== NETGROUP TESTS ===== */
        -: 4856:
        -: 4857:    /* Create a new netgroup */
        1: 4858:    tcase_add_loop_test(tc_sysdb, test_sysdb_add_basic_netgroup, 27000, 27010);
        -: 4859:
        -: 4860:    /* Verify the netgroups were added */
        1: 4861:    tcase_add_loop_test(tc_sysdb, test_sysdb_search_netgroup_by_name, 27000, 27010);
        -: 4862:
        -: 4863:    /* Test setting attributes */
        1: 4864:    tcase_add_loop_test(tc_sysdb, test_sysdb_set_netgroup_attr, 27000, 27010);
        -: 4865:
        -: 4866:    /* Verify they have been changed */
        1: 4867:    tcase_add_loop_test(tc_sysdb, test_sysdb_get_netgroup_attr, 27000, 27010);
        -: 4868:
        -: 4869:    /* Remove half of them by name */
        1: 4870:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_netgroup_by_name, 27000, 27005);
        -: 4871:
        -: 4872:    /* Remove the other half by DN */
        1: 4873:    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_netgroup_entry, 27005, 27010);
        -: 4874:
        -: 4875:/* ===== SERVICE TESTS ===== */
        -: 4876:
        -: 4877:    /* Create a new service */
        1: 4878:    tcase_add_test(tc_sysdb, test_sysdb_add_services);
        1: 4879:    tcase_add_test(tc_sysdb, test_sysdb_store_services);
        1: 4880:    tcase_add_test(tc_sysdb, test_sysdb_svc_remove_alias);
        -: 4881:
        -: 4882:/* Add all test cases to the test suite */
        1: 4883:    suite_add_tcase(s, tc_sysdb);
        -: 4884:
        1: 4885:    TCase *tc_memberof = tcase_create("SYSDB member/memberof/memberuid Tests");
        -: 4886:
        1: 4887:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group, 0, 10);
        1: 4888:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_user, 0, 10);
        1: 4889:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_add_group_member,
        -: 4890:                        0, 10);
        1: 4891:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_memberuid,
        -: 4892:                        0, 10);
        1: 4893:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4894:                        MBO_GROUP_BASE + 5, MBO_GROUP_BASE + 6);
        1: 4895:    tcase_add_loop_test(tc_memberof,
        -: 4896:                        test_sysdb_memberof_check_memberuid_without_group_5,
        -: 4897:                        0, 10);
        1: 4898:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4899:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4900:
        1: 4901:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group, 0, 10);
        1: 4902:    tcase_add_test(tc_memberof, test_sysdb_memberof_close_loop);
        1: 4903:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_user, 0, 10);
        1: 4904:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_add_group_member,
        -: 4905:                        0, 10);
        1: 4906:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_memberuid_loop,
        -: 4907:                        0, 10);
        1: 4908:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4909:                        MBO_GROUP_BASE + 5, MBO_GROUP_BASE + 6);
        1: 4910:    tcase_add_loop_test(tc_memberof,
        -: 4911:                        test_sysdb_memberof_check_memberuid_loop_without_group_5,
        -: 4912:                        0, 10);
        1: 4913:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4914:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4915:
        -: 4916:    /* Ghost users tests */
        1: 4917:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
        -: 4918:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4919:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
        -: 4920:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4921:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_remove_child_group_and_check_ghost,
        -: 4922:                        MBO_GROUP_BASE + 1, MBO_GROUP_BASE + 10);
        -: 4923:    /* Only one group should be left now */
        1: 4924:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4925:                        MBO_GROUP_BASE + 9 , MBO_GROUP_BASE + 10);
        -: 4926:
        -: 4927:    /* ghost users - RFC2307 */
        -: 4928:    /* Add groups with ghost users */
        1: 4929:    tcase_add_loop_test(tc_memberof, test_sysdb_add_group_with_ghosts,
        -: 4930:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4931:    /* Check the ghost user attribute */
        1: 4932:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_ghost,
        -: 4933:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4934:    /* Add user entries, converting the ghost attributes to member attributes */
        -: 4935:    /* We only convert half of the users and keep the ghost attributes for the
        -: 4936:     * other half as we also want to test if we don't delete any ghost users
        -: 4937:     * by accident
        -: 4938:     */
        1: 4939:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_convert_to_real_users,
        -: 4940:                        MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS/2);
        -: 4941:    /* Check the members and ghosts are there as appropriate */
        1: 4942:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_convert,
        -: 4943:                        MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
        -: 4944:    /* Rename the other half */
        1: 4945:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_ghost_replace,
        -: 4946:                        MBO_GROUP_BASE + NUM_GHOSTS/2 + 1,
        -: 4947:                        MBO_GROUP_BASE + NUM_GHOSTS);
        -: 4948:    /* Attempt to replace with the same data to check if noop works correctly */
        1: 4949:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_ghost_replace_noop,
        -: 4950:                        MBO_GROUP_BASE + NUM_GHOSTS/2 + 1,
        -: 4951:                        MBO_GROUP_BASE + NUM_GHOSTS);
        -: 4952:    /* Remove the real users */
        1: 4953:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_user_cleanup,
        -: 4954:                        MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS/2);
        1: 4955:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4956:                        MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
        -: 4957:
        -: 4958:    /* ghost users - memberof mod_del */
        1: 4959:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
        -: 4960:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4961:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
        -: 4962:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4963:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_del,
        -: 4964:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4965:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4966:                        MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
        -: 4967:
        -: 4968:    /* ghost users - memberof mod_add */
        -: 4969:    /* Add groups without ghosts first */
        1: 4970:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group, 0, 10);
        -: 4971:    /* Add ghosts to groups so that they propagate */
        1: 4972:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_add,
        -: 4973:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4974:    /* Check if the ghosts in fact propagated */
        1: 4975:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
        -: 4976:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4977:    /* Clean up */
        1: 4978:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4979:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4980:
        -: 4981:    /* ghost users - replace */
        1: 4982:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
        -: 4983:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4984:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
        -: 4985:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4986:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_replace,
        -: 4987:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4988:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 4989:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4990:
        -: 4991:    /* ghost users - replace but retain inherited */
        1: 4992:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_double_ghosts,
        -: 4993:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        1: 4994:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_double_ghosts,
        -: 4995:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 4996:    /* This loop counts backwards so the indexing is a little odd */
        1: 4997:    tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_replace_keep,
        -: 4998:                        1 , 11);
        1: 4999:    tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
        -: 5000:                        MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
        -: 5001:
        1: 5002:    suite_add_tcase(s, tc_memberof);
        -: 5003:
        1: 5004:    TCase *tc_subdomain = tcase_create("SYSDB sub-domain Tests");
        -: 5005:
        1: 5006:    tcase_add_test(tc_subdomain, test_sysdb_subdomain_create);
        1: 5007:    tcase_add_test(tc_subdomain, test_sysdb_subdomain_store_user);
        1: 5008:    tcase_add_test(tc_subdomain, test_sysdb_subdomain_user_ops);
        1: 5009:    tcase_add_test(tc_subdomain, test_sysdb_subdomain_group_ops);
        -: 5010:
        1: 5011:    suite_add_tcase(s, tc_subdomain);
        -: 5012:
        -: 5013:#ifdef BUILD_AUTOFS
        1: 5014:    TCase *tc_autofs = tcase_create("SYSDB autofs Tests");
        -: 5015:
        1: 5016:    tcase_add_loop_test(tc_subdomain, test_autofs_create_map,
        -: 5017:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5018:
        1: 5019:    tcase_add_loop_test(tc_subdomain, test_autofs_retrieve_map,
        -: 5020:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5021:
        1: 5022:    tcase_add_loop_test(tc_subdomain, test_autofs_store_entry_in_map,
        -: 5023:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5024:
        1: 5025:    tcase_add_loop_test(tc_subdomain, test_autofs_retrieve_keys_by_map,
        -: 5026:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5027:
        1: 5028:    tcase_add_loop_test(tc_subdomain, test_autofs_delete_map,
        -: 5029:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5030:
        1: 5031:    tcase_add_loop_test(tc_subdomain, test_autofs_retrieve_map_neg,
        -: 5032:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5033:
        1: 5034:    tcase_add_loop_test(tc_subdomain, test_autofs_key_duplicate,
        -: 5035:                        TEST_AUTOFS_MAP_BASE, TEST_AUTOFS_MAP_BASE+10);
        -: 5036:
        1: 5037:    tcase_add_test(tc_subdomain, test_autofs_get_duplicate_keys);
        -: 5038:
        1: 5039:    suite_add_tcase(s, tc_autofs);
        -: 5040:#endif
        -: 5041:
        1: 5042:    return s;
        -: 5043:}
        -: 5044:
        1: 5045:int main(int argc, const char *argv[]) {
        -: 5046:    int opt;
        -: 5047:    int ret;
        -: 5048:    poptContext pc;
        -: 5049:    int failure_count;
        1: 5050:    int no_cleanup = 0;
        -: 5051:    Suite *sysdb_suite;
        -: 5052:    SRunner *sr;
        -: 5053:
        6: 5054:    struct poptOption long_options[] = {
        -: 5055:        POPT_AUTOHELP
        4: 5056:        SSSD_MAIN_OPTS
        -: 5057:        {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0,
        1: 5058:         _("Do not delete the test database after a test run"), NULL },
        -: 5059:        POPT_TABLEEND
        -: 5060:    };
        -: 5061:
        -: 5062:    /* Set debug level to invalid value so we can deside if -d 0 was used. */
        1: 5063:    debug_level = SSSDBG_INVALID;
        -: 5064:
        1: 5065:    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
        2: 5066:    while((opt = poptGetNextOpt(pc)) != -1) {
        -: 5067:        switch(opt) {
        -: 5068:        default:
    #####: 5069:            fprintf(stderr, "\nInvalid option %s: %s\n\n",
        -: 5070:                    poptBadOption(pc, 0), poptStrerror(opt));
    #####: 5071:            poptPrintUsage(pc, stderr, 0);
    #####: 5072:            return 1;
        -: 5073:        }
        -: 5074:    }
        1: 5075:    poptFreeContext(pc);
        -: 5076:
        1: 5077:    DEBUG_INIT(debug_level);
        -: 5078:
        1: 5079:    tests_set_cwd();
        -: 5080:
        1: 5081:    ret = unlink(TESTS_PATH"/"LOCAL_SYSDB_FILE);
        1: 5082:    if (ret != EOK && errno != ENOENT) {
    #####: 5083:        fprintf(stderr, "Could not delete the test ldb file (%d) (%s)\n",
    #####: 5084:                errno, strerror(errno));
    #####: 5085:        return EXIT_FAILURE;
        -: 5086:    }
        -: 5087:
        1: 5088:    sysdb_suite = create_sysdb_suite();
        1: 5089:    sr = srunner_create(sysdb_suite);
        -: 5090:    /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
        1: 5091:    srunner_run_all(sr, CK_ENV);
        1: 5092:    failure_count = srunner_ntests_failed(sr);
        1: 5093:    srunner_free(sr);
        1: 5094:    if (failure_count == 0 && !no_cleanup) {
        1: 5095:        ret = unlink(TESTS_PATH"/"TEST_CONF_FILE);
        1: 5096:        if (ret != EOK) {
    #####: 5097:            fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n",
    #####: 5098:                    errno, strerror(errno));
    #####: 5099:            return EXIT_FAILURE;
        -: 5100:        }
        1: 5101:        ret = unlink(TESTS_PATH"/"LOCAL_SYSDB_FILE);
        1: 5102:        if (ret != EOK) {
    #####: 5103:            fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n",
    #####: 5104:                    errno, strerror(errno));
    #####: 5105:            return EXIT_FAILURE;
        -: 5106:        }
        -: 5107:
        1: 5108:        return EXIT_SUCCESS;
        -: 5109:    }
    #####: 5110:    return  EXIT_FAILURE;
        -: 5111:}


More information about the sssd-devel mailing list