/*
SSSD
AD Subdomains Module
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2013 Red Hat
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/sdap_async.h"
#include "providers/ad/ad_subdomains.h"
#include "providers/ad/ad_domain_info.h"
#include "providers/ad/ad_common.h"
#include "providers/ldap/sdap_idmap.h"
#include "providers/ldap/sdap_ops.h"
#include "util/util_sss_idmap.h"
#include <ctype.h>
#include <ndr.h>
/* Attributes of AD trusted domains */
/* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
* for example.
*
* The absence of msDS-TrustForestTrustInfo attribute denotes a domain from
* the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
* for more information.
*/
#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
/* do not refresh more often than every 5 seconds for now */
const char *ad_domain,
const char ***_ad_enabled_domains)
{
int ret;
const char *str;
const char *option_name;
int count;
bool is_ad_in_domains;
return ENOMEM;
}
goto done;
}
count = 0;
goto done;
}
is_ad_in_domains = false;
for (int i = 0; i < count; i++) {
}
if (is_ad_in_domains == false) {
goto done;
}
goto done;
}
} else {
goto done;
}
}
done:
return ret;
}
const char **enabled_doms)
{
if (enabled_doms == NULL) {
return true;
}
}
static errno_t
struct sss_domain_info *subdom,
struct ad_id_ctx **_subdom_id_ctx)
{
const char *gc_service_name;
const char *service_name;
char *ad_domain;
char *ad_site_override;
const char *realm;
const char *hostname;
const char *keytab;
return EINVAL;
}
if (ad_options == NULL) {
return ENOMEM;
}
if (gc_service_name == NULL) {
return ENOMEM;
}
if (service_name == NULL) {
return ENOMEM;
}
return ret;
}
return ENOMEM;
}
/* use AD plugin */
return ENOMEM;
}
return ret;
}
return EFAULT;
}
/* Set up the ID mapping object */
return EOK;
}
struct ad_subdomains_ctx {
char *domain_name;
const char **ad_enabled_domains;
};
struct sysdb_attrs *attrs,
bool *_enumerates)
{
const char *name;
return ret;
}
return EOK;
}
static errno_t
struct sss_domain_info *domain,
struct sysdb_attrs *subdom_attrs,
bool enumerate)
{
const char *name;
char *realm;
const char *flat;
bool mpg;
goto done;
}
&trust_type);
goto done;
}
goto done;
}
if (!realm) {
goto done;
}
if (ret) {
name);
goto done;
}
goto done;
}
if (err != IDMAP_SUCCESS) {
goto done;
}
goto done;
}
done:
return ret;
}
struct sdap_idmap_ctx *idmap_ctx,
struct sdap_options *opts,
struct sysdb_attrs **subdomains,
bool root_domain,
bool *_changes)
{
const char *value;
size_t c, h;
int ret;
bool enumerate;
h = 0;
if (root_domain) {
&root_name);
goto done;
}
}
/* check existing subdomains */
/* If we are handling root domain, skip all the other domains. We don't
* want to accidentally remove non-root domains
*/
continue;
}
for (c = 0; c < num_subdomains; c++) {
if (handled[c]) {
continue;
}
&value);
goto done;
}
break;
}
}
if (c >= num_subdomains) {
/* ok this subdomain does not exist anymore, let's clean up */
goto done;
}
continue;
}
/* Remove the subdomain from the list of LDAP domains */
/* terminate all requests for this subdomain so we can free it */
} else {
/* ok let's try to update it */
goto done;
}
if (ret) {
/* Nothing we can do about the error. Let's at least try
* to reuse the existing domains
*/
"will try to use cached subdomain\n");
}
handled[c] = true;
h++;
}
}
if (num_subdomains == h) {
/* all domains were already accounted for and have been updated */
*_changes = false;
goto done;
}
/* if we get here it means we have changes to the subdomains list */
*_changes = true;
for (c = 0; c < num_subdomains; c++) {
if (handled[c]) {
continue;
}
/* Nothing we can do about the error. Let's at least try
* to reuse the existing domains.
*/
goto done;
}
if (ret) {
"will try to use cached subdomain\n");
}
}
done:
*_last_refreshed = 0;
} else {
}
return ret;
}
struct sss_domain_info *domain,
const char **enabled_domains_list,
struct sysdb_attrs *root,
struct sysdb_attrs ***_sd_out)
{
const char *sd_name;
const char *root_name;
/* We are connected directly to the root domain. The 'sd'
* list is complete and we can just use it
*/
return EOK;
}
/* If we searched for root separately, we must:
* a) treat the root domain as a subdomain
* b) filter the subdomain we are connected to from the subdomain
* list, from our point of view, it's the master domain
*/
return ENOMEM;
}
sdi = 0;
for (i = 0; i < nsd; i++) {
goto fail;
}
continue;
} else {
}
"Not including primary domain %s in the subdomain list\n",
continue;
}
sdi++;
}
/* Now include the root */
goto fail;
}
sdi++;
} else {
}
}
return EOK;
fail:
return ret;
}
static errno_t
struct sss_domain_info *parent)
{
int ret;
return ret;
}
} else {
}
}
}
return EOK;
}
{
const char *path;
bool canonicalize = false;
} else {
"most probably because the auth provider "
"is not 'ad'. Kerberos configuration "
"snippet to set the 'canonicalize' option "
"will not be created.\n");
}
/* Just continue */
}
return ret;
}
/* Just continue */
}
return ret;
}
return EOK;
}
struct ad_get_slave_domain_state {
};
static struct tevent_req *
struct tevent_context *ev,
struct ad_subdomains_ctx *sd_ctx,
struct sysdb_attrs *root_attrs,
struct ad_id_ctx *root_id_ctx)
{
struct ad_get_slave_domain_state);
return NULL;
}
goto immediately;
}
/* asynchronous processing */
return req;
}
} else {
}
return req;
}
{
int ret;
return ret;
}
return EAGAIN;
}
{
int dp_error;
if (dp_error == DP_ERR_OFFLINE) {
"cannot get the subdomain list while offline\n");
ret = ERR_OFFLINE;
}
return;
}
NULL, false, 0,
return;
}
return;
}
{
bool has_changes;
int dp_error;
/* We continue to finish sdap_id_op. */
}
/* retry */
goto done;
}
return;
} else if (dp_error == DP_ERR_OFFLINE) {
ret = ERR_OFFLINE;
goto done;
goto done;
}
/* Based on whether we are connected to the forest root or not, we might
* need to exclude the subdomain we are connected to from the list of
* subdomains.
*/
return;
}
/* Got all the subdomains, let's process them. */
&has_changes);
goto done;
}
if (has_changes) {
goto done;
}
}
done:
return;
}
}
{
return EOK;
}
static struct sss_domain_info *
{
const char *name;
return NULL;
}
/* With a subsequent run, the root should already be known */
return root;
}
static struct ad_id_ctx *
struct sss_domain_info *root_domain,
struct sdap_options *opts)
{
return NULL;
}
&root_id_ctx);
return NULL;
}
} else {
}
return root_id_ctx;
}
struct ad_get_root_domain_state {
};
static struct tevent_req *
struct tevent_context *ev,
const char *forest,
struct sdap_handle *sh,
struct ad_subdomains_ctx *sd_ctx)
{
const char *filter;
return NULL;
}
goto immediately;
}
goto immediately;
}
goto immediately;
}
return req;
} else {
}
return req;
}
{
bool has_changes;
&reply);
goto done;
}
if (reply_count == 0) {
goto done;
} else if (reply_count > 1) {
"domain list might be incomplete!\n");
goto done;
}
reply, reply_count, true,
&has_changes);
goto done;
}
if (has_changes) {
goto done;
}
}
if (root_domain == NULL) {
goto done;
}
goto done;
}
done:
return;
}
}
struct tevent_req *req,
struct sysdb_attrs **_attrs,
{
return EOK;
}
struct ad_subdomains_refresh_state {
};
static struct tevent_req *
struct tevent_context *ev,
struct ad_subdomains_ctx *sd_ctx)
{
struct ad_subdomains_refresh_state);
return NULL;
}
goto immediately;
}
/* asynchronous processing */
return req;
}
} else {
}
return req;
}
{
int ret;
return ret;
}
return EAGAIN;
}
{
int dp_error;
if (dp_error == DP_ERR_OFFLINE) {
"cannot get the subdomain list while offline\n");
ret = ERR_OFFLINE;
}
return;
}
/* connect to the DC we are a member of */
return;
}
return;
}
{
const char *realm;
char *master_sid;
char *flat_name;
char *forest;
goto done;
}
goto done;
}
goto done;
}
/*
* If ad_enabled_domains contains only master domain
* we shouldn't lookup other domains.
*/
"No other enabled domain than master.\n");
goto done;
}
}
}
goto done;
}
return;
done:
return;
}
}
{
int dp_error;
root_attrs = NULL;
root_id_ctx = NULL;
/* We continue to finish sdap_id_op. */
}
/* We finish sdap_id_op here since we connect
* to forest root for slave domains. */
/* retry */
}
return;
} else if (dp_error == DP_ERR_OFFLINE) {
return;
return;
}
return;
}
return;
}
{
}
return;
}
}
{
return EOK;
}
struct ad_subdomains_handler_state {
};
static struct tevent_req *
struct ad_subdomains_ctx *sd_ctx,
struct dp_subdomains_data *data,
struct dp_req_params *params)
{
struct ad_subdomains_handler_state);
return NULL;
}
"nothing to do\n");
goto immediately;
}
goto immediately;
}
return req;
/* TODO For backward compatibility we always return EOK to DP now. */
return req;
}
{
/* TODO For backward compatibility we always return EOK to DP now. */
}
struct tevent_req *req,
struct dp_reply_std *data)
{
return EOK;
}
static struct tevent_req *
struct tevent_context *ev,
void *pvt)
{
}
static errno_t
{
return ad_subdomains_refresh_recv(req);
}
struct dp_method *dp_methods)
{
const char *ad_domain;
return ENOMEM;
}
return EINVAL;
}
return ENOMEM;
}
"Subdomains Refresh", NULL);
/* Ignore, responders will trigger refresh from time to time. */
}
"Users from trusted domains might not be resolved correctly\n");
/* Ignore this error and try to discover the subdomains later */
}
return EOK;
}