sysdb.c revision 956309e24c32cd0886736bf065a27d5bdd200a77
/*
SSSD
System Database
Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com>
Copyright (C) 2008-2011 Stephen Gallagher <ssorce@redhat.com>
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/strtonum.h"
#include "util/sss_utf8.h"
#include "db/sysdb_private.h"
#include <time.h>
#define LDB_MODULES_PATH "LDB_MODULES_PATH"
struct ldb_context **_ldb)
{
int ret;
struct ldb_context *ldb;
const char *mod_path;
return EINVAL;
}
if (!ldb) {
return EIO;
}
if (ret != LDB_SUCCESS) {
return EIO;
}
}
if (ret != LDB_SUCCESS) {
return EIO;
}
return EOK;
}
char **sanitized)
{
return ENOMEM;
}
/* We can't include the trailing NULL because it would
* be escaped and result in an unterminated string
*/
if (!*sanitized) {
}
return ret;
}
struct sss_domain_info *dom,
const char *subtree_name)
{
char *clean_subtree;
return NULL;
}
if (dn) {
}
return dn;
}
struct sss_domain_info *dom,
const char *object_name,
const char *subtree_name)
{
char *clean_name;
char *clean_subtree;
if (!tmp_ctx) {
return NULL;
}
goto done;
}
goto done;
}
done:
return dn;
}
{
char *clean_name;
return NULL;
}
return dn;
}
{
char *clean_name;
return NULL;
}
return dn;
}
{
char *clean_name;
return NULL;
}
return dn;
}
struct sss_domain_info *dom)
{
}
{
/* We have to create a tmp_ctx here because
* ldb_dn_new_fmt() fails if mem_ctx is NULL
*/
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
if (_name) {
goto done;
}
if (!*_name) {
goto done;
}
}
goto done;
}
if (!*_val) {
goto done;
}
done:
return ret;
}
{
}
struct sss_domain_info *dom)
{
}
{
}
{
}
{
}
{
struct ldb_message_element *e = NULL;
int i;
e = &(attrs->a[i]);
}
if (!e && alloc) {
if (!e) return ENOMEM;
attrs->a = e;
}
if (!e) {
return ENOENT;
}
*el = e;
return EOK;
}
struct ldb_message_element **el)
{
}
const char **string)
{
struct ldb_message_element *el;
int ret;
if (ret) {
return ret;
}
return ERANGE;
}
return EOK;
}
{
struct ldb_message_element *el;
int ret;
char *endptr;
if (ret) {
return ret;
}
return ERANGE;
}
errno = 0;
return EOK;
}
{
struct ldb_message_element *el;
int ret;
char *endptr;
if (ret) {
return ret;
}
return ERANGE;
}
errno = 0;
return EOK;
}
bool *value)
{
struct ldb_message_element *el;
int ret;
if (ret) {
return ret;
}
return ERANGE;
}
*value = true;
else
*value = false;
return EOK;
}
{
struct ldb_message_element *el;
int ret;
unsigned int u;
const char **a;
if (ret) {
return ret;
}
if (a == NULL) {
return ENOMEM;
}
for(u = 0; u < el->num_values; u++) {
if (a[u] == NULL) {
talloc_free(a);
return ENOMEM;
}
}
*string = a;
return EOK;
}
{
int ret;
return ret;
}
return ENOMEM;
}
el->num_values++;
return EOK;
}
{
struct ldb_val v;
}
{
struct ldb_val v;
}
{
if(value) {
}
}
{
int ret;
return ret;
}
/* now steal and assign the string */
el->num_values++;
return EOK;
}
{
struct ldb_val v;
char *str;
int ret;
return ret;
}
{
struct ldb_val v;
char *str;
int ret;
return ret;
}
{
struct ldb_val v;
char *str;
int ret;
return ret;
}
struct sysdb_attrs *dst,
const char *name)
{
int i;
struct ldb_message_element *src_el;
goto done;
}
for (i = 0; i < src_el->num_values; i++) {
goto done;
}
}
done:
return ret;
}
const char *attr_name,
const char *domain,
const char *const *list)
{
int i, j, num;
char *member;
int ret;
if (ret) {
return ret;
}
if (!vals) {
return ENOMEM;
}
if (!member) {
continue;
}
j++;
}
el->num_values = j;
return EOK;
}
{
char *ret;
int l;
if (name[l] != '\0') {
struct ldb_val v;
char *tmp;
if (!tmp) {
return NULL;
}
if (!ret) {
return NULL;
}
return ret;
}
if (!ret) {
return NULL;
}
return ret;
}
{
}
{
}
/* TODO: make a more complete and precise mapping */
int sysdb_error_to_errno(int ldberr)
{
switch (ldberr) {
case LDB_SUCCESS:
return EOK;
case LDB_ERR_OPERATIONS_ERROR:
return EIO;
case LDB_ERR_NO_SUCH_OBJECT:
return ENOENT;
case LDB_ERR_BUSY:
return EBUSY;
return EEXIST;
return EINVAL;
default:
("LDB returned unexpected error: [%s]\n",
ldb_strerror(ldberr)));
return EFAULT;
}
}
/* =Transactions========================================================== */
{
int ret;
if (ret != LDB_SUCCESS) {
}
return sysdb_error_to_errno(ret);
}
{
int ret;
if (ret != LDB_SUCCESS) {
}
return sysdb_error_to_errno(ret);
}
{
int ret;
if (ret != LDB_SUCCESS) {
}
return sysdb_error_to_errno(ret);
}
/* =Initialization======================================================== */
{
char *ldb_file;
/* special case for the local domain */
} else {
}
if (!ldb_file) {
return ENOMEM;
}
return EOK;
}
{
struct ldb_message *msg;
int ret;
goto done;
}
/* == create base domain object == */
if (!msg) {
goto done;
}
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
/* do a synchronous add */
if (ret != LDB_SUCCESS) {
"for domain %s!\n",
domain_name));
goto done;
}
/* == create Users tree == */
if (!msg) {
goto done;
}
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
/* do a synchronous add */
if (ret != LDB_SUCCESS) {
"for domain %s!\n",
domain_name));
goto done;
}
/* == create Groups tree == */
if (!msg) {
goto done;
}
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
/* do a synchronous add */
if (ret != LDB_SUCCESS) {
"domain %s!\n",
domain_name));
goto done;
}
done:
return ret;
}
/* Compare versions of sysdb, returns ERRNO accordingly */
static errno_t
sysdb_version_check(const char *expected,
const char *received)
{
int ret;
if (ret != 2) {
return EINVAL;
}
if (ret != 2) {
return EINVAL;
}
if (recv_major > exp_major) {
return EUCLEAN;
} else if (recv_major < exp_major) {
return EMEDIUMTYPE;
}
if (recv_minor > exp_minor) {
return EUCLEAN;
} else if (recv_minor < exp_minor) {
return EMEDIUMTYPE;
}
return EOK;
}
struct sss_domain_info *domain,
const char *db_path,
bool allow_upgrade,
{
const char *base_ldif;
struct ldb_message_element *el;
struct ldb_result *res;
int ret;
if (!sysdb) {
return ENOMEM;
}
goto done;
}
goto done;
}
if (!tmp_ctx) {
goto done;
}
if (!verdn) {
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
goto done;
}
if (!el) {
goto done;
}
goto done;
}
if (!version) {
goto done;
}
/* all fine, return */
goto done;
}
if (!allow_upgrade) {
("Wrong DB version (got %s expected %s)\n",
version, SYSDB_VERSION));
goto done;
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
goto done;
}
}
/* The version should now match SYSDB_VERSION.
* If not, it means we didn't match any of the
* known older versions. The DB might be
* corrupt or generated by a newer version of
* SSSD.
*/
/* The cache has been upgraded.
* We need to reopen the LDB to ensure that
* any changes made above take effect.
*/
}
goto done;
}
DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n",
goto done;
}
/* SYSDB_BASE does not exists, means db is empty, populate */
if (ret != LDB_SUCCESS) {
DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
goto done;
}
}
goto done;
}
/* The cache has been newly created.
* We need to reopen the LDB to ensure that
* all of the special values take effect
* (such as enabling the memberOf plugin and
* the various indexes).
*/
}
done:
} else {
}
return ret;
}
struct sss_domain_info *domains,
const char *alt_db_path,
bool allow_upgrade)
{
struct sss_domain_info *dom;
const char *db_path;
int ret;
if (alt_db_path) {
} else {
}
if (allow_upgrade) {
/* check if we have an old sssd.ldb to upgrade */
return ret;
}
}
/* open a db for each domain */
allow_upgrade, &sysdb);
return ret;
}
}
return EOK;
}
struct sss_domain_info *domain,
const char *db_path,
{
}
{
struct ldb_message);
struct ldb_message);
}
const char *newname)
{
struct ldb_message_element *e = NULL;
int i;
const char *dummy;
e = &(attrs->a[i]);
}
return EEXIST;
}
}
if (e != NULL) {
return ENOMEM;
}
}
return EOK;
}
/* Search for all incidences of attr_name in a list of
* sysdb_attrs and add their value to a list
*
* TODO: Currently only works for single-valued
* attributes. Multi-valued attributes will return
* only the first entry
*/
struct sysdb_attrs **attrs,
int attr_count,
const char *attr_name,
char ***_list)
{
int attr_idx;
int i;
char **list;
char **tmp_list;
int list_idx;
/* Assume that every attrs entry contains the attr_name
* This may waste a little memory if some entries don't
* have the attribute, but it will save us the trouble
* of continuously resizing the array.
*/
if (!list) {
return ENOMEM;
}
list_idx = 0;
/* Loop through all entries in attrs */
/* Examine each attribute within the entry */
/* Attribute name matches the requested name
* Copy it to the output list
*/
list,
return ENOMEM;
}
list_idx++;
/* We only support single-valued attributes
* Break here and go on to the next entry
*/
break;
}
}
}
/* if list_idx < attr_count, do a realloc to
* reclaim unused memory
*/
if (list_idx < attr_count) {
if (!tmp_list) {
return ENOMEM;
}
}
return EOK;
}
const char *attr_name,
bool *value)
{
struct ldb_result *res;
int lret;
return ENOMEM;
}
if (lret != LDB_SUCCESS) {
goto done;
}
/* This entry has not been populated in LDB
* This is a common case, as unlike LDAP,
* LDB does not need to have all of its parent
* objects actually exist.
* This object in the sysdb exists mostly just
* to contain this attribute.
*/
*value = false;
goto done;
("Got more than one reply for base search!\n"));
goto done;
}
done:
return ret;
}
const char *cn_value,
const char *attr_name,
bool value)
{
int lret;
return EINVAL;
}
return ENOMEM;
}
if (lret != LDB_SUCCESS) {
goto done;
}
goto done;
}
if (lret != LDB_SUCCESS) {
goto done;
}
("Got more than one reply for base search!\n"));
goto done;
} else {
if (lret != LDB_SUCCESS) {
goto done;
}
}
if (lret != LDB_SUCCESS) {
goto done;
}
} else {
}
done:
return ret;
}
struct sss_domain_info *domain,
bool *has_enumerated)
{
if (!tmp_ctx) {
goto done;
}
if (!dn) {
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
bool enumerated)
{
if (!tmp_ctx) {
goto done;
}
if (!dn) {
goto done;
}
done:
return ret;
}
struct sysdb_attrs *attrs,
const char *ldap_attr,
const char **_primary)
{
struct ldb_message_element *sysdb_name_el;
struct ldb_message_element *orig_dn_el;
size_t i;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
/* Entry contains only one name. Just return that */
goto done;
}
/* Multiple values for name. Check whether one matches the RDN */
if (ret) {
goto done;
}
if (orig_dn_el->num_values == 0) {
goto done;
&rdn_attr,
&rdn_val);
goto done;
}
} else {
goto done;
}
/* First check whether the attribute name matches */
/* Multiple entries, and the RDN attribute doesn't match.
* We have no way of resolving this deterministically,
* so we'll use the first value as a fallback.
*/
"not match. Will use the first value as fallback.\n"));
goto done;
}
for (i = 0; i < sysdb_name_el->num_values; i++) {
if (strcasecmp(rdn_val,
/* This name matches the RDN. Use it */
break;
}
}
if (i < sysdb_name_el->num_values) {
/* Match was found */
} 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.
*/
goto done;
}
done:
}
return ret;
}
/*
* An entity with multiple names would have multiple SYSDB_NAME attributes
* after being translated into sysdb names using a map.
* Given a primary name returned by sysdb_attrs_primary_name(), this function
* returns the other SYSDB_NAME attribute values so they can be saved as
* SYSDB_NAME_ALIAS into cache.
*
* If lowercase is set, all aliases are duplicated in lowercase as well.
*/
struct sysdb_attrs *attrs,
const char *primary,
bool lowercase,
const char ***_aliases)
{
struct ldb_message_element *sysdb_name_el;
const char *name;
char *lower;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
if (!aliases) {
goto done;
}
if (lowercase) {
("Domain is case-insensitive; will add lowercased aliases\n"));
}
ai = 0;
for (i=0; i < sysdb_name_el->num_values; i++) {
if (lowercase) {
/* Domain is case-insensitive. Save the lower-cased version */
if (!lower) {
goto done;
}
for (j=0; j < ai; j++) {
break;
}
}
goto done;
}
ai++;
}
} else {
/* Domain is case-sensitive. Save it as-is */
goto done;
}
ai++;
}
}
}
done:
return ret;
}
struct sysdb_attrs **attr_list,
const char *ldap_attr,
char ***name_list)
{
size_t i, j;
char **list;
const char *name;
/* Assume that every entry has a primary name */
if (!list) {
return ENOMEM;
}
j = 0;
for (i = 0; i < attr_count; i++) {
attr_list[i],
&name);
/* Skip and continue. Don't advance 'j' */
continue;
}
if (!list[j]) {
goto done;
}
j++;
}
/* NULL-terminate the list */
done:
}
return ret;
}
struct sss_domain_info *domain,
const char *name,
const char **_cname)
{
struct ldb_result *res;
const char *cname;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
/* User is not cached yet */
goto done;
goto done;
}
if (!cname) {
goto done;
}
done:
return ret;
}
struct ldb_message **msgs,
struct sysdb_attrs ***attrs)
{
int i;
struct sysdb_attrs **a;
if (a == NULL) {
return ENOMEM;
}
for (i = 0; i < count; i++) {
a[i] = talloc(a, struct sysdb_attrs);
if (a[i] == NULL) {
talloc_free(a);
return ENOMEM;
}
}
*attrs = a;
return EOK;
}