summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2011-03-16 12:29:37 -0400
committerStephen Gallagher <sgallagh@redhat.com>2011-03-23 04:58:37 -0400
commitd86c2d2995933d61fc3c63f74ec260b5c8c75bf9 (patch)
treeb480ea82383bedf7408bed830fd1c658486cb02f
parent42d8e67c26df2b7660507d26b9a50911bdd3cf18 (diff)
downloadsssd-d86c2d2995933d61fc3c63f74ec260b5c8c75bf9.tar.gz
sssd-d86c2d2995933d61fc3c63f74ec260b5c8c75bf9.tar.xz
sssd-d86c2d2995933d61fc3c63f74ec260b5c8c75bf9.zip
Add sysdb_attrs_primary_name()
This function will check a sysdb_attrs struct for the primary name of the entity it represents. If there are multiple entries, it will pick the one that matches the RDN. If none match, it will throw an error.
-rw-r--r--src/db/sysdb.c102
-rw-r--r--src/db/sysdb.h4
2 files changed, 106 insertions, 0 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 34c65dfab..ef9d0a237 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -2154,3 +2154,105 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs,
+ const char *ldap_attr,
+ const char **_primary)
+{
+ errno_t ret;
+ char *rdn_attr = NULL;
+ char *rdn_val = NULL;
+ struct ldb_message_element *sysdb_name_el;
+ struct ldb_message_element *orig_dn_el;
+ size_t i;
+ TALLOC_CTX *tmpctx = NULL;
+
+ tmpctx = talloc_new(NULL);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_get_el(attrs,
+ SYSDB_NAME,
+ &sysdb_name_el);
+ if (sysdb_name_el->num_values == 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (sysdb_name_el->num_values == 1) {
+ /* Entry contains only one name. Just return that */
+ *_primary = (const char *)sysdb_name_el->values[0].data;
+ ret = EOK;
+ goto done;
+ }
+
+ /* Multiple values for name. Check whether one matches the RDN */
+
+ ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
+ if (ret) {
+ goto done;
+ }
+ if (orig_dn_el->num_values == 0) {
+ DEBUG(7, ("Original DN is not available.\n"));
+ } else if (orig_dn_el->num_values == 1) {
+ ret = sysdb_get_rdn(sysdb, tmpctx,
+ (const char *) orig_dn_el->values[0].data,
+ &rdn_attr,
+ &rdn_val);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not get rdn from [%s]\n",
+ (const char *) orig_dn_el->values[0].data));
+ goto done;
+ }
+ } else {
+ DEBUG(1, ("Should not have more than one origDN\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* First check whether the attribute name matches */
+ DEBUG(8, ("Comparing attribute names [%s] and [%s]\n",
+ rdn_attr, ldap_attr));
+ if (strcasecmp(rdn_attr, ldap_attr) != 0) {
+ /* Multiple entries, and the RDN attribute doesn't match.
+ * We have no way of resolving this deterministically,
+ * so we'll punt.
+ */
+ DEBUG(1, ("Cannot save entry. It has multiple names and the RDN "
+ "attribute does not match\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ for (i = 0; i < sysdb_name_el->num_values; i++) {
+ if (strcasecmp(rdn_val,
+ (const char *)sysdb_name_el->values[i].data) == 0) {
+ /* This name matches the RDN. Use it */
+ break;
+ }
+ }
+ if (i < sysdb_name_el->num_values) {
+ /* Match was found */
+ *_primary = (const char *)sysdb_name_el->values[i].data;
+ } else {
+ /* If we can't match the name to the RDN, we just have to
+ * throw up our hands. There's no deterministic way to
+ * decide which name is correct.
+ */
+ DEBUG(1, ("Cannot save entry. Unable to determine groupname\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
+ ret, strerror(ret)));
+ }
+ talloc_free(tmpctx);
+ return ret;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index caef6163e..e98426551 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -215,6 +215,10 @@ int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs,
const char *domain,
struct ldb_val *values,
int num_values);
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs,
+ const char *ldap_attr,
+ const char **_primary);
/* convert an ldb error into an errno error */
int sysdb_error_to_errno(int ldberr);