/*
SSSD
System Database
Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <check.h>
#include <talloc.h>
#include <tevent.h>
#include <popt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "util/util.h"
#include "confdb/confdb_setup.h"
#include "db/sysdb_private.h"
#include "tests/common.h"
#define TESTS_PATH "tests_sysdb"
#define TEST_CONF_FILE "tests_conf.ldb"
#define TEST_ATTR_NAME "test_attr_name"
#define TEST_ATTR_VALUE "test_attr_value"
#define TEST_ATTR_UPDATE_VALUE "test_attr_update_value"
#define TEST_ATTR_ADD_NAME "test_attr_add_name"
#define TEST_ATTR_ADD_VALUE "test_attr_add_value"
#define CUSTOM_TEST_CONTAINER "custom_test_container"
#define CUSTOM_TEST_OBJECT "custom_test_object"
#define ASQ_TEST_USER "testuser27010"
#define ASQ_TEST_USER_UID 27010
#define MBO_USER_BASE 27500
#define MBO_GROUP_BASE 28500
struct sysdb_test_ctx {
struct sysdb_ctx *sysdb;
struct confdb_ctx *confdb;
struct tevent_context *ev;
struct sss_domain_info *domain;
};
static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
{
struct sysdb_test_ctx *test_ctx;
char *conf_db;
int ret;
const char *val[2];
val[1] = NULL;
/* Create tests directory if it doesn't exist */
/* (relative to current dir) */
ret = mkdir(TESTS_PATH, 0775);
if (ret == -1 && errno != EEXIST) {
fail("Could not create %s directory", TESTS_PATH);
return EFAULT;
}
test_ctx = talloc_zero(NULL, struct sysdb_test_ctx);
if (test_ctx == NULL) {
fail("Could not allocate memory for test context");
return ENOMEM;
}
/* Create an event context
* It will not be used except in confdb_init and sysdb_init
*/
test_ctx->ev = tevent_context_init(test_ctx);
if (test_ctx->ev == NULL) {
fail("Could not create event context");
talloc_free(test_ctx);
return EIO;
}
conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE);
if (conf_db == NULL) {
fail("Out of memory, aborting!");
talloc_free(test_ctx);
return ENOMEM;
}
DEBUG(3, ("CONFDB: %s\n", conf_db));
/* Connect to the conf db */
ret = confdb_init(test_ctx, &test_ctx->confdb, conf_db);
if (ret != EOK) {
fail("Could not initialize connection to the confdb");
talloc_free(test_ctx);
return ret;
}
val[0] = "LOCAL";
ret = confdb_add_param(test_ctx->confdb, true,
"config/sssd", "domains", val);
if (ret != EOK) {
fail("Could not initialize domains placeholder");
talloc_free(test_ctx);
return ret;
}
val[0] = "local";
ret = confdb_add_param(test_ctx->confdb, true,
"config/domain/LOCAL", "id_provider", val);
if (ret != EOK) {
fail("Could not initialize provider");
talloc_free(test_ctx);
return ret;
}
val[0] = "TRUE";
ret = confdb_add_param(test_ctx->confdb, true,
"config/domain/LOCAL", "enumerate", val);
if (ret != EOK) {
fail("Could not initialize LOCAL domain");
talloc_free(test_ctx);
return ret;
}
val[0] = "TRUE";
ret = confdb_add_param(test_ctx->confdb, true,
"config/domain/LOCAL", "cache_credentials", val);
if (ret != EOK) {
fail("Could not initialize LOCAL domain");
talloc_free(test_ctx);
return ret;
}
ret = confdb_get_domain(test_ctx->confdb, "local", &test_ctx->domain);
if (ret != EOK) {
fail("Could not retrieve LOCAL domain");
talloc_free(test_ctx);
return ret;
}
ret = sysdb_domain_init(test_ctx,
test_ctx->domain, TESTS_PATH, &test_ctx->sysdb);
if (ret != EOK) {
fail("Could not initialize connection to the sysdb (%d)", ret);
talloc_free(test_ctx);
return ret;
}
*ctx = test_ctx;
return EOK;
}
struct test_data {
struct tevent_context *ev;
struct sysdb_test_ctx *ctx;
const char *username;
const char *groupname;
const char *netgrname;
uid_t uid;
gid_t gid;
const char *shell;
bool finished;
int error;
struct sysdb_attrs *attrs;
const char **attrlist;
struct ldb_message *msg;
size_t msgs_count;
struct ldb_message **msgs;
};
static int test_add_user(struct test_data *data)
{
char *homedir;
char *gecos;
int ret;
homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
gecos = talloc_asprintf(data, "Test User %d", data->uid);
ret = sysdb_add_user(data, data->ctx->sysdb,
data->ctx->domain, data->username,
data->uid, 0, gecos, homedir, "/bin/bash",
NULL, 0);
return ret;
}
static int test_store_user(struct test_data *data)
{
char *homedir;
char *gecos;
int ret;
homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
gecos = talloc_asprintf(data, "Test User %d", data->uid);
ret = sysdb_store_user(data, data->ctx->sysdb,
data->ctx->domain, data->username, "x",
data->uid, 0, gecos, homedir,
data->shell ? data->shell : "/bin/bash",
NULL, -1);
return ret;
}
static int test_remove_user(struct test_data *data)
{
struct ldb_dn *user_dn;
int ret;
user_dn = sysdb_user_dn(data->ctx->sysdb, data, "LOCAL", data->username);
if (!user_dn) return ENOMEM;
ret = sysdb_delete_entry(data->ctx->sysdb, user_dn, true);
return ret;
}
static int test_remove_user_by_uid(struct test_data *data)
{
int ret;
ret = sysdb_delete_user(data, data->ctx->sysdb,
data->ctx->domain, NULL, data->uid);
return ret;
}
static int test_remove_nonexistent_group(struct test_data *data)
{
int ret;
ret = sysdb_delete_group(data, data->ctx->sysdb,
data->ctx->domain, NULL, data->uid);
return ret;
}
static int test_remove_nonexistent_user(struct test_data *data)
{
int ret;
ret = sysdb_delete_user(data, data->ctx->sysdb,
data->ctx->domain, NULL, data->uid);
return ret;
}
static int test_add_group(struct test_data *data)
{
int ret;
ret = sysdb_add_group(data, data->ctx->sysdb,
data->ctx->domain, data->groupname,
data->gid, NULL, 0);
return ret;
}
static int test_add_incomplete_group(struct test_data *data)
{
int ret;
ret = sysdb_add_incomplete_group(data->ctx->sysdb, data->ctx->domain,
data->groupname, data->gid);
return ret;
}
static int test_store_group(struct test_data *data)
{
int ret;
ret = sysdb_store_group(data, data->ctx->sysdb,
data->ctx->domain, data->groupname,
data->gid, NULL, -1);
return ret;
}
static int test_remove_group(struct test_data *data)
{
struct ldb_dn *group_dn;
int ret;
group_dn = sysdb_group_dn(data->ctx->sysdb, data, "LOCAL", data->groupname);
if (!group_dn) return ENOMEM;
ret = sysdb_delete_entry(data->ctx->sysdb, group_dn, true);
return ret;
}
static int test_remove_group_by_gid(struct test_data *data)
{
int ret;
ret = sysdb_delete_group(data, data->ctx->sysdb,
data->ctx->domain, NULL, data->gid);
if (ret == ENOENT) {
ret = EOK;
}
return ret;
}
static int test_set_user_attr(struct test_data *data)
{
int ret;
ret = sysdb_set_user_attr(data, data->ctx->sysdb,
data->ctx->domain, data->username,
data->attrs, SYSDB_MOD_REP);
return ret;
}
static int test_add_group_member(struct test_data *data)
{
const char *username;
int ret;
username = talloc_asprintf(data, "testuser%d", data->uid);
if (username == NULL) {
return ENOMEM;
}
ret = sysdb_add_group_member(data->ctx->sysdb,
data->ctx->domain,
data->groupname, username,
SYSDB_MEMBER_USER);
return ret;
}
static int test_remove_group_member(struct test_data *data)
{
const char *username;
int ret;
username = talloc_asprintf(data, "testuser%d", data->uid);
if (username == NULL) {
return ENOMEM;
}
ret = sysdb_remove_group_member(data->ctx->sysdb,
|