summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2011-11-08 16:30:36 +0100
committerPavel Březina <pbrezina@redhat.com>2011-11-21 16:12:13 +0100
commitfff5efcea89a021fd958918299517c870c7c933a (patch)
tree9d561464050fe9fd11210220404d1624587f00ba
parentfc36652d35b49383d17d4cdf4a68b5e29976784f (diff)
downloadsssd_unused-fff5efcea89a021fd958918299517c870c7c933a.tar.gz
sssd_unused-fff5efcea89a021fd958918299517c870c7c933a.tar.xz
sssd_unused-fff5efcea89a021fd958918299517c870c7c933a.zip
sudo sysdb interface: sudo commands
-rw-r--r--src/db/sysdb.c19
-rw-r--r--src/db/sysdb.h33
-rw-r--r--src/db/sysdb_ops.c221
-rw-r--r--src/tests/sysdb-tests.c131
4 files changed, 403 insertions, 1 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index c49399f7..ee8d2fc6 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -214,6 +214,25 @@ struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_c
return ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_NETGROUP_BASE, domain);
}
+struct ldb_dn *sysdb_sudocmd_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
+ const char *domain, const char *command)
+{
+ errno_t ret;
+ char *clean_command;
+ struct ldb_dn *dn;
+
+ ret = sysdb_dn_sanitize(NULL, command, &clean_command);
+ if (ret != EOK) {
+ return NULL;
+ }
+
+ dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_SUDOCMD,
+ clean_command, domain);
+ talloc_free(clean_command);
+
+ return dn;
+}
+
errno_t sysdb_get_rdn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
const char *_dn, char **_name, char **_val)
{
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 88767d3c..b1835e6d 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -36,14 +36,18 @@
#define SYSDB_GROUPS_CONTAINER "cn=groups"
#define SYSDB_CUSTOM_CONTAINER "cn=custom"
#define SYSDB_NETGROUP_CONTAINER "cn=Netgroups"
+#define SYSDB_SUDO_CONTAINER "cn=sudo"
+#define SYSDB_SUDOCMDS_CONTAINER "cn=sudocmds,"SYSDB_SUDO_CONTAINER
#define SYSDB_TMPL_USER_BASE SYSDB_USERS_CONTAINER",cn=%s,"SYSDB_BASE
#define SYSDB_TMPL_GROUP_BASE SYSDB_GROUPS_CONTAINER",cn=%s,"SYSDB_BASE
#define SYSDB_TMPL_CUSTOM_BASE SYSDB_CUSTOM_CONTAINER",cn=%s,"SYSDB_BASE
#define SYSDB_TMPL_NETGROUP_BASE SYSDB_NETGROUP_CONTAINER",cn=%s,"SYSDB_BASE
+#define SYSDB_TMPL_SUDOCMD_BASE SYSDB_SUDOCMDS_CONTAINER",cn=%s,"SYSDB_BASE
#define SYSDB_USER_CLASS "user"
#define SYSDB_GROUP_CLASS "group"
#define SYSDB_NETGROUP_CLASS "netgroup"
+#define SYSDB_SUDOCOMMAND_CLASS "sudoCommand"
#define SYSDB_NAME "name"
#define SYSDB_NAME_ALIAS "nameAlias"
@@ -163,6 +167,7 @@
#define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE
#define SYSDB_TMPL_GROUP SYSDB_NAME"=%s,"SYSDB_TMPL_GROUP_BASE
#define SYSDB_TMPL_NETGROUP SYSDB_NAME"=%s,"SYSDB_TMPL_NETGROUP_BASE
+#define SYSDB_TMPL_SUDOCMD SYSDB_NAME"=%s,"SYSDB_TMPL_SUDOCMD_BASE
#define SYSDB_TMPL_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE
#define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE
@@ -255,6 +260,8 @@ struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *sysdb, void *mem_ctx,
const char *domain, const char *name);
struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *sysdb, void *mem_ctx,
const char *domain);
+struct ldb_dn *sysdb_sudocmd_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
+ const char *domain, const char *command);
errno_t sysdb_group_dn_name(struct sysdb_ctx *sysdb, void *mem_ctx,
const char *dn_str, char **name);
struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *sysdb, void *mem_ctx,
@@ -429,6 +436,13 @@ int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
const char **attrs,
struct ldb_message **msg);
+/* Search sudo command (by command) */
+int sysdb_search_sudocmd(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *command,
+ const char **attrs,
+ struct ldb_message **msg);
+
/* Replace entry attrs */
int sysdb_set_entry_attr(struct sysdb_ctx *sysdb,
struct ldb_dn *entry_dn,
@@ -453,6 +467,12 @@ int sysdb_set_netgroup_attr(struct sysdb_ctx *sysdb,
struct sysdb_attrs *attrs,
int mod_op);
+/* Replace sudo command attrs */
+int sysdb_set_sudocmd_attr(struct sysdb_ctx *sysdb,
+ const char *command,
+ struct sysdb_attrs *attrs,
+ int mod_op);
+
/* Allocate a new id */
int sysdb_get_new_id(struct sysdb_ctx *sysdb,
uint32_t *id);
@@ -509,6 +529,16 @@ int sysdb_add_netgroup(struct sysdb_ctx *sysdb,
int cache_timeout,
time_t now);
+/* Add sudo command (only basic attrs and w/o checks) */
+int sysdb_add_basic_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command);
+
+int sysdb_add_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command,
+ struct sysdb_attrs *attrs,
+ int cache_timeout,
+ time_t now);
+
/* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */
int sysdb_mod_group_member(struct sysdb_ctx *sysdb,
struct ldb_dn *member_dn,
@@ -673,6 +703,9 @@ int sysdb_search_netgroups(TALLOC_CTX *mem_ctx,
int sysdb_delete_netgroup(struct sysdb_ctx *sysdb,
const char *name);
+int sysdb_delete_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command);
+
errno_t sysdb_attrs_to_list(TALLOC_CTX *mem_ctx,
struct sysdb_attrs **attrs,
int attr_count,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 3734bb18..3da41d61 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -387,7 +387,49 @@ done:
}
-/* =Search-Group-by-Name============================================ */
+/* =Search-Sudocmd================================================= */
+
+int sysdb_search_sudocmd(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *command,
+ const char **attrs,
+ struct ldb_message **msg)
+{
+ TALLOC_CTX *tmp_ctx;
+ static const char *def_attrs[] = { SYSDB_NAME, NULL };
+ struct ldb_message **msgs = NULL;
+ struct ldb_dn *basedn;
+ size_t msgs_count = 0;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ basedn = sysdb_sudocmd_dn(sysdb, tmp_ctx, sysdb->domain->name, command);
+ if (!basedn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
+ attrs?attrs:def_attrs, &msgs_count, &msgs);
+ if (ret) {
+ goto done;
+ }
+
+ *msg = talloc_steal(mem_ctx, msgs[0]);
+
+done:
+ if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+/* =Search-Netgroup-by-Name========================================= */
int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
@@ -580,6 +622,35 @@ done:
return ret;
}
+/* =Replace-Attributes-On-Sudo-Command======================================= */
+
+int sysdb_set_sudocmd_attr(struct sysdb_ctx *sysdb,
+ const char *command,
+ struct sysdb_attrs *attrs,
+ int mod_op)
+{
+ errno_t ret;
+ struct ldb_dn *dn;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ dn = sysdb_sudocmd_dn(sysdb, tmp_ctx, sysdb->domain->name, command);
+ if (!dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
/* =Get-New-ID============================================================ */
int sysdb_get_new_id(struct sysdb_ctx *sysdb,
@@ -1416,6 +1487,111 @@ done:
return ret;
}
+/* =Add-Basic-Sudo-Command-NO-CHECKS============================================= */
+
+int sysdb_add_basic_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command)
+{
+ struct ldb_message *msg;
+ int ret;
+
+ msg = ldb_msg_new(NULL);
+ if (!msg) {
+ return ENOMEM;
+ }
+
+ /* sudo command dn */
+ msg->dn = sysdb_sudocmd_dn(sysdb, msg, sysdb->domain->name, command);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD,
+ SYSDB_OBJECTCLASS, SYSDB_SUDOCOMMAND_CLASS);
+ if (ret) goto done;
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, command);
+ if (ret) goto done;
+
+ /* creation time */
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
+ (unsigned long) time(NULL));
+ if (ret) goto done;
+
+ ret = ldb_add(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(ret);
+
+done:
+ if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(msg);
+ return ret;
+}
+
+/* FIXME - cache timeout and thus now might not be needed, we might want to just
+ * always rewrite sudo rules */
+int sysdb_add_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command,
+ struct sysdb_attrs *attrs,
+ int cache_timeout,
+ time_t now)
+{
+ TALLOC_CTX *tmp_ctx;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = ldb_transaction_start(sysdb->ldb);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* try to add the sudo command */
+ ret = sysdb_add_basic_sudocmd(sysdb, command);
+ if (ret && ret != EEXIST) goto done;
+
+ if (!attrs) {
+ attrs = sysdb_new_attrs(tmp_ctx);
+ if (!attrs) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ if (!now) {
+ now = time(NULL);
+ }
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
+ if (ret) goto done;
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
+ ((cache_timeout) ?
+ (now + cache_timeout) : 0));
+ if (ret) goto done;
+
+ ret = sysdb_set_sudocmd_attr(sysdb, command, attrs, SYSDB_MOD_REP);
+
+done:
+ if (ret == EOK) {
+ ret = ldb_transaction_commit(sysdb->ldb);
+ ret = sysdb_error_to_errno(ret);
+ }
+
+ if (ret != EOK) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ ldb_transaction_cancel(sysdb->ldb);
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
/* if one of the basic attributes is empty ("") as opposed to NULL,
@@ -2426,6 +2602,49 @@ done:
return ret;
}
+/* =Delete-Sudocmd-================================================ */
+
+/* Do we need this? Or shall we delete the whole tree recursively? */
+int sysdb_delete_sudocmd(struct sysdb_ctx *sysdb,
+ const char *command)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message *msg;
+ int ret;
+
+ if (!command) return EINVAL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_search_sudocmd(tmp_ctx, sysdb,
+ command, NULL, &msg);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("sysdb_search_sudocmd failed: %d (%s)\n",
+ ret, strerror(ret)));
+ goto done;
+ } else if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("sudo command does not exist, nothing to delete\n"));
+ goto done;
+ }
+
+ ret = sysdb_delete_entry(sysdb, msg->dn, false);
+ if (ret != EOK) {
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
/* ========= Authentication against cached password ============ */
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 9c080c9e..96575582 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -166,6 +166,7 @@ struct test_data {
const char *username;
const char *groupname;
const char *netgrname;
+ const char *sudocmdname;
uid_t uid;
gid_t gid;
const char *shell;
@@ -479,6 +480,24 @@ static int test_set_netgroup_attr(struct test_data *data)
return ret;
}
+static int test_add_basic_sudocmd(struct test_data *data)
+{
+ return sysdb_add_basic_sudocmd(data->ctx->sysdb,
+ data->sudocmdname);
+}
+
+static int test_add_sudocmd(struct test_data *data)
+{
+ return sysdb_add_sudocmd(data->ctx->sysdb,
+ data->sudocmdname,
+ NULL, 30, 0);
+}
+
+static int test_remove_sudocmd(struct test_data *data)
+{
+ return sysdb_delete_sudocmd(data->ctx->sysdb, data->sudocmdname);
+}
+
START_TEST (test_sysdb_store_user)
{
struct sysdb_test_ctx *test_ctx;
@@ -2675,6 +2694,112 @@ START_TEST(test_sysdb_remove_netgroup_member)
}
END_TEST
+START_TEST (test_sysdb_add_basic_sudocmd)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ int ret;
+
+ /* Setup */
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ data = talloc_zero(test_ctx, struct test_data);
+ data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
+ data->uid = _i; /* This is kinda abuse of uid, though */
+ data->sudocmdname = talloc_asprintf(data, "testsudocmd%d", _i);
+
+ ret = test_add_basic_sudocmd(data);
+
+ fail_if(ret != EOK, "Could not add sudo command %s", data->sudocmdname);
+ talloc_free(test_ctx);
+}
+END_TEST
+
+START_TEST (test_sysdb_add_sudocmd)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ int ret;
+
+ /* Setup */
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ data = talloc_zero(test_ctx, struct test_data);
+ data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
+ data->uid = _i; /* This is kinda abuse of uid, though */
+ data->sudocmdname = talloc_asprintf(data, "testsudocmd%d", _i);
+
+ ret = test_add_sudocmd(data);
+ fail_if(ret != EOK, "Could not add sudo command %s", data->sudocmdname);
+ talloc_free(test_ctx);
+}
+END_TEST
+
+START_TEST (test_sysdb_search_sudocmd)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ int ret;
+ const char *sudocmdname;
+ struct ldb_message *msg;
+ struct ldb_dn *sudocmddn;
+
+ /* Setup */
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ sudocmdname = talloc_asprintf(test_ctx, "testsudocmd%d", _i);
+
+ ret = sysdb_search_sudocmd(test_ctx, test_ctx->sysdb,
+ sudocmdname, NULL, &msg);
+ fail_if(ret != EOK, "Could not find sudo command with name %s", sudocmdname);
+
+ sudocmddn = sysdb_sudocmd_dn(test_ctx->sysdb, test_ctx,
+ test_ctx->domain->name, sudocmdname);
+ fail_if(sudocmddn == NULL);
+ fail_if(ldb_dn_compare(msg->dn, sudocmddn) != 0, "Found wrong sudo command!\n");
+ talloc_free(test_ctx);
+}
+END_TEST
+
+START_TEST (test_sysdb_delete_sudocmd)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ int ret;
+
+ /* Setup */
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ data = talloc_zero(test_ctx, struct test_data);
+ data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
+ data->sudocmdname = talloc_asprintf(data, "testsudocmd%d", _i);
+
+ ret = test_remove_sudocmd(data);
+
+ fail_if(ret != EOK, "Could not remove sudo command with name %s", data->sudocmdname);
+ talloc_free(test_ctx);
+}
+END_TEST
+
START_TEST(test_odd_characters)
{
errno_t ret;
@@ -3052,6 +3177,12 @@ Suite *create_sysdb_suite(void)
/* Remove the other half by DN */
tcase_add_loop_test(tc_sysdb, test_sysdb_remove_netgroup_entry, 27005, 27010);
+/* ===== SUDO TESTS ===== */
+ tcase_add_loop_test(tc_sysdb, test_sysdb_add_basic_sudocmd, 27010, 27015);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_add_sudocmd, 27015, 27020);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_search_sudocmd, 27010, 27020);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_delete_sudocmd, 27010, 27020);
+
/* Add all test cases to the test suite */
suite_add_tcase(s, tc_sysdb);