/*
SSSD
System Database
Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
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 "db/sysdb_private.h"
#include <time.h>
#include <ctype.h>
/* helpers */
struct ldb_message *sysdb_msg,
const char *ts_attr,
const char *want_attrs[])
{
bool include = true;
if (want_attrs != NULL) {
/* Otherwise merge all ts attrs */
}
if (include == false) {
return EOK;
}
return EOK;
}
return EIO;
}
return sysdb_error_to_errno(ret);
}
} else {
/* Assumes the timestamps cache only holds single-valued
* attributes */
}
return EOK;
}
struct ldb_message *sysdb_msg,
const char *attrs[])
{
bool ts_dn;
if (ts_dn == false) {
return ERR_NO_TS;
}
return ENOMEM;
}
NULL,
&ts_msgs);
"No such DN in the timestamp cache: %s\n",
goto done;
"Cannot find TS cache entry for [%s]: [%d]: %s\n",
goto done;
}
if (msgs_count != 1) {
"Expected 1 result for base search, got %zu\n", msgs_count);
return EIO;
}
/* Deliberately start from 2 in order to not merge
* objectclass/objectcategory and avoid breaking MPGs where the OC might
* be made up
*/
sysdb_ts_cache_attrs[c], attrs);
"Cannot merge ts attr %s\n", sysdb_ts_cache_attrs[c]);
goto done;
}
}
done:
return ret;
}
struct ldb_result *res,
const char *attrs[])
{
return EOK;
}
"TS cache doesn't handle this DN type, skipping\n");
continue;
} else if (ret == ERR_TS_CACHE_MISS) {
"TS cache doesn't contain this DN, skipping\n");
continue;
"Cannot merge timestamp cache values for %s\n",
/* non-fatal */
continue;
}
}
return EOK;
}
struct ldb_message **msgs,
const char *attrs[])
{
}
/* users */
struct sss_domain_info *domain,
const char *name,
struct ldb_result **_res)
{
char *sanitized_name;
char *lc_sanitized_name;
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
goto done;
}
if (ret) {
goto done;
}
/* We expected either 0 or 1 result for search with
* SYSDB_PWNAM_FILTER, but we got more. This error
* is handled individually depending on what function
* called sysdb_getpwnam, so we just print a message
* here and let the caller decide what error code to
* propagate based on res->count > 1. */
"Search for [%s] returned multiple results. It can be an email "
"address shared among multiple users or an email address of a "
"user that conflicts with another user's fully qualified name. "
"SSSD will not be able to handle those users properly.\n",
}
/* Merge in the timestamps from the fast ts db */
/* non-fatal */
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name,
struct ldb_result **res)
{
int ret;
return ENOMEM;
}
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
&override_obj, &orig_obj);
"sysdb_search_override_by_name failed.\n");
goto done;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
goto done;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
NULL);
goto done;
}
} else {
}
goto done;
}
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
if (ret) {
goto done;
}
/* Merge in the timestamps from the fast ts db */
/* non-fatal */
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **res)
{
int ret;
return ENOMEM;
}
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
&override_obj, &orig_obj);
"sysdb_search_user_override_by_uid failed.\n");
goto done;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
goto done;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
NULL);
goto done;
}
} else {
}
goto done;
}
}
done:
return ret;
}
const char *base_filter,
const char *name_filter,
const char *addtl_filter)
{
char *filter;
return NULL;
}
} else {
}
}
}
}
if (filter) {
}
return filter;
}
struct sss_domain_info *domain,
bool domain_scope,
const char *upn,
struct ldb_result **_res)
{
return ENOMEM;
}
goto done;
}
done:
return ret;
}
const char *attrs[],
struct ldb_result *ts_res,
const char *filter,
struct ldb_result **_res)
{
goto done;
}
return ENOMEM;
}
goto done;
}
if (ret) {
goto done;
}
done:
return ret;
}
struct ldb_result *ts_res,
const char *name_filter,
char **_dn_filter)
{
char *dn_filter;
*_dn_filter = NULL;
goto done;
}
return ENOMEM;
}
goto done;
}
"(%s=%s)",
goto done;
}
}
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name_filter,
const char *addtl_filter,
struct ldb_result **_res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
NULL, addtl_filter);
goto done;
}
&ts_res);
}
goto done;
}
goto done;
}
goto done;
}
goto done;
}
if (ret) {
goto done;
}
/* Merge in the timestamps from the fast ts db */
/* non-fatal */
}
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
}
struct sss_domain_info *domain,
const char *name_filter,
const char *addtl_filter,
struct ldb_result **_res)
{
size_t c;
int ret;
return ENOMEM;
}
goto done;
}
if (DOM_HAS_VIEWS(domain)) {
NULL);
/* enumeration assumes that the cache is up-to-date, hence we do not
* need to handle ENOENT separately. */
goto done;
}
}
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
}
/* groups */
{
int i;
/* see if this is a user to convert to a group */
for (i = 0; i < el->num_values; i++) {
break;
}
}
/* no, leave as is */
/* yes, convert */
return EOK;
}
{
int ret;
int i;
if (ret) {
return ret;
}
}
return EOK;
}
struct sss_domain_info *domain,
const char *name,
struct ldb_result **res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
&override_obj, &orig_obj);
"sysdb_search_group_override_by_name failed.\n");
goto done;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
goto done;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
if (DOM_HAS_VIEWS(domain)) {
"entries which must be resolved before overrides can be "
"applied.\n",
goto done;
}
}
NULL);
goto done;
}
}
/* Must be called even without views to check to
* SYSDB_DEFAULT_OVERRIDE_NAME */
"sysdb_add_group_member_overrides failed.\n");
goto done;
}
}
done:
} else {
}
}
return ret;
}
struct sss_domain_info *domain,
const char *name,
struct ldb_result **_res)
{
const char *fmt_filter;
char *sanitized_name;
char *lc_sanitized_name;
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
} else {
}
if (!base_dn) {
goto done;
}
goto done;
}
if (ret) {
goto done;
}
if (ret) {
goto done;
}
/* non-fatal */
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
&override_obj, &orig_obj);
"sysdb_search_group_override_by_gid failed.\n");
goto done;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
goto done;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
if (DOM_HAS_VIEWS(domain)) {
"entries which must be resolved before overrides can be "
"applied.\n",
goto done;
}
}
NULL);
goto done;
}
}
/* Must be called even without views to check to
* SYSDB_DEFAULT_OVERRIDE_NAME */
"sysdb_add_group_member_overrides failed.\n");
goto done;
}
}
done:
} else {
}
}
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
const char *fmt_filter;
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
} else {
}
if (!base_dn) {
goto done;
}
if (ret) {
goto done;
}
if (ret) {
goto done;
}
/* non-fatal */
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name_filter,
const char *addtl_filter,
struct ldb_result **_res)
{
const char *base_filter;
return EINVAL;
}
if (!tmp_ctx) {
return ENOMEM;
}
} else {
}
if (!base_dn) {
goto done;
}
NULL, addtl_filter);
goto done;
}
&ts_res);
}
goto done;
}
goto done;
}
goto done;
}
goto done;
}
if (lret != LDB_SUCCESS) {
goto done;
}
if (ret) {
goto done;
}
/* Merge in the timestamps from the fast ts db */
/* non-fatal */
}
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
}
struct sss_domain_info *domain,
const char *name_filter,
const char *addtl_filter,
struct ldb_result **_res)
{
size_t c;
int ret;
return ENOMEM;
}
goto done;
}
if (DOM_HAS_VIEWS(domain)) {
NULL);
/* enumeration assumes that the cache is up-to-date, hence we do not
* need to handle ENOENT separately. */
goto done;
}
}
"sysdb_add_group_member_overrides failed.\n");
goto done;
}
}
done:
return ret;
}
struct sss_domain_info *domain,
struct ldb_result **_res)
{
}
struct sss_domain_info *domain,
const char *name,
struct ldb_result **_res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
/* User is not cached yet */
goto done;
goto done;
}
/* no need to steal the dn, we are not freeing the result */
/* note we count on the fact that the default search callback
* will just keep appending values. This is by design and can't
* change so it is ok to already have a result (from the getpwnam)
* even before we call the next search */
if (!ctrl) {
goto done;
}
if (!ctrl[0]) {
goto done;
}
if (!control) {
goto done;
}
if (!control->source_attribute) {
goto done;
}
NULL);
if (ret != LDB_SUCCESS) {
goto done;
}
if (ret == LDB_SUCCESS) {
}
if (ret != LDB_SUCCESS) {
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *upn,
struct ldb_result **_res)
{
const char *sysdb_name;
size_t i;
return ENOMEM;
}
goto done;
}
goto done;
}
} else {
if (sysdb_name == NULL) {
return EINVAL;
}
"sysdb_add_overrides_to_object() failed.\n");
return ret;
}
}
}
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name,
struct ldb_result **_res)
{
int ret;
size_t c;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
/* User is not cached yet */
goto done;
goto done;
}
/* no need to steal the dn, we are not freeing the result */
/* note we count on the fact that the default search callback
* will just keep appending values. This is by design and can't
* change so it is ok to already have a result (from the getpwnam)
* even before we call the next search */
if (!ctrl) {
goto done;
}
if (!ctrl[0]) {
goto done;
}
if (!control) {
goto done;
}
if (!control->source_attribute) {
goto done;
}
NULL);
if (ret != LDB_SUCCESS) {
goto done;
}
if (ret == LDB_SUCCESS) {
}
if (ret != LDB_SUCCESS) {
goto done;
}
if (DOM_HAS_VIEWS(domain)) {
/* Skip user entry because it already has override values added */
NULL);
"sysdb_add_overrides_to_object failed.\n");
goto done;
}
}
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name,
const char **attributes,
struct ldb_result **_res)
{
char *sanitized_name;
char *lc_sanitized_name;
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
goto done;
}
if (ret) {
goto done;
}
/* Merge in the timestamps from the fast ts db */
/* non-fatal */
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name,
const char **attributes,
struct ldb_result **_res)
{
int ret;
NULL};
return ENOMEM;
}
attrs = attributes;
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
false, discard_const(&attrs));
goto done;
}
"sysdb_search_user_override_attrs_by_name failed.\n");
return ret;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
return ret;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
attrs);
return ret;
}
} else {
}
goto done;
}
}
done:
return ret;
}
/* This function splits a three-tuple into three strings
* It assumes that any whitespace between the parentheses
* and commas are intentional and does not attempt to
* strip them out. Leading and trailing whitespace is
* ignored.
*
* This behavior is compatible with nss_ldap's
* implementation.
*/
const char *triple,
char **hostname,
char **username,
char **domainname)
{
const char *p = triple;
const char *p_host;
const char *p_user;
const char *p_domain;
/* Pre-set the values to NULL here so if they are not
* copied, we don't return garbage below.
*/
*domainname = NULL;
if (!tmp_ctx) {
return ENOMEM;
}
/* Remove any leading whitespace */
while (*p && isspace(*p)) p++;
if (*p != '(') {
/* Triple must start and end with parentheses */
goto done;
}
p++;
p_host = p;
/* Find the first comma */
while (*p && *p != ',') p++;
if (!*p) {
/* No comma was found: parse error */
goto done;
}
if (len > 0) {
/* Copy the host string */
if (!host) {
goto done;
}
}
p++;
p_user = p;
/* Find the second comma */
while (*p && *p != ',') p++;
if (!*p) {
/* No comma was found: parse error */
goto done;
}
if (len > 0) {
/* Copy the user string */
if (!user) {
goto done;
}
}
p++;
p_domain = p;
/* Find the closing parenthesis */
while (*p && *p != ')') p++;
if (*p != ')') {
/* No trailing parenthesis: parse error */
goto done;
}
if (len > 0) {
/* Copy the domain string */
if (!domain) {
goto done;
}
}
p++;
/* skip trailing whitespace */
while (*p && isspace(*p)) p++;
if (*p) {
/* Extra data after the closing parenthesis
* is a parse error
*/
goto done;
}
/* Return any non-NULL values */
if (host) {
}
if (user) {
}
if (domain) {
}
done:
return ret;
}
struct ldb_result *res,
struct sysdb_netgroup_ctx ***entries,
{
size_t c = 0;
char *triple_str;
int i, j;
return ENOENT;
}
if (!tmp_ctx) {
return ENOMEM;
}
}
}
}
goto done;
}
if (size != 0) {
/* Copy in all of the entries */
for(j = 0; j < el->num_values; j++) {
if (!triple_str) {
goto done;
}
struct sysdb_netgroup_ctx);
if (!tmp_entry[c]) {
goto done;
}
"Cannot split netgroup triple [%s], "
"this attribute will be skipped \n",
continue;
}
c++;
}
}
for(j = 0; j < el->num_values; j++) {
struct sysdb_netgroup_ctx);
if (!tmp_entry[c]) {
goto done;
}
goto done;
}
c++;
}
}
}
}
/* Add NULL terminator */
*netgroup_count = c;
done:
return ret;
}
struct sss_domain_info *domain,
const char *netgroup,
struct ldb_result **res)
{
char *sanitized_netgroup;
char *lc_sanitized_netgroup;
char *netgroup_dn;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
goto done;
}
if (!netgroup_dn) {
goto done;
}
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *netgrname,
const char **attributes,
struct ldb_result **res)
{
char *sanitized_netgroup;
char *lc_sanitized_netgroup;
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
if (!base_dn) {
goto done;
}
goto done;
}
if (ret) {
goto done;
}
done:
return ret;
}
struct sss_domain_info *dom,
struct sss_domain_info *parent_dom,
enum sysdb_member_type mtype,
const char *name,
char ***_direct_parents)
{
const char *dn;
char *sanitized_dn;
const char *member_filter;
int i, pi;
const char *tmp_str;
if (mtype == SYSDB_MEMBER_USER) {
} else if (mtype == SYSDB_MEMBER_GROUP) {
} else {
goto done;
}
if (!dn) {
goto done;
}
goto done;
}
if (!member_filter) {
goto done;
}
if (parent_dom == NULL) {
} else {
}
if (!basedn) {
goto done;
}
"searching sysdb with filter [%s]\n", member_filter);
direct_sysdb_count = 0;
goto done;
}
/* EOK */
/* Get the list of sysdb groups by name */
if (!direct_parents) {
goto done;
}
pi = 0;
for(i = 0; i < direct_sysdb_count; i++) {
SYSDB_NAME, NULL);
if (!tmp_str) {
/* This should never happen, but if it does, just continue */
continue;
}
if (!direct_parents[pi]) {
goto done;
}
pi++;
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *name_or_upn_or_sid,
const char **_cname)
{
const char *cname;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
&res);
"sysdb_search_object_by_uuid failed or returned "
"more than one result [%d][%s].\n",
goto done;
}
}
}
/* User cannot be found in cache */
goto done;
}
} else {
goto done;
}
if (!cname) {
goto done;
}
done:
return ret;
}
struct sss_domain_info *domain,
const char *cert,
struct ldb_result **res)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
/* If there are views we first have to search the overrides for matches */
if (DOM_HAS_VIEWS(domain)) {
&override_obj, &orig_obj);
"sysdb_search_override_by_cert failed.\n");
goto done;
}
}
/* If there are no views or nothing was found in the overrides the
* original objects are searched. */
goto done;
}
}
/* If there are views we have to check if override values must be added to
* the original object. */
NULL);
} else {
}
goto done;
goto done;
}
}
done:
return ret;
}
struct ldb_result *ts_res)
{
int ret;
return sysdb_res;
}
struct ldb_message *,
total);
return NULL;
}
/* FIXME - this is O(2), so inefficient for large sets! */
if (ret == 0) {
break;
}
}
/* We already have this DN but ts_res might be more up-to-date
* wrt timestamps */
continue;
}
/* new DN, merge */
count++;
}
struct ldb_message *,
count);
return NULL;
}
}
return sysdb_res;
}
{
size_t i;
for (i = 0; sysdb_ts_cache_attrs[i] != NULL; i++) {
break;
}
}
if (sysdb_ts_cache_attrs[i] == NULL) {
return false;
}
return true;
}
struct sysdb_attrs *attrs)
{
int ti = 0;
return NULL;
}
struct ldb_message_element,
return NULL;
}
ti++;
}
}
return ts_attrs;
}