confdb.c revision b5825c74b6bf7a99ae2172392dbecb51179013a6
/*
SSSD
NSS Configuratoin DB
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 "config.h"
#include <ctype.h>
#include "confdb/confdb_private.h"
#include "util/strtonum.h"
if (!var) { \
goto label; \
} \
} while(0)
/* Warning messages */
#define SAME_DOMAINS_ERROR_MSG "Domain '%s' is the same as or differs only "\
"in case from domain '%s'.\n"
{
char *ret;
if (!ret)
return NULL;
/* move current string to the end */
return ret;
}
{
char *p;
const char *s;
int l, ret;
/* section must be a non null string and must not start with '/' */
s = section;
l = 0;
while ((p = strchrnul(s, '/'))) {
if (l == 0) {
l = 3 + (p-s);
dn[l] = '\0';
} else {
}
if (!dn) {
goto done;
}
if (*p == '\0') {
break; /* reached end */
}
s = p+1;
if (*s == '\0') { /* a section cannot end in '.' */
goto done;
}
}
done:
return ret;
}
bool replace,
const char *section,
const char *attribute,
const char **values)
{
struct ldb_message *msg;
struct ldb_result *res;
char *secdn;
const char *rdn_name;
int ret, i;
if (!tmp_ctx) {
goto done;
}
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
errno = 0;
/* cn first */
if (ret != LDB_SUCCESS) {
goto done;
}
/* now the requested attribute */
for (i = 0; values[i]; i++) {
if (ret != LDB_SUCCESS) {
goto done;
}
}
if (ret != LDB_SUCCESS) {
goto done;
}
} else {
int optype;
errno = 0;
/* mark this as a replacement */
else optype = LDB_FLAG_MOD_ADD;
if (ret != LDB_SUCCESS) {
goto done;
}
/* now the requested attribute */
for (i = 0; values[i]; i++) {
if (ret != LDB_SUCCESS) {
goto done;
}
}
if (ret != LDB_SUCCESS) {
"ldb_modify failed: [%s](%d)[%s]\n",
goto done;
}
}
done:
"Failed to add [%s] to [%s], error [%d] (%s)\n",
}
return ret;
}
const char *section,
const char *attribute,
char ***values)
{
struct ldb_result *res;
char *secdn;
char **vals;
struct ldb_message_element *el;
int ret, i;
if (!tmp_ctx)
return ENOMEM;
goto done;
}
if (!dn) {
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
goto done;
}
if (!vals) {
goto done;
}
/* should always be strings so this should be safe */
for (i = 0; i < el->num_values; i++) {
if (!vals[i]) {
goto done;
}
}
}
}
done:
"Failed to get [%s] from [%s], error [%d] (%s)\n",
}
return ret;
}
const char *section,
const char *attribute,
const char *val)
{
char *secdn;
struct ldb_message *msg;
if (!tmp_ctx) {
return ENOMEM;
}
goto done;
}
if (!dn) {
goto done;
}
if (!msg) {
goto done;
}
if (lret != LDB_SUCCESS) {
goto done;
}
if (lret != LDB_SUCCESS) {
goto done;
}
if (lret != LDB_SUCCESS) {
"ldb_modify failed: [%s](%d)[%s]\n",
goto done;
}
done:
"Failed to set [%s] from [%s], error [%d] (%s)\n",
}
return ret;
}
{
char *restr;
int ret;
goto failed;
}
if (values[0]) {
/* too many values */
goto failed;
}
} else {
/* Did not return a value, so use the default */
return EOK;
}
/* Copy the default string */
}
if (!restr) {
goto failed;
}
return EOK;
"Failed to get [%s] from [%s], error [%d] (%s)\n",
return ret;
}
{
long val;
int ret;
goto failed;
}
goto failed;
}
if (values[0]) {
/* too many values */
goto failed;
}
errno = 0;
if (errno) {
goto failed;
}
goto failed;
}
} else {
}
return EOK;
"Failed to read [%s] from [%s], error [%d] (%s)\n",
return ret;
}
{
long val;
int ret;
goto failed;
}
goto failed;
}
if (values[0]) {
/* too many values */
goto failed;
}
errno = 0;
if (errno) {
goto failed;
}
} else {
}
return EOK;
"Failed to read [%s] from [%s], error [%d] (%s)\n",
return ret;
}
{
bool val;
int ret;
goto failed;
}
goto failed;
}
if (values[0]) {
/* too many values */
goto failed;
}
val = false;
val = true;
} else {
goto failed;
}
} else {
}
return EOK;
"Failed to read [%s] from [%s], error [%d] (%s)\n",
return ret;
}
/* WARNING: Unlike other similar functions, this one does NOT take a default,
* and returns ENOENT if the attribute was not found ! */
char ***result)
{
int ret;
goto done;
}
/* too many values */
goto done;
}
} else {
/* Did not return a value */
goto done;
}
done:
"Failed to get [%s] from [%s], error [%d] (%s)\n",
}
return ret;
}
struct confdb_ctx **cdb_ctx,
const char *confdb_location)
{
struct confdb_ctx *cdb;
if (!cdb)
return ENOMEM;
/* Because confdb calls use sync ldb calls, we create a separate event
* context here. This will prevent the ldb sync calls to start nested
* events.
* NOTE: this means that we *cannot* do async calls and return in confdb
* unless we convert all calls and hook back to the main event context.
*/
return EIO;
}
return EIO;
}
if (ret != LDB_SUCCESS) {
return EIO;
}
if (ret != LDB_SUCCESS) {
return EIO;
}
return EOK;
}
const char *entry,
{
char *endptr;
*return_value = 0;
return EFAULT;
}
return EOK;
}
return EINVAL;
}
if (errno) {
return errno;
}
if (*endptr != '\0') {
/* Not all of the string was a valid number */
return EINVAL;
}
*return_value = u32ret;
return EOK;
}
bool *return_value,
const char *entry,
bool default_value)
{
*return_value = 0;
return EFAULT;
}
return EOK;
}
*return_value = 0;
}
*return_value = 1;
}
else {
return EINVAL;
}
return EOK;
}
* the local provider */
{
}
return defval;
}
struct ldb_message *msg,
{
int cred_expiration;
int id_timeout;
"Invalid value for [%s]\n", CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT);
goto done;
}
"Failed to read expiration time of offline credentials.\n");
goto done;
}
/* convert from days to seconds */
if (cred_expiration != 0 &&
}
/* Set up the PAM identity timeout */
&id_timeout);
if (cached_auth_timeout > id_timeout) {
"cached_auth_timeout is greater than pam_id_timeout so be aware "
"that back end could be called to handle initgroups.\n");
}
done:
}
return ret;
}
const char *name,
struct sss_domain_info **_domain)
{
struct sss_domain_info *domain;
struct ldb_result *res;
const char *tmp;
char *default_domain;
bool fqnames_default = false;
if (!dn) {
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
goto done;
}
if (!domain) {
goto done;
}
if (!tmp) {
"Invalid configuration entry, fatal error!\n");
goto done;
}
goto done;
}
NULL);
if (tmp) {
goto done;
}
}
else {
"Domain [%s] does not specify an ID provider, disabling!\n",
goto done;
}
/* The files provider is not valid anymore */
goto done;
}
/* If this is the local provider, we need to ensure that
* no other provider was specified for other types, since
* the local provider cannot load them.
*/
NULL);
"Local ID provider does not support [%s] as an AUTH provider.\n", tmp);
goto done;
}
NULL);
"Local ID provider does not support [%s] as an ACCESS provider.\n", tmp);
goto done;
}
NULL);
"Local ID provider does not support [%s] as a CHPASS provider.\n", tmp);
goto done;
}
/* The LOCAL provider use always Magic Private Groups */
}
/* Determine if this domain can be enumerated */
/* TEMP: test if the old bitfield conf value is used and warn it has been
* superceeded. */
if (val > 0) { /* ok there was a number in here */
"Warning: enumeration parameter in %s still uses integers! "
} else { /* assume the new format */
"Invalid value for %s\n", CONFDB_DOMAIN_ENUMERATE);
goto done;
}
}
}
"Cannnot get the default domain [%d]: %s\n",
goto done;
}
* in NSS interfaces */
if (default_domain != NULL) {
"Default domain suffix set. Changing default for "
"use_fully_qualified_names to True.\n");
fqnames_default = true;
}
goto done;
}
"Invalid configuration detected (default_domain_suffix is used "
"while use_fully_qualified_names was set to false).\n");
goto done;
}
"Invalid value for %s\n",
goto done;
}
goto done;
}
CONFDB_DOMAIN_MAXID, 0);
goto done;
}
goto done;
}
/* Do we allow to cache credentials */
"Invalid value for %s\n", CONFDB_DOMAIN_CACHE_CREDS);
goto done;
}
"Invalid value for %s\n",
goto done;
}
"Invalid value for %s\n", CONFDB_DOMAIN_LEGACY_PASS);
goto done;
}
/* Get the global entry cache timeout setting */
"Invalid value for [%s]\n",
goto done;
}
/* Override the user cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the group cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the netgroup cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the service cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the autofs cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the sudo cache timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Override the ssh known hosts timeout, if specified */
"Invalid value for [%s]\n",
goto done;
}
/* Set refresh_expired_interval, if specified */
0);
"Invalid value for [%s]\n",
goto done;
}
/* detect and fix misconfiguration */
"refresh_expired_interval (%d) cannot be greater than "
"entry_cache_timeout (%u)\n",
"refresh_expired_interval is being set to recommended value "
"entry_cache_timeout * 0.75 (%u).\n",
}
/* Set the PAM warning time, if specified. If not specified, pass on
* the "not set" value of "-1" which means "use provider default". The
* value 0 means "always display the warning if server sends one" */
-1);
if (val == -1) {
-1, &val);
"Failed to read PAM expiration warning, not fatal.\n");
val = -1;
}
}
if (val >= 0) {
"Setting domain password expiration warning to %d days\n", val);
/* The value is in days, transform it to seconds */
}
"Invalid value for [%s]\n", CONFDB_DOMAIN_OVERRIDE_GID);
goto done;
}
if (!domain->override_homedir) {
goto done;
}
}
if (!domain->fallback_homedir) {
goto done;
}
}
if (!domain->subdomain_homedir) {
goto done;
}
}
goto done;
}
}
if (!domain->override_shell) {
goto done;
}
}
if (!domain->default_shell) {
goto done;
}
}
CONFDB_DOMAIN_CASE_SENSITIVE, "true");
domain->case_sensitive = true;
domain->case_preserve = true;
domain->case_sensitive = false;
domain->case_preserve = false;
domain->case_sensitive = false;
domain->case_preserve = true;
} else {
"Invalid value for %s\n", CONFDB_DOMAIN_CASE_SENSITIVE);
goto done;
}
} else {
/* default */
domain->case_sensitive = true;
domain->case_preserve = true;
}
if (domain->case_sensitive == false &&
"Local ID provider does not support the case insensitive flag\n");
goto done;
}
if (ret != 0) {
"Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
goto done;
}
}
NULL);
if (ret != 0) {
"Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
goto done;
}
}
CONFDB_DOMAIN_SUBDOMAIN_REFRESH, 14400);
"Invalid value for [%s]\n", CONFDB_DOMAIN_SUBDOMAIN_REFRESH);
goto done;
}
"init_cached_auth_timeout failed: %s:[%d].\n",
goto done;
}
done:
return ret;
}
struct sss_domain_info **domains)
{
char **domlist;
int ret, i;
return EOK;
}
&domlist);
goto done;
}
goto done;
}
for (i = 0; domlist[i]; i++) {
/* check if domain name is really unique */
goto done;
}
}
if (ret) {
"Error (%d [%s]) retrieving domain [%s], skipping!\n",
continue;
}
}
"No properly configured domains, fatal error!\n");
goto done;
}
done:
return ret;
}
const char *name,
struct sss_domain_info **_domain)
{
int ret;
return ret;
}
return EOK;
}
}
return ENOENT;
}
struct confdb_ctx *cdb,
char ***_names)
{
int i;
int ret;
return ENOMEM;
}
goto done;
}
if (ret != LDB_SUCCESS) {
goto done;
}
goto done;
}
NULL);
"The object [%s] doesn't have a name\n",
goto done;
}
goto done;
}
}
done:
return ret;
}