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:49 -0400
commitb4706b56a7921909290a12929f4256a352fc7138 (patch)
tree8545ff35b9f69f7af8848ecf5e84d42e8cb7ea24
parent9c5f876a31ac48c670ae184d452cf5c8f3abbd9d (diff)
downloadsssd-b4706b56a7921909290a12929f4256a352fc7138.tar.gz
sssd-b4706b56a7921909290a12929f4256a352fc7138.tar.xz
sssd-b4706b56a7921909290a12929f4256a352fc7138.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 9c239b2de..4f59d9d6a 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -2038,3 +2038,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);