sysdb.c revision dd285415d7a8d8376207960cfa3e977524c3b98c
/*
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 "util/crypto/sss_crypto.h"
#include "db/sysdb_private.h"
#include <time.h>
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;
}
const char *name)
{
char *clean_name;
return NULL;
}
return dn;
}
struct sss_domain_info *dom)
{
}
{
char *clean_name;
return NULL;
}
return dn;
}
struct sss_domain_info *dom)
{
}
{
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;
}
{
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)
{
unsigned int u;
const char **a;
if (a == NULL) {
return NULL;
}
for (u = 0; u < el->num_values; u++) {
if (a[u] == NULL) {
talloc_free(a);
return NULL;
}
}
return a;
}
{
struct ldb_message_element *el;
int ret;
const char **a;
if (ret) {
return ret;
}
if (a == NULL) {
return ENOMEM;
}
*string = a;
return EOK;
}
const char *name, bool check_values,
{
int ret;
size_t c;
return ret;
}
if (check_values) {
for (c = 0; c < el->num_values; c++) {
return EOK;
}
}
}
return ENOMEM;
}
el->num_values++;
return EOK;
}
{
}
/* Check if the same value already exists. */
{
}
{
struct ldb_val v;
}
{
struct ldb_val v;
}
{
char *lc_str;
int ret;
return EINVAL;
}
return ENOMEM;
}
if (safe) {
} else {
}
return ret;
}
{
struct ldb_val v;
}
const char *base64_str)
{
struct ldb_val v;
int ret;
if (base64_str == NULL) {
return EINVAL;
}
return ENOMEM;
}
talloc_free(v.data);
return ret;
}
{
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;
}
const char *value)
{
value);
}
const char *value)
{
value);
}
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) {
"Failed to get user dn for [%s]\n", list[i]);
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",
return EFAULT;
}
}
/* =Transactions========================================================== */
{
int ret;
if (ret == LDB_SUCCESS) {
} else {
"Failed to start ldb transaction! (%d)\n", ret);
}
return sysdb_error_to_errno(ret);
}
{
int ret;
#ifdef HAVE_SYSTEMTAP
#endif
if (ret == LDB_SUCCESS) {
} else {
"Failed to commit ldb transaction! (%d)\n", ret);
}
return sysdb_error_to_errno(ret);
}
{
int ret;
if (ret == LDB_SUCCESS) {
} else {
"Failed to cancel ldb transaction! (%d)\n", ret);
}
return sysdb_error_to_errno(ret);
}
{
struct ldb_message);
struct ldb_message);
}
const char *newname)
{
struct ldb_message_element *e = NULL;
int i;
const char *dummy;
e = &(attrs->a[i]);
}
"New attribute name [%s] already exists.\n", newname);
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;
struct ldb_message_element *el;
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;
}
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 {
}
if (lret != LDB_SUCCESS) {
"ldb operation failed: [%s](%d)[%s]\n",
}
done:
return ret;
}
bool *has_enumerated)
{
if (!tmp_ctx) {
goto done;
}
if (!dn) {
goto done;
}
done:
return ret;
}
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.
*/
"The entry has multiple names and the RDN attribute does "
"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.
*/
"Cannot save entry. Unable to determine groupname\n");
goto done;
}
done:
"Could not determine primary name: [%d][%s]\n",
}
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 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;
}
int sysdb_compare_usn(const char *a, const char *b)
{
if (a == NULL) {
return -1;
}
if (b == NULL) {
return 1;
}
/* trim leading zeros */
while (len_a > 0 && *a == '0') {
a++;
len_a--;
}
while (len_b > 0 && *b == '0') {
b++;
len_b--;
}
/* less digits means lower number */
return -1;
}
/* more digits means bigger number */
return 1;
}
/* now we can compare digits since alphabetical order is the same
* as numeric order */
return strcmp(a, b);
}
struct sysdb_attrs **attrs,
char **_usn)
{
char *usn;
size_t i;
goto done;
}
for (i = 0; i < num_attrs; i++) {
/* USN value is not present, assuming zero. */
current = "0";
return ret;
}
continue;
}
continue;
}
}
}
done:
} else {
}
return ENOMEM;
}
return EOK;
}
{
int ret;
if (ret == LDB_SUCCESS) {
}
return ENOMEM;
}
{
}
{
}
{
}
{
int ret;
if (ret == LDB_SUCCESS) {
}
return ENOMEM;
}
{
}
{
}
{
}
{
const char *sysdb_comp_name = NULL;
return false;
}
/* The second component name is not "cn" */
return false;
}
if (strncasecmp("users",
(const char *) sysdb_comp_val->data,
sysdb_comp_val->length) == 0) {
return true;
}
if (strncasecmp("groups",
(const char *) sysdb_comp_val->data,
sysdb_comp_val->length) == 0) {
return true;
}
return false;
}