/*
SSSD
LDAP Provider Common Functions
Authors:
Simo Sorce <ssorce@redhat.com>
Copyright (C) 2008-2010 Red Hat
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 "providers/ldap/ldap_common.h"
#include "providers/fail_over.h"
#include "providers/ldap/sdap_async_private.h"
#include "providers/krb5/krb5_common.h"
#include "db/sysdb_sudo.h"
#include "db/sysdb_services.h"
#include "db/sysdb_autofs.h"
#include "util/sss_krb5.h"
#include "util/crypto/sss_crypto.h"
#include "providers/ldap/ldap_opts.h"
#include "providers/ldap/sdap_idmap.h"
/* a fd the child process would log into */
int ldap_child_debug_fd = -1;
int
sdap_domain_destructor(void *mem)
{
struct sdap_domain *dom =
talloc_get_type(mem, struct sdap_domain);
DLIST_REMOVE(*(dom->head), dom);
return 0;
}
struct sdap_domain *
sdap_domain_get(struct sdap_options *opts,
struct sss_domain_info *dom)
{
struct sdap_domain *sditer = NULL;
DLIST_FOR_EACH(sditer, opts->sdom) {
if (sditer->dom == dom) {
break;
}
}
return sditer;
}
errno_t
sdap_domain_add(struct sdap_options *opts,
struct sss_domain_info *dom,
struct sdap_domain **_sdom)
{
struct sdap_domain *sdom;
sdom = talloc_zero(opts, struct sdap_domain);
if (sdom == NULL) {
return ENOMEM;
}
sdom->dom = dom;
sdom->head = &opts->sdom;
if (opts->sdom) {
/* Only allow subdomains of the parent domain */
if (dom->parent == NULL ||
dom->parent != opts->sdom->dom) {
DEBUG(SSSDBG_OP_FAILURE, ("Domain %s is not a subdomain of %s\n",
dom->name, opts->sdom->dom->name));
return EINVAL;
}
}
talloc_set_destructor((TALLOC_CTX *)sdom, sdap_domain_destructor);
DLIST_ADD_END(opts->sdom, sdom, struct sdap_domain *);
if (_sdom) *_sdom = sdom;
return EOK;
}
void
sdap_domain_remove(struct sdap_options *opts,
struct sss_domain_info *dom)
{
struct sdap_domain *sdom;
sdom = sdap_domain_get(opts, dom);
if (sdom == NULL) return;
DLIST_REMOVE(*(sdom->head), sdom);
}
int ldap_get_options(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct confdb_ctx *cdb,
const char *conf_path,
struct sdap_options **_opts)
{
struct sdap_attr_map *default_attr_map;
struct sdap_attr_map *default_user_map;
struct sdap_attr_map *default_group_map;
struct sdap_attr_map *default_netgroup_map;
struct sdap_attr_map *default_service_map;
struct sdap_options *opts;
char *schema;
const char *search_base;
const char *pwd_policy;
int ret;
int account_cache_expiration;
int offline_credentials_expiration;
const char *ldap_deref;
int ldap_deref_val;
int o;
const char *authtok_type;
struct dp_opt_blob authtok_blob;
char *cleartext;
const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
SDAP_GROUP_SEARCH_BASE,
SDAP_NETGROUP_SEARCH_BASE,
SDAP_SERVICE_SEARCH_BASE,
-1 };
opts = talloc_zero(memctx, struct sdap_options);
if (!opts) return ENOMEM;
ret = sdap_domain_add(opts, dom, NULL);
if (ret != EOK) {
goto done;
}
ret = dp_get_options(opts, cdb, conf_path,
default_basic_opts,
SDAP_OPTS_BASIC,
&opts->basic);
if (ret != EOK) {
goto done;
}
/* Handle search bases */
search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
if (search_base != NULL) {
/* set user/group/netgroup search bases if they are not */
for (o = 0; search_base_options[o] != -1; o++) {
if (NULL == dp_opt_get_string(opts->basic, search_base_options[o])) {
ret = dp_opt_set_string(opts->basic, search_base_options[o],
search_base);
if (ret != EOK) {
goto done;
}
DEBUG(6, ("Option %s set to %s\n",
opts->basic[search_base_options[o]].opt_name,
dp_opt_get_string(opts->basic,
search_base_options[o])));
}
}
} else {
DEBUG(5, ("Search base not set, trying to discover it later when "
"connecting to the LDAP server.\n"));
}
/* Default search */
ret = sdap_parse_search_base(opts, opts->basic,
SDAP_SEARCH_BASE,
&opts->sdom->search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* User search */
ret = sdap_parse_search_base(opts, opts->basic,
SDAP_USER_SEARCH_BASE,
&opts->sdom->user_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Group search base */
ret = sdap_parse_search_base(opts, opts->basic,
SDAP_GROUP_SEARCH_BASE,
&opts->sdom->group_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Netgroup search */
ret = sdap_parse_search_base(opts, opts->basic,
SDAP_NETGROUP_SEARCH_BASE,
&opts->sdom->netgroup_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Service search */
ret = sdap_parse_search_base(opts, opts->basic,
SDAP_SERVICE_SEARCH_BASE,
&opts->sdom->service_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY);
if (pwd_policy == NULL) {
DEBUG(1, ("Missing password policy, this may not happen.\n"));
ret = EINVAL;
goto done;
}
if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) != 0 &&
|