/*
SSSD
System Database - View and Override related calls
Copyright (C) 2014 Sumit Bose <sbose@redhat.com>
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 "util/util.h"
#include "util/cert.h"
#include "db/sysdb_private.h"
/* In general is should not be possible that there is a view container without
* a view name set. But to be on the safe side we return both information
* separately. */
static errno_t sysdb_get_view_name_ex(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
char **_view_name,
bool *view_container_exists)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
const char *tmp_str;
struct ldb_dn *view_base_dn;
struct ldb_result *res;
const char *attrs[] = {SYSDB_VIEW_NAME,
NULL};
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
view_base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_BASE);
if (view_base_dn == NULL) {
ret = EIO;
goto done;
}
ret = ldb_search(sysdb->ldb, tmp_ctx, &res, view_base_dn, LDB_SCOPE_BASE,
attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = EIO;
goto done;
}
if (res->count > 1) {
DEBUG(SSSDBG_OP_FAILURE, "Base search returned [%d] results, "
"expected 1.\n", res->count);
ret = EINVAL;
goto done;
}
if (res->count == 0) {
*view_container_exists = false;
ret = ENOENT;
goto done;
} else {
*view_container_exists = true;
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_VIEW_NAME,
NULL);
if (tmp_str == NULL) {
ret = ENOENT;
goto done;
}
}
*_view_name = talloc_steal(mem_ctx, discard_const(tmp_str));
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
char **view_name)
{
bool view_container_exists;
return sysdb_get_view_name_ex(mem_ctx, sysdb, view_name,
&view_container_exists);
}
errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb,
const char *view_name)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
char *tmp_str;
bool view_container_exists = false;
bool add_view_name = false;
struct ldb_message *msg;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = sysdb_get_view_name_ex(tmp_ctx, sysdb, &tmp_str,
&view_container_exists);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name_ex failed.\n");
goto done;
}
if (ret == EOK) {
if (strcmp(tmp_str, view_name) == 0) {
/* view name already known, nothing to do */
DEBUG(SSSDBG_TRACE_ALL, "View name already in place.\n");
ret = EOK;
goto done;
} else {
/* view name changed */
DEBUG(SSSDBG_CONF_SETTINGS,
"View name changed from [%s] to [%s].\n", tmp_str, view_name);
}
} else {
add_view_name = true;
}
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
ret = ENOMEM;
goto done;
}
msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_BASE);
if (msg->dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = EIO;
goto done;
}
ret = ldb_msg_add_empty(msg, SYSDB_VIEW_NAME,
add_view_name ? LDB_FLAG_MOD_ADD
: LDB_FLAG_MOD_REPLACE,
NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_VIEW_NAME, view_name);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (view_container_exists) {
ret = ldb_modify(sysdb->ldb, msg);
} else {
ret = ldb_add(sysdb->ldb, msg);
}
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Failed to %s view container [%s](%d)[%s]\n",
view_container_exists ? "modify" : "add",
ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name)
{
struct ldb_dn *dn;
TALLOC_CTX *tmp_ctx;
int ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_SEARCH_BASE,
view_name);
if (dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
ret = EIO;
goto done;
}
ret = sysdb_delete_recursive(sysdb, dn, true);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb)
{
int ret;
int sret;
TALLOC_CTX *tmp_ctx;
bool in_transaction = false;
struct ldb_result *res;
size_t c;
struct ldb_message *msg;
struct ldb_dn *base_dn;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
ret = ENOMEM;
goto done;
}
base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed\n");
ret = ENOMEM;
goto done;
}
ret = ldb_msg_add_empty(msg, SYSDB_CACHE_EXPIRE, LDB_FLAG_MOD_REPLACE,
NULL);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_CACHE_EXPIRE, "1");
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = sysdb_transaction_start(sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
goto done;
}
in_transaction = true;
ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
NULL, "%s", SYSDB_UC);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
for (c = 0; c < res->count; c++) {
msg->dn = res->msgs[c]->dn;
ret = ldb_modify(sysdb->ldb, msg);
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_modify failed: [%s](%d)[%s]\n",
ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
}
talloc_free(res);
ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
NULL, "%s", SYSDB_GC);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
for (c = 0; c < res->count; c++) {
msg->dn = res->msgs[c]->dn;
ret = ldb_modify(sysdb->ldb, msg);
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_modify failed: [%s](%d)[%s]\n",
ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
}
ret = EOK;
done:
if (in_transaction) {
if (ret == EOK) {
sret = sysdb_transaction_commit(sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed, " \
"nothing we can do about.\n");
ret = sret;
}
} else {
sret = sysdb_transaction_cancel(sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed, " \
"nothing we can do about.\n");
}
}
}
talloc_free(tmp_ctx);
return ret;
}
static errno_t
add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
struct sysdb_attrs *attrs,
bool add_name,
const char *name_override)
{
int ret;
if (add_name) {
ret = sysdb_attrs_add_string(attrs, SYSDB_DEFAULT_OVERRIDE_NAME,
name_override);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n");
return ret;
}
}
if (!domain->case_sensitive) {
ret = sysdb_attrs_add_lc_name_alias(attrs, name_override);
} else {
ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, name_override);
}
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n");
return ret;
}
return EOK;
}
errno_t sysdb_store_override(struct sss_domain_info *domain,
const char *view_name,
enum sysdb_member_type type,
struct sysdb_attrs *attrs, struct ldb_dn *obj_dn)
{
TALLOC_CTX *tmp_ctx;
const char *anchor;
int ret;
struct ldb_dn *override_dn;
const char *override_dn_str;
const char *obj_dn_str;
const char *obj_attrs[] = { SYSDB_OBJECTCLASS,
SYSDB_OVERRIDE_DN,
NULL};
size_t count = 0;
struct ldb_message **msgs;
struct ldb_message *msg = NULL;
const char *obj_override_dn;
bool add_ref = true;
size_t c;
bool in_transaction = false;
bool has_override = true;
const char *name_override;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
if (attrs != NULL) {
has_override = true;
ret = sysdb_attrs_get_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
&anchor);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing anchor in override attributes.\n");
ret = EINVAL;
goto done;
}
override_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_OVERRIDE, anchor, view_name);
if (override_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
ret = ENOMEM;
goto done;
}
} else {
/* if there is no override for the given object, just store the DN of
* the object iself in the SYSDB_OVERRIDE_DN attribute to indicate
* that it was checked if an override exists and none was found. */
has_override = false;
override_dn = obj_dn;
}
override_dn_str = ldb_dn_get_linearized(override_dn);
obj_dn_str = ldb_dn_get_linearized(obj_dn);
if (override_dn_str == NULL || obj_dn_str == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
ret = ENOMEM;
goto done;
}
ret = sysdb_search_entry(tmp_ctx, domain->sysdb, obj_dn, LDB_SCOPE_BASE,
NULL, obj_attrs, &count, &msgs);
if (ret != EOK) {
if (ret == ENOENT) {
DEBUG(SSSDBG_CRIT_FAILURE, "Object to override does not exists.\n");
} else {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
}
goto done;
}
if (count != 1) {
DEBUG(SSSDBG_CRIT_FAILURE, "Base searched returned more than one object.\n");
ret = EINVAL;
goto done;
}
obj_override_dn = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OVERRIDE_DN,
NULL);
if (obj_override_dn != NULL) {
/* obj_override_dn can either point to the object itself, i.e there is
* no override, or to a overide object. This means it can change from
* the object DN to a override DN and back but not from one override
* DN to a different override DN. If the new and the old DN are the
* same we do not need to update the original object. */
if (strcmp(obj_override_dn, override_dn_str) != 0) {
if (strcmp(obj_override_dn, obj_dn_str) != 0
&& strcmp(override_dn_str, obj_dn_str) != 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Existing [%s] and new [%s] override DN do not match.\n",
obj_override_dn, override_dn_str);
ret = EINVAL;
goto done;
}
} else {
add_ref = false;
}
}
ret = ldb_transaction_start(domain->sysdb->ldb);
if (ret != EOK) {
return sysdb_error_to_errno(ret);
}
in_transaction = true;
if (has_override) {
ret = ldb_delete(domain->sysdb->ldb, override_dn);
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_ALL,
"ldb_delete failed, maybe object did not exist. Ignoring.\n");
}
ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name_override);
if (ret == EOK) {
ret = add_name_and_aliases_for_name_override(domain, attrs, false,
name_override);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"add_name_and_aliases_for_name_override failed.\n");
goto done;
}
} else if (ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
ret = ENOMEM;
goto done;
}
msg->dn = override_dn;
msg->elements = talloc_array(msg, struct ldb_message_element,
attrs->num);
if (msg->elements == NULL) {
ret = ENOMEM;
goto done;
}
for (c = 0; c < attrs->num; c++) {
/* Set num_values to 1 because by default user and group overrides
* use the same attribute name for the GID and this cause SSSD
* machinery to add the same value twice */
if (attrs->a[c].num_values > 1
&& strcmp(attrs->a[c].name, SYSDB_GIDNUM) == 0) {
attrs->a[c].num_values = 1;
}
msg->elements[c] = attrs->a[c];
msg->elements[c].flags = LDB_FLAG_MOD_ADD;
}
msg->num_elements = attrs->num;
ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
switch(type) {
case SYSDB_MEMBER_USER:
ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS,
SYSDB_OVERRIDE_USER_CLASS);
break;
case SYSDB_MEMBER_GROUP:
ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS,
SYSDB_OVERRIDE_GROUP_CLASS);
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object type.\n");
ret = EINVAL;
goto done;
}
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_OBJECT_DN, LDB_FLAG_MOD_ADD,
NULL);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_OBJECT_DN, obj_dn_str);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_add(domain->sysdb->ldb, msg);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to store override entry: %s(%d)[%s]\n",
ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (add_ref) {
talloc_free(msg);
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
ret = ENOMEM;
goto done;
}
msg->dn = obj_dn;
ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN,
obj_override_dn == NULL ? LDB_FLAG_MOD_ADD
: LDB_FLAG_MOD_REPLACE,
NULL);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_DN, override_dn_str);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_modify(domain->sysdb->ldb, msg);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to store override DN: %s(%d)[%s]\n",
ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
}
ret = EOK;
done:
if (in_transaction) {
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret));
ldb_transaction_cancel(domain->sysdb->ldb);
} else {
ret = ldb_transaction_commit(domain->sysdb->ldb);
ret = sysdb_error_to_errno(ret);
}
}
talloc_zfree(tmp_ctx);
return ret;
}
static errno_t safe_original_attributes(struct sss_domain_info *domain,
struct sysdb_attrs *attrs,
struct ldb_dn *obj_dn,
const char **allowed_attrs)
{
int ret;
size_t c;
TALLOC_CTX *tmp_ctx;
struct ldb_result *orig_obj;
char *orig_attr_name;
struct ldb_message_element *el = NULL;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_obj, obj_dn,
LDB_SCOPE_BASE, NULL, NULL);
if (ret != EOK || orig_obj->count != 1) {
DEBUG(SSSDBG_CRIT_FAILURE, "Original object not found.\n");
goto done;
}
/* Safe orginal values in attributes prefixed by OriginalAD. */
for (c = 0; allowed_attrs[c] != NULL; c++) {
el = ldb_msg_find_element(orig_obj->msgs[0], allowed_attrs[c]);
if (el != NULL) {
orig_attr_name = talloc_asprintf(tmp_ctx, "%s%s",
ORIGINALAD_PREFIX,
allowed_attrs[c]);
if (orig_attr_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
ret = ENOMEM;
goto done;
}
ret = sysdb_attrs_add_val(attrs, orig_attr_name,
&el->values[0]);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_val failed.\n");
goto done;
}
} else {
DEBUG(SSSDBG_TRACE_ALL,
"Original object does not have [%s] set.\n",
allowed_attrs[c]);
}
}
/* Add existing aliases to new ones */
el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_NAME_ALIAS);
if (el != NULL) {
for (c = 0; c < el->num_values; c++) {
/* To avoid issue with ldb_modify if e.g. the orginal and the
* override name are the same, we use the *_safe version here. */
ret = sysdb_attrs_add_val_safe(attrs, SYSDB_NAME_ALIAS,
&el->values[c]);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n");
goto done;
}
}
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
struct sysdb_attrs *override_attrs,
struct ldb_dn *obj_dn)
{
int ret;
TALLOC_CTX *tmp_ctx;
struct sysdb_attrs *attrs;
size_t c;
size_t d;
size_t num_values;
struct ldb_message_element *el = NULL;
const char *allowed_attrs[] = { SYSDB_UIDNUM,
SYSDB_GIDNUM,
SYSDB_GECOS,
SYSDB_HOMEDIR,
SYSDB_SHELL,
SYSDB_NAME,
SYSDB_SSH_PUBKEY,
SYSDB_USER_CERT,
NULL };
bool override_attrs_found = false;
if (override_attrs == NULL) {
/* nothing to do */
return EOK;
}
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
attrs = sysdb_new_attrs(tmp_ctx);
if (attrs == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
ret = ENOMEM;
goto done;
}
for (c = 0; allowed_attrs[c] != NULL; c++) {
ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false,
&el);
if (ret == EOK) {
override_attrs_found = true;
if (strcmp(allowed_attrs[c], SYSDB_NAME) == 0) {
if (el->values[0].data[el->values[0].length] != '\0') {
DEBUG(SSSDBG_CRIT_FAILURE,
"String attribute does not end with \\0.\n");
ret = EINVAL;
goto done;
}
ret = add_name_and_aliases_for_name_override(domain, attrs,
true,
(char *) el->values[0].data);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"add_name_and_aliases_for_name_override failed.\n");
goto done;
}
} else {
num_values = el->num_values;
/* Only SYSDB_SSH_PUBKEY and SYSDB_USER_CERT are allowed to
* have multiple values. */
if (strcmp(allowed_attrs[c], SYSDB_SSH_PUBKEY) != 0
&& strcmp(allowed_attrs[c], SYSDB_USER_CERT) != 0
&& num_values != 1) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Override attribute for [%s] has more [%zd] " \
"than one value, using only the first.\n",
allowed_attrs[c], num_values);
num_values = 1;
}
for (d = 0; d < num_values; d++) {
ret = sysdb_attrs_add_val(attrs, allowed_attrs[c],
&el->values[d]);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_val failed.\n");
goto done;
}
DEBUG(SSSDBG_TRACE_ALL,
"Override [%s] with [%.*s] for [%s].\n",
allowed_attrs[c], (int) el->values[d].length,
el->values[d].data, ldb_dn_get_linearized(obj_dn));
}
}
} else if (ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el_ext failed.\n");
goto done;
}
}
if (override_attrs_found) {
ret = safe_original_attributes(domain, attrs, obj_dn, allowed_attrs);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "safe_original_attributes failed.\n");
goto done;
}
ret = sysdb_set_entry_attr(domain->sysdb, obj_dn, attrs, SYSDB_MOD_REP);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
goto done;
}
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
#define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
#define SYSDB_USER_UID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")("SYSDB_UIDNUM"=%lu))"
#define SYSDB_USER_CERT_OVERIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")%s)"
#define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
#define SYSDB_GROUP_GID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))"
enum override_object_type {
OO_TYPE_UNDEF = 0,
OO_TYPE_USER,
OO_TYPE_GROUP
};
errno_t sysdb_search_override_by_cert(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *cert,
const char **attrs,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
TALLOC_CTX *tmp_ctx;
struct ldb_dn *base_dn;
struct ldb_result *override_res;
struct ldb_result *orig_res;
char *cert_filter;
int ret;
const char *orig_obj_dn;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
ret = ENOMEM;
goto done;
}
ret = sss_cert_derb64_to_ldap_filter(tmp_ctx, cert, SYSDB_USER_CERT,
&cert_filter);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter failed.\n");
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
LDB_SCOPE_SUBTREE, attrs, SYSDB_USER_CERT_OVERIDE_FILTER,
cert_filter);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (override_res->count == 0) {
DEBUG(SSSDBG_TRACE_FUNC, "No user override found for cert [%s].\n",
cert);
ret = ENOENT;
goto done;
} else if (override_res->count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Found more than one override for cert [%s].\n", cert);
ret = EINVAL;
goto done;
}
if (orig_obj != NULL) {
orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
SYSDB_OVERRIDE_OBJECT_DN,
NULL);
if (orig_obj_dn == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing link to original object in override [%s].\n",
ldb_dn_get_linearized(override_res->msgs[0]->dn));
ret = EINVAL;
goto done;
}
base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = ENOMEM;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
*orig_obj = talloc_steal(mem_ctx, orig_res);
}
*override_obj = talloc_steal(mem_ctx, override_res);
ret = EOK;
done:
talloc_zfree(tmp_ctx);
return ret;
}
static errno_t sysdb_search_override_by_name(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name,
const char *filter,
const char **attrs,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
TALLOC_CTX *tmp_ctx;
struct ldb_dn *base_dn;
struct ldb_result *override_res;
struct ldb_result *orig_res;
char *sanitized_name;
char *lc_sanitized_name;
int ret;
const char *orig_obj_dn;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
ret = ENOMEM;
goto done;
}
ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain,
&sanitized_name, &lc_sanitized_name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize_for_dom failed.\n");
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
LDB_SCOPE_SUBTREE, attrs, filter,
lc_sanitized_name,
sanitized_name, sanitized_name);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (override_res->count == 0) {
DEBUG(SSSDBG_TRACE_FUNC, "No user override found for name [%s].\n",
name);
ret = ENOENT;
goto done;
} else if (override_res->count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Found more than one override for name [%s].\n", name);
ret = EINVAL;
goto done;
}
if (orig_obj != NULL) {
orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
SYSDB_OVERRIDE_OBJECT_DN,
NULL);
if (orig_obj_dn == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing link to original object in override [%s].\n",
ldb_dn_get_linearized(override_res->msgs[0]->dn));
ret = EINVAL;
goto done;
}
base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = ENOMEM;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
*orig_obj = talloc_steal(mem_ctx, orig_res);
}
*override_obj = talloc_steal(mem_ctx, override_res);
ret = EOK;
done:
talloc_zfree(tmp_ctx);
return ret;
}
errno_t sysdb_search_user_override_attrs_by_name(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name,
const char **attrs,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
return sysdb_search_override_by_name(mem_ctx, domain, name,
SYSDB_USER_NAME_OVERRIDE_FILTER,
attrs, override_obj, orig_obj);
}
errno_t sysdb_search_group_override_attrs_by_name(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name,
const char **attrs,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
return sysdb_search_override_by_name(mem_ctx, domain, name,
SYSDB_GROUP_NAME_OVERRIDE_FILTER,
attrs, override_obj, orig_obj);
}
errno_t sysdb_search_user_override_by_name(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
const char *attrs[] = SYSDB_PW_ATTRS;
return sysdb_search_override_by_name(mem_ctx, domain, name,
SYSDB_USER_NAME_OVERRIDE_FILTER,
attrs, override_obj, orig_obj);
}
errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
const char *attrs[] = SYSDB_GRSRC_ATTRS;
return sysdb_search_override_by_name(mem_ctx, domain, name,
SYSDB_GROUP_NAME_OVERRIDE_FILTER,
attrs, override_obj, orig_obj);
}
static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
unsigned long int id,
enum override_object_type type,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
TALLOC_CTX *tmp_ctx;
static const char *user_attrs[] = SYSDB_PW_ATTRS;
static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
const char **attrs;
struct ldb_dn *base_dn;
struct ldb_result *override_res;
struct ldb_result *orig_res;
int ret;
const char *orig_obj_dn;
const char *filter;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
ret = ENOMEM;
goto done;
}
switch(type) {
case OO_TYPE_USER:
filter = SYSDB_USER_UID_OVERRIDE_FILTER;
attrs = user_attrs;
break;
case OO_TYPE_GROUP:
filter = SYSDB_GROUP_GID_OVERRIDE_FILTER;
attrs = group_attrs;
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected override object type [%d].\n",
type);
ret = EINVAL;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
LDB_SCOPE_SUBTREE, attrs, filter, id);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (override_res->count == 0) {
DEBUG(SSSDBG_TRACE_FUNC,
"No user override found for %s with id [%lu].\n",
(type == OO_TYPE_USER ? "user" : "group"), id);
ret = ENOENT;
goto done;
} else if (override_res->count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Found more than one override for id [%lu].\n", id);
ret = EINVAL;
goto done;
}
if (orig_obj != NULL) {
orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
SYSDB_OVERRIDE_OBJECT_DN,
NULL);
if (orig_obj_dn == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing link to original object in override [%s].\n",
ldb_dn_get_linearized(override_res->msgs[0]->dn));
ret = EINVAL;
goto done;
}
base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
if (base_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = ENOMEM;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
*orig_obj = talloc_steal(mem_ctx, orig_res);
}
*override_obj = talloc_steal(mem_ctx, override_res);
ret = EOK;
done:
talloc_zfree(tmp_ctx);
return ret;
}
errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
uid_t uid,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
return sysdb_search_override_by_id(mem_ctx, domain, uid, OO_TYPE_USER,
override_obj, orig_obj);
}
errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
gid_t gid,
struct ldb_result **override_obj,
struct ldb_result **orig_obj)
{
return sysdb_search_override_by_id(mem_ctx, domain, gid, OO_TYPE_GROUP,
override_obj, orig_obj);
}
/**
* @brief Add override data to the original object
*
* @param[in] domain Domain struct, needed to access the cache
* @oaram[in] obj The original object
* @param[in] override_obj The object with the override data, may be NULL
* @param[in] req_attrs List of attributes to be requested, if not set a
* default list dependig on the object type will be used
*
* @return EOK - Override data was added successfully
* @return ENOMEM - There was insufficient memory to complete the operation
* @return ENOENT - The original object did not have the SYSDB_OVERRIDE_DN
* attribute or the value of the attribute points an object
* which does not exists. Both conditions indicate that the
* cache must be refreshed.
*/
errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
struct ldb_message *obj,
struct ldb_message *override_obj,
const char **req_attrs)
{
int ret;
const char *override_dn_str;
struct ldb_dn *override_dn;
TALLOC_CTX *tmp_ctx;
struct ldb_result *res;
struct ldb_message *override;
uint64_t uid;
static const char *user_attrs[] = SYSDB_PW_ATTRS;
static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
const char **attrs;
struct attr_map {
const char *attr;
const char *new_attr;
} attr_map[] = {
{SYSDB_UIDNUM, OVERRIDE_PREFIX SYSDB_UIDNUM},
{SYSDB_GIDNUM, OVERRIDE_PREFIX SYSDB_GIDNUM},
{SYSDB_GECOS, OVERRIDE_PREFIX SYSDB_GECOS},
{SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR},
{SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL},
{SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME},
{SYSDB_SSH_PUBKEY, OVERRIDE_PREFIX SYSDB_SSH_PUBKEY},
{SYSDB_USER_CERT, OVERRIDE_PREFIX SYSDB_USER_CERT},
{NULL, NULL}
};
size_t c;
size_t d;
struct ldb_message_element *tmp_el;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
if (override_obj == NULL) {
override_dn_str = ldb_msg_find_attr_as_string(obj,
SYSDB_OVERRIDE_DN, NULL);
if (override_dn_str == NULL) {
if (is_local_view(domain->view_name)) {
/* LOCAL view doesn't have to have overrideDN specified. */
ret = EOK;
goto done;
}
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing override DN for object [%s].\n",
ldb_dn_get_linearized(obj->dn));
ret = ENOENT;
goto done;
}
override_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, override_dn_str);
if (override_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = ENOMEM;
goto done;
}
if (ldb_dn_compare(obj->dn, override_dn) == 0) {
DEBUG(SSSDBG_TRACE_ALL, "Object [%s] has no overrides.\n",
ldb_dn_get_linearized(obj->dn));
ret = EOK;
goto done;
}
attrs = req_attrs;
if (attrs == NULL) {
uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0);
if (uid == 0) {
/* No UID hence group object */
attrs = group_attrs;
} else {
attrs = user_attrs;
}
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, override_dn,
LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (res->count == 1) {
override = res->msgs[0];
} else if (res->count == 0) {
DEBUG(SSSDBG_TRACE_FUNC, "Override object [%s] does not exists.\n",
override_dn_str);
ret = ENOENT;
goto done;
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Base search for override object returned [%d] results.\n",
res->count);
ret = EINVAL;
goto done;
}
} else {
override = override_obj;
}
for (c = 0; attr_map[c].attr != NULL; c++) {
tmp_el = ldb_msg_find_element(override, attr_map[c].attr);
if (tmp_el != NULL) {
for (d = 0; d < tmp_el->num_values; d++) {
ret = ldb_msg_add_steal_value(obj, attr_map[c].new_attr,
&tmp_el->values[d]);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_value failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
}
}
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
struct ldb_message *obj,
bool expect_override_dn)
{
int ret;
size_t c;
struct ldb_result *res_members;
TALLOC_CTX *tmp_ctx;
struct ldb_result *override_obj;
static const char *member_attrs[] = SYSDB_PW_ATTRS;
const char *override_dn_str;
struct ldb_dn *override_dn;
const char *memberuid;
const char *orig_name;
char *orig_domain;
char *val;
struct sss_domain_info *orig_dom;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
ret = ENOMEM;
goto done;
}
ret = sysdb_get_user_members_recursively(tmp_ctx, domain, obj->dn,
&res_members);
if (ret == ENOENT) {
ret = EOK;
goto done;
} else if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_get_user_members_recursively failed.\n");
goto done;
}
for (c = 0; c < res_members->count; c++) {
if (ldb_msg_find_attr_as_uint64(res_members->msgs[c],
SYSDB_UIDNUM, 0) == 0) {
/* Skip non-POSIX-user members i.e. groups and non-POSIX users */
continue;
}
if (expect_override_dn) {
override_dn_str = ldb_msg_find_attr_as_string(res_members->msgs[c],
SYSDB_OVERRIDE_DN,
NULL);
} else {
override_dn_str = ldb_dn_get_linearized(res_members->msgs[c]->dn);
}
if (override_dn_str == NULL) {
if (is_local_view(domain->view_name)) {
/* LOCAL view doesn't have to have overrideDN specified. */
ret = EOK;
goto done;
}
DEBUG(SSSDBG_CRIT_FAILURE,
"Missing override DN for object [%s].\n",
ldb_dn_get_linearized(res_members->msgs[c]->dn));
ret = ENOENT;
goto done;
}
override_dn = ldb_dn_new(res_members, domain->sysdb->ldb,
override_dn_str);
if (override_dn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
ret = ENOMEM;
goto done;
}
orig_name = ldb_msg_find_attr_as_string(res_members->msgs[c],
SYSDB_NAME,
NULL);
if (orig_name == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
ldb_dn_get_linearized(res_members->msgs[c]->dn));
ret = EINVAL;
goto done;
}
/* start with default view name, if it exists or use NULL */
memberuid = ldb_msg_find_attr_as_string(res_members->msgs[c],
SYSDB_DEFAULT_OVERRIDE_NAME,
NULL);
/* If there is an override object, check if the name is overridden */
if (ldb_dn_compare(res_members->msgs[c]->dn, override_dn) != 0) {
DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n",
ldb_dn_get_linearized(res_members->msgs[c]->dn));
ret = ldb_search(domain->sysdb->ldb, res_members, &override_obj,
override_dn, LDB_SCOPE_BASE, member_attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
if (override_obj->count != 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Base search for override object returned [%d] results.\n",
override_obj->count);
ret = EINVAL;
goto done;
}
memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0],
SYSDB_NAME,
memberuid);
}
/* add domain name if memberuid is a short name */
if (memberuid != NULL && strchr(memberuid, '@') == NULL) {
ret = sss_parse_internal_fqname(tmp_ctx, orig_name,
NULL, &orig_domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sss_parse_internal_fqname failed to split [%s].\n",
orig_name);
goto done;
}
if (orig_domain != NULL) {
orig_dom = find_domain_by_name(get_domains_head(domain),
orig_domain, true);
if (orig_dom == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Cannot find domain with name [%s].\n",
orig_domain);
ret = ERR_DOMAIN_NOT_FOUND;
goto done;
}
memberuid = sss_create_internal_fqname(tmp_ctx, memberuid,
orig_dom->name);
if (memberuid == NULL) {
DEBUG(SSSDBG_OP_FAILURE,
"sss_create_internal_fqname failed.\n");
ret = ENOMEM;
goto done;
}
}
}
if (memberuid == NULL) {
DEBUG(SSSDBG_TRACE_ALL, "No override name available.\n");
memberuid = orig_name;
}
val = talloc_strdup(obj, memberuid);
if (val == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID, val);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
ret = sysdb_error_to_errno(ret);
goto done;
}
DEBUG(SSSDBG_TRACE_ALL, "Added [%s] to [%s].\n", memberuid,
OVERRIDE_PREFIX SYSDB_MEMBERUID);
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
struct ldb_message_element *
sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
const struct ldb_message *msg,
const char *attr_name)
{
TALLOC_CTX *tmp_ctx = NULL;
struct ldb_message_element *val;
char *override_attr_name;
if (DOM_HAS_VIEWS(dom)) {
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
val = NULL;
goto done;
}
override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
attr_name);
if (override_attr_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
val = NULL;
goto done;
}
val = ldb_msg_find_element(msg, override_attr_name);
if (val != NULL) {
goto done;
}
}
val = ldb_msg_find_element(msg, attr_name);
done:
talloc_free(tmp_ctx);
return val;
}
uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
const struct ldb_message *msg,
const char *attr_name,
uint64_t default_value)
{
TALLOC_CTX *tmp_ctx = NULL;
uint64_t val;
char *override_attr_name;
if (DOM_HAS_VIEWS(dom)) {
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
val = default_value;
goto done;
}
override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
attr_name);
if (override_attr_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
val = default_value;
goto done;
}
if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
val = ldb_msg_find_attr_as_uint64(msg, override_attr_name,
default_value);
goto done;
}
}
val = ldb_msg_find_attr_as_uint64(msg, attr_name, default_value);
done:
talloc_free(tmp_ctx);
return val;
}
const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
const struct ldb_message *msg,
const char *attr_name,
const char * default_value)
{
TALLOC_CTX *tmp_ctx = NULL;
const char *val;
char *override_attr_name;
if (DOM_HAS_VIEWS(dom)) {
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
val = default_value;
goto done;
}
override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
attr_name);
if (override_attr_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
val = default_value;
goto done;
}
if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
val = ldb_msg_find_attr_as_string(msg, override_attr_name,
default_value);
goto done;
}
}
val = ldb_msg_find_attr_as_string(msg, attr_name, default_value);
done:
talloc_free(tmp_ctx);
return val;
}