summaryrefslogtreecommitdiffstats
path: root/src/db
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-09-09 16:23:36 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-10-13 09:49:37 -0400
commit1a3c4b9f378e3b04161e4f35b2efa5fae3d56a7b (patch)
tree72253ab5da05835f1c305f014a572727aa7aec15 /src/db
parent585fc61d6b972939fdee815cea7463007b9ff9fe (diff)
downloadsssd-1a3c4b9f378e3b04161e4f35b2efa5fae3d56a7b.tar.gz
sssd-1a3c4b9f378e3b04161e4f35b2efa5fae3d56a7b.tar.xz
sssd-1a3c4b9f378e3b04161e4f35b2efa5fae3d56a7b.zip
Netgroups sysdb API
Diffstat (limited to 'src/db')
-rw-r--r--src/db/sysdb.c6
-rw-r--r--src/db/sysdb.h109
-rw-r--r--src/db/sysdb_ops.c353
-rw-r--r--src/db/sysdb_search.c336
4 files changed, 802 insertions, 2 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index a2a94a5b7..454922693 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -52,6 +52,12 @@ struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_GROUP, name, domain);
}
+struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name)
+{
+ return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_NETGROUP, name, domain);
+}
+
errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
const char *_dn, char **_name)
{
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index d8a78badb..a2b842fe1 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -35,12 +35,15 @@
#define SYSDB_USERS_CONTAINER "cn=users"
#define SYSDB_GROUPS_CONTAINER "cn=groups"
#define SYSDB_CUSTOM_CONTAINER "cn=custom"
+#define SYSDB_NETGROUP_CONTAINER "cn=Netgroups"
#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_USER_CLASS "user"
#define SYSDB_GROUP_CLASS "group"
+#define SYSDB_NETGROUP_CLASS "netgroup"
#define SYSDB_NAME "name"
#define SYSDB_OBJECTCLASS "objectClass"
@@ -75,6 +78,9 @@
#define SYSDB_CACHE_EXPIRE "dataExpireTimestamp"
#define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp"
+#define SYSDB_NETGROUP_TRIPLE "netgroupTriple"
+#define SYSDB_DESCRIPTION "description"
+
#define SYSDB_CACHEDPWD "cachedPassword"
#define SYSDB_UUID "uniqueID"
@@ -92,6 +98,7 @@
#define SYSDB_UC "objectclass="SYSDB_USER_CLASS
#define SYSDB_GC "objectclass="SYSDB_GROUP_CLASS
+#define SYSDB_NC "objectclass="SYSDB_NETGROUP_CLASS
#define SYSDB_MPGC "|("SYSDB_UC")("SYSDB_GC")"
#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")("SYSDB_NAME"=%s))"
@@ -110,6 +117,9 @@
#define SYSDB_GETCACHED_FILTER "(&"SYSDB_UC")("SYSDB_LAST_LOGIN">=%lu))"
+#define SYSDB_NETGR_FILTER "(&("SYSDB_NC")("SYSDB_NAME"=%s))"
+#define SYSDB_NETGR_TRIPLES_FILTER "(|("SYSDB_NAME"=%s)("SYSDB_MEMBEROF"=%s))"
+
#define SYSDB_DEFAULT_ATTRS SYSDB_LAST_UPDATE, \
SYSDB_CACHE_EXPIRE, \
SYSDB_INITGR_EXPIRE, \
@@ -131,6 +141,10 @@
SYSDB_DEFAULT_ATTRS, \
NULL}
+#define SYSDB_NETGR_ATTRS {SYSDB_NAME, SYSDB_NETGROUP_TRIPLE, \
+ SYSDB_DEFAULT_ATTRS, \
+ NULL}
+
#define SYSDB_INITGR_ATTR SYSDB_MEMBEROF
#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, \
SYSDB_DEFAULT_ATTRS, \
@@ -138,6 +152,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_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE
#define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE
@@ -200,6 +215,8 @@ struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
const char *domain, const char *name);
struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
const char *domain, const char *name);
+struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name);
errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
const char *dn_str, char **name);
struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx,
@@ -282,6 +299,17 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
struct ldb_result **res);
+struct sysdb_netgroup_ctx {
+ char *hostname;
+ char *username;
+ char *domainname;
+};
+errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ struct ldb_result **res);
+
int sysdb_initgroups(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
@@ -295,6 +323,12 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
const char **attributes,
struct ldb_result **res);
+int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *netgrname,
+ const char **attributes,
+ struct ldb_result **res);
/* functions that modify the databse
* they have to be called within a transaction
@@ -336,7 +370,7 @@ int sysdb_search_user_by_uid(TALLOC_CTX *mem_ctx,
const char **attrs,
struct ldb_message **msg);
-/* Search Group (gy gid or name) */
+/* Search Group (by gid or name) */
int sysdb_search_group_by_name(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
@@ -351,6 +385,14 @@ int sysdb_search_group_by_gid(TALLOC_CTX *mem_ctx,
const char **attrs,
struct ldb_message **msg);
+/* Search Netgroup (by name) */
+int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char **attrs,
+ struct ldb_message **msg);
+
/* Replace entry attrs */
int sysdb_set_entry_attr(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
@@ -374,6 +416,13 @@ int sysdb_set_group_attr(TALLOC_CTX *mem_ctx,
struct sysdb_attrs *attrs,
int mod_op);
+/* Replace netgroup attrs */
+int sysdb_set_netgroup_attr(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ struct sysdb_attrs *attrs,
+ int mod_op);
+
/* Allocate a new id */
int sysdb_get_new_id(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
@@ -416,6 +465,18 @@ int sysdb_add_group(TALLOC_CTX *mem_ctx,
struct sysdb_attrs *attrs,
int cache_timeout);
+/* Add netgroup (only basic attrs and w/o checks) */
+int sysdb_add_basic_netgroup(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name, const char *description);
+
+int sysdb_add_netgroup(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char *description,
+ struct sysdb_attrs *attrs,
+ int cache_timeout);
+
/* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */
int sysdb_mod_group_member(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
@@ -460,6 +521,44 @@ errno_t sysdb_update_members(struct sysdb_ctx *sysdb,
const char **add_groups,
const char **del_groups);
+errno_t sysdb_add_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname);
+
+errno_t sysdb_remove_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname);
+
+errno_t sysdb_mod_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname,
+ int mod_op);
+
+errno_t sysdb_add_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup);
+
+errno_t sysdb_remove_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup);
+
+errno_t sysdb_mod_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup,
+ int mod_op);
+
/* Password caching function.
* If you are in a transaction ignore sysdb and pass in the handle.
* If you are not in a transaction pass NULL in handle and provide sysdb,
@@ -554,10 +653,18 @@ int sysdb_delete_group(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name, gid_t gid);
+int sysdb_delete_netgroup(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *name);
+
errno_t sysdb_attrs_to_list(TALLOC_CTX *memctx,
struct sysdb_attrs **attrs,
int attr_count,
const char *attr_name,
char ***_list);
+errno_t sysdb_netgr_to_triples(TALLOC_CTX *mem_ctx,
+ struct ldb_result *res,
+ struct sysdb_netgroup_ctx ***triples);
+
#endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 14af94889..373ce37f2 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -377,6 +377,49 @@ done:
}
+/* =Search-Group-by-Name============================================ */
+
+int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char **attrs,
+ struct ldb_message **msg)
+{
+ TALLOC_CTX *tmpctx;
+ static const char *def_attrs[] = { SYSDB_NAME, NULL };
+ struct ldb_message **msgs = NULL;
+ struct ldb_dn *basedn;
+ size_t msgs_count = 0;
+ int ret;
+
+ tmpctx = talloc_new(mem_ctx);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ basedn = sysdb_netgroup_dn(ctx, tmpctx, domain->name, name);
+ if (!basedn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmpctx, ctx, 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(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(tmpctx);
+ return ret;
+}
+
/* =Replace-Attributes-On-Entry=========================================== */
int sysdb_set_entry_attr(TALLOC_CTX *mem_ctx,
@@ -463,6 +506,35 @@ int sysdb_set_group_attr(TALLOC_CTX *mem_ctx,
return sysdb_set_entry_attr(mem_ctx, ctx, dn, attrs, mod_op);
}
+/* =Replace-Attributes-On-Netgroup=========================================== */
+
+int sysdb_set_netgroup_attr(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ 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_netgroup_dn(ctx, tmp_ctx, domain->name, name);
+ if (!dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_set_entry_attr(tmp_ctx, ctx, dn, attrs, mod_op);
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
/* =Get-New-ID============================================================ */
@@ -860,7 +932,7 @@ int sysdb_add_basic_group(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- /* user dn */
+ /* group dn */
msg->dn = sysdb_group_dn(ctx, msg, domain->name, name);
if (!msg->dn) {
ERROR_OUT(ret, ENOMEM, done);
@@ -1049,6 +1121,118 @@ fail:
return ret;
}
+/* =Add-Basic-Netgroup-NO-CHECKS============================================= */
+
+int sysdb_add_basic_netgroup(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name, const char *description)
+{
+ struct ldb_message *msg;
+ int ret;
+
+ msg = ldb_msg_new(NULL);
+ if (!msg) {
+ return ENOMEM;
+ }
+
+ /* netgroup dn */
+ msg->dn = sysdb_netgroup_dn(ctx, msg, domain->name, name);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD,
+ SYSDB_OBJECTCLASS, SYSDB_NETGROUP_CLASS);
+ if (ret) goto done;
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
+ if (ret) goto done;
+
+ if (description && *description) {
+ ret = add_string(msg, LDB_FLAG_MOD_ADD,
+ SYSDB_DESCRIPTION, description);
+ 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(ctx->ldb, msg);
+ ret = sysdb_error_to_errno(ret);
+
+done:
+ if (ret) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(msg);
+ return ret;
+}
+
+
+/* =Add-Netgroup-Function==================================================== */
+
+int sysdb_add_netgroup(struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char *description,
+ struct sysdb_attrs *attrs,
+ int cache_timeout)
+{
+ TALLOC_CTX *tmp_ctx;
+ time_t now;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = ldb_transaction_start(ctx->ldb);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* try to add the netgroup */
+ ret = sysdb_add_basic_netgroup(ctx, domain, name, description);
+ if (ret) goto done;
+
+ if (!attrs) {
+ attrs = sysdb_new_attrs(tmp_ctx);
+ if (!attrs) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ 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_netgroup_attr(ctx, domain, name, attrs, SYSDB_MOD_REP);
+
+done:
+ if (ret == EOK) {
+ ret = ldb_transaction_commit(ctx->ldb);
+ ret = sysdb_error_to_errno(ret);
+ }
+
+ if (ret != EOK) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ ldb_transaction_cancel(ctx->ldb);
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
@@ -1917,6 +2101,44 @@ fail:
return ret;
}
+/* =Delete-Netgroup-by-Name============================================== */
+
+int sysdb_delete_netgroup(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *name)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message *msg;
+ int ret;
+
+ if (!name) return EINVAL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_search_netgroup_by_name(tmp_ctx, sysdb,
+ domain, name, NULL, &msg);
+ if (ret != EOK) {
+ DEBUG(6, ("sysdb_search_netgroup_by_name failed: %d (%s)\n",
+ ret, strerror(ret)));
+ goto done;
+ }
+
+ ret = sysdb_delete_entry(sysdb, msg->dn, false);
+ if (ret != EOK) {
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
/* ========= Authentication against cached password ============ */
@@ -2255,3 +2477,132 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+errno_t sysdb_add_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname)
+{
+ return sysdb_mod_netgroup_tuple(sysdb, domain, netgroup, hostname,
+ username, domainname, SYSDB_MOD_ADD);
+}
+
+errno_t sysdb_remove_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname)
+{
+ return sysdb_mod_netgroup_tuple(sysdb, domain, netgroup, hostname,
+ username, domainname, SYSDB_MOD_DEL);
+}
+
+errno_t sysdb_mod_netgroup_tuple(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *hostname,
+ const char *username,
+ const char *domainname,
+ int mod_op)
+{
+ errno_t ret;
+ int lret;
+ struct ldb_message *msg;
+ char *triple;
+
+ msg = ldb_msg_new(NULL);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ msg->dn = sysdb_netgroup_dn(sysdb, msg, domain->name, netgroup);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ triple = talloc_asprintf(msg, "(%s,%s,%s)",
+ hostname, username, domainname);
+ if (!triple) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ ret = add_string(msg, mod_op, SYSDB_NETGROUP_TRIPLE, triple);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ lret = ldb_modify(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(lret);
+
+done:
+ if (ret) {
+ DEBUG(3, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_free(msg);
+ return ret;
+}
+
+errno_t sysdb_add_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup)
+{
+ return sysdb_mod_netgroup_member(sysdb, domain, netgroup,
+ member_netgroup, SYSDB_MOD_ADD);
+}
+
+errno_t sysdb_remove_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup)
+{
+ return sysdb_mod_netgroup_member(sysdb, domain, netgroup,
+ member_netgroup, SYSDB_MOD_DEL);
+}
+
+errno_t sysdb_mod_netgroup_member(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ const char *member_netgroup,
+ int mod_op)
+{
+ errno_t ret;
+ int lret;
+ struct ldb_message *msg;
+ char *member;
+
+ msg = ldb_msg_new(NULL);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ msg->dn = sysdb_netgroup_dn(sysdb, msg, domain->name, netgroup);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ member = talloc_asprintf(msg, SYSDB_TMPL_NETGROUP,
+ member_netgroup, domain->name);
+ if (!member) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = add_string(msg, mod_op, SYSDB_MEMBER, member);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ lret = ldb_modify(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(lret);
+
+done:
+ if (ret) {
+ DEBUG(3, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_free(msg);
+ return ret;
+}
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index a24ea5b17..91519e3aa 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -23,6 +23,7 @@
#include "db/sysdb_private.h"
#include "confdb/confdb.h"
#include <time.h>
+#include <ctype.h>
/* users */
@@ -503,3 +504,338 @@ done:
talloc_zfree(tmpctx);
return ret;
}
+
+/* This function splits a three-tuple into three strings
+ * It assumes that any whitespace between the parentheses
+ * and commas are intentional and does not attempt to
+ * strip them out. Leading and trailing whitespace is
+ * ignored.
+ *
+ * This behavior is compatible with nss_ldap's
+ * implementation.
+ */
+static errno_t sysdb_netgr_split_triple(TALLOC_CTX *mem_ctx,
+ const char *triple,
+ char **hostname,
+ char **username,
+ char **domainname)
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ const char *p = triple;
+ const char *p_host;
+ const char *p_user;
+ const char *p_domain;
+ size_t len;
+
+ char *host = NULL;
+ char *user = NULL;
+ char *domain = NULL;
+
+ /* Pre-set the values to NULL here so if they are not
+ * copied, we don't return garbage below.
+ */
+ *hostname = NULL;
+ *username = NULL;
+ *domainname = NULL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ /* Remove any leading whitespace */
+ while (*p && isspace(*p)) p++;
+
+ if (*p != '(') {
+ /* Triple must start and end with parentheses */
+ ret = EINVAL;
+ goto done;
+ }
+ p++;
+ p_host = p;
+
+ /* Find the first comma */
+ while (*p && *p != ',') p++;
+
+ if (!*p) {
+ /* No comma was found: parse error */
+ ret = EINVAL;
+ goto done;
+ }
+
+ len = p - p_host;
+
+ if (len > 0) {
+ /* Copy the host string */
+ host = talloc_strndup(tmp_ctx, p_host, len);
+ if (!host) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ p++;
+ p_user = p;
+
+ /* Find the second comma */
+ while (*p && *p != ',') p++;
+
+ if (!*p) {
+ /* No comma was found: parse error */
+ ret = EINVAL;
+ goto done;
+ }
+
+ len = p - p_user;
+
+ if (len > 0) {
+ /* Copy the user string */
+ user = talloc_strndup(tmp_ctx, p_user, len);
+ if (!user) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ p++;
+ p_domain = p;
+
+ /* Find the closing parenthesis */
+ while (*p && *p != ')') p++;
+ if (*p != ')') {
+ /* No trailing parenthesis: parse error */
+ ret = EINVAL;
+ goto done;
+ }
+
+ len = p - p_domain;
+
+ if (len > 0) {
+ /* Copy the domain string */
+ domain = talloc_strndup(tmp_ctx, p_domain, len);
+ if (!domain) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ p++;
+
+ /* skip trailing whitespace */
+ while (*p && isspace(*p)) p++;
+
+ if (*p) {
+ /* Extra data after the closing parenthesis
+ * is a parse error
+ */
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* Return any non-NULL values */
+ if (host) {
+ *hostname = talloc_steal(mem_ctx, host);
+ }
+
+ if (user) {
+ *username = talloc_steal(mem_ctx, user);
+ }
+
+ if (domain) {
+ *domainname = talloc_steal(mem_ctx, domain);
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_netgr_to_triples(TALLOC_CTX *mem_ctx,
+ struct ldb_result *res,
+ struct sysdb_netgroup_ctx ***triples)
+{
+ errno_t ret;
+ size_t size = 0;
+ char *triple_str;
+ TALLOC_CTX *tmp_ctx;
+ struct sysdb_netgroup_ctx **tmp_triples = NULL;
+ struct ldb_message_element *el;
+ int i, j;
+
+ if(!res || res->count == 0) {
+ return ENOENT;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ for (i=0; i < res->count; i++) {
+ el = ldb_msg_find_element(res->msgs[i], SYSDB_NETGROUP_TRIPLE);
+ if (!el) {
+ /* No triples in this netgroup. It might be a nesting
+ * container only.
+ * Skip it and continue on.
+ */
+ continue;
+ }
+
+ /* Enlarge the array by the value count
+ * Always keep one extra entry for the NULL terminator
+ */
+ tmp_triples = talloc_realloc(tmp_ctx, tmp_triples,
+ struct sysdb_netgroup_ctx *,
+ size+el->num_values+1);
+ if (!tmp_triples) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Copy in all of the triples */
+ for(j = 0; j < el->num_values; j++) {
+ triple_str = talloc_strndup(tmp_ctx,
+ (const char *)el->values[j].data,
+ el->values[j].length);
+ if (!triple_str) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tmp_triples[size] = talloc_zero(tmp_triples,
+ struct sysdb_netgroup_ctx);
+ if (!tmp_triples[size]) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_netgr_split_triple(tmp_triples[size],
+ triple_str,
+ &tmp_triples[size]->hostname,
+ &tmp_triples[size]->username,
+ &tmp_triples[size]->domainname);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ size++;
+ }
+ }
+
+ if (!tmp_triples) {
+ /* No entries were found
+ * Create a dummy reply
+ */
+ tmp_triples = talloc_array(tmp_ctx, struct sysdb_netgroup_ctx *, 1);
+ if (!tmp_triples) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ /* Add NULL terminator */
+ tmp_triples[size] = NULL;
+
+ *triples = talloc_steal(mem_ctx, tmp_triples);
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *netgroup,
+ struct ldb_result **res)
+{
+ TALLOC_CTX *tmp_ctx;
+ static const char *attrs[] = SYSDB_NETGR_ATTRS;
+ struct ldb_dn *base_dn;
+ struct ldb_result *result;
+ char *netgroup_dn;
+ int lret;
+ errno_t ret;
+
+ if (!domain) {
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ base_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
+ SYSDB_TMPL_NETGROUP_BASE,
+ domain->name);
+ if (!base_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ netgroup_dn = talloc_asprintf(tmp_ctx, SYSDB_TMPL_NETGROUP,
+ netgroup, domain->name);
+ if (!netgroup_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ lret = ldb_search(ctx->ldb, tmp_ctx, &result, base_dn,
+ LDB_SCOPE_SUBTREE, attrs,
+ SYSDB_NETGR_TRIPLES_FILTER,
+ netgroup, netgroup_dn);
+ ret = sysdb_error_to_errno(lret);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ *res = talloc_steal(mem_ctx, result);
+ ret = EOK;
+
+done:
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *ctx,
+ struct sss_domain_info *domain,
+ const char *netgrname,
+ const char **attributes,
+ struct ldb_result **res)
+{
+ TALLOC_CTX *tmpctx;
+ struct ldb_dn *base_dn;
+ struct ldb_result *result;
+ int ret;
+
+ if (!domain) {
+ return EINVAL;
+ }
+
+ tmpctx = talloc_new(mem_ctx);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
+ SYSDB_TMPL_NETGROUP_BASE, domain->name);
+ if (!base_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_search(ctx->ldb, tmpctx, &result, base_dn,
+ LDB_SCOPE_SUBTREE, attributes,
+ SYSDB_NETGR_FILTER, netgrname);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+
+ *res = talloc_steal(mem_ctx, result);
+done:
+ talloc_zfree(tmpctx);
+ return ret;
+}