ipa_subdomains_id.c revision e2d96566aeb881bd89e5c9236d663f6a9a88019a
/*
SSSD
IPA Identity Backend Module for sub-domains
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2012 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 <errno.h>
#include "util/strtonum.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
#include "providers/ipa/ipa_subdomains.h"
static struct tevent_req *
struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct sysdb_attrs *override_attrs,
struct be_acct_req *ar);
static errno_t
struct ipa_subdomain_account_state {
struct tevent_context *ev;
struct ipa_id_ctx *ipa_ctx;
struct sdap_id_ctx *ctx;
struct sdap_id_op *op;
struct sss_domain_info *domain;
struct be_acct_req *ar;
bool ipa_server_mode;
bool server_retry;
int entry_type;
const char *filter;
int filter_type;
struct sysdb_attrs *override_attrs;
int dp_error;
};
struct be_acct_req *ar);
struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct be_acct_req *ar)
{
struct tevent_req *req;
struct ipa_subdomain_account_state *state;
struct tevent_req *subreq;
int ret;
return NULL;
}
goto fail;
}
goto fail;
}
/* With views we cannot got directly to the look up the AD objects but
* have to check first if the request matches an override in the given
* view. But there are cases where this can be skipped and the AD object
* can be searched directly:
* - if no view is defined, i.e. the server does not supprt views yet
* - searches by SID: because we do not override the SID
* - if the responder does not send the EXTRA_INPUT_MAYBE_WITH_VIEW flags,
* because in this case the entry was found in the cache and the
* original value is used for the search (e.g. during cache updates) */
|| (!state->ipa_server_mode
EXTRA_INPUT_MAYBE_WITH_VIEW) != 0 )) {
"ipa_subdomain_account_get_original_step failed.\n");
goto fail;
}
return req;
}
if (!subreq) {
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req);
struct ipa_subdomain_account_state);
int dp_error = DP_ERR_FATAL;
int ret;
goto fail;
}
goto fail;
}
return;
fail:
return;
}
#define OVERRIDE_ANCHOR_SID_PREFIX ":SID:"
{
struct tevent_req);
struct ipa_subdomain_account_state);
int dp_error = DP_ERR_FATAL;
int ret;
struct be_acct_req *ar;
&state->override_attrs);
goto fail;
}
&anchor);
goto fail;
}
OVERRIDE_ANCHOR_SID_PREFIX_LEN) == 0) {
&ar);
goto fail;
}
if (state->ipa_server_mode
== BE_REQ_INITGROUPS) {
"Switching back to BE_REQ_INITGROUPS.\n");
}
} else {
"Unsupported override anchor type [%s].\n", anchor);
goto fail;
}
} else {
}
"ipa_subdomain_account_get_original_step failed.\n");
goto fail;
}
return;
fail:
return;
}
struct be_acct_req *ar)
{
struct ipa_subdomain_account_state);
struct tevent_req *subreq;
if (state->ipa_server_mode) {
} else {
}
return ENOMEM;
}
return EOK;
}
{
struct tevent_req);
struct ipa_subdomain_account_state);
int dp_error = DP_ERR_FATAL;
int ret;
if (state->ipa_server_mode) {
} else {
}
return;
}
return;
}
{
struct ipa_subdomain_account_state);
if (dp_error_out) {
}
return EOK;
}
struct ipa_get_subdom_acct {
struct tevent_context *ev;
struct ipa_id_ctx *ipa_ctx;
struct sdap_id_ctx *ctx;
struct sdap_id_op *op;
struct sss_domain_info *domain;
struct sysdb_attrs *override_attrs;
int entry_type;
const char *filter;
int filter_type;
int dp_error;
};
struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct sysdb_attrs *override_attrs,
struct be_acct_req *ar)
{
struct tevent_req *req;
struct ipa_get_subdom_acct *state;
struct tevent_req *subreq;
int ret;
goto fail;
}
goto fail;
}
switch (state->entry_type) {
case BE_REQ_USER:
case BE_REQ_GROUP:
case BE_REQ_BY_SECID:
case BE_REQ_USER_AND_GROUP:
case BE_REQ_INITGROUPS:
break;
default:
}
if (!subreq) {
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req);
struct ipa_get_subdom_acct);
int dp_error = DP_ERR_FATAL;
int ret;
char *endptr;
return;
}
/* With V1 of the extdom plugin a user lookup will resolve the full
* group membership of the user. */
} else {
"by the IPA provider but are resolved " \
"by the responder directly from the " \
"cache.\n");
return;
}
}
return;
}
switch (state->filter_type) {
case BE_FILTER_NAME:
return;
}
break;
case BE_FILTER_IDNUM:
return;
}
break;
case BE_FILTER_SECID:
return;
}
break;
default:
return;
}
if (!subreq) {
return;
}
return;
}
{
struct tevent_req);
struct ipa_get_subdom_acct);
int dp_error = DP_ERR_FATAL;
int ret;
/* retry */
if (!subreq) {
return;
}
return;
}
return;
}
/* FIXME: do we need some special handling of ENOENT */
}
{
struct ipa_get_subdom_acct);
if (dp_error_out) {
}
return EOK;
}
/* IPA lookup for server mode. Directly to AD. */
struct ipa_get_ad_acct_state {
int dp_error;
struct tevent_context *ev;
struct ipa_id_ctx *ipa_ctx;
struct be_acct_req *ar;
struct sss_domain_info *obj_dom;
char *object_sid;
struct sysdb_attrs *override_attrs;
struct ldb_message *obj_msg;
};
struct sss_domain_info *dom);
static struct tevent_req *
struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct sysdb_attrs *override_attrs,
struct be_acct_req *ar)
{
struct tevent_req *req;
struct tevent_req *subreq;
struct ipa_get_ad_acct_state *state;
struct sdap_domain *sdom;
struct sdap_id_conn_ctx **clist;
struct sdap_id_ctx *sdap_id_ctx;;
/* This can only be a subdomain request, verify subdomain */
goto fail;
}
/* Let's see if this subdomain has a ad_id_ctx */
goto fail;
}
/* We read users and groups from GC. From groups, we may switch to
* using LDAP connection in the group request itself, but in order
* to resolve Universal group memberships, we also need the GC
* connection
*/
case BE_REQ_INITGROUPS:
case BE_REQ_BY_SECID:
case BE_REQ_GROUP:
break;
default:
break;
}
goto fail;
}
/* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */
goto fail;
}
goto fail;
}
return req;
fail:
return req;
}
static struct ad_id_ctx *
struct sss_domain_info *dom)
{
struct ipa_ad_server_ctx *iter;
}
}
static errno_t
{
const char *name;
const char *homedir;
struct sss_nss_homedir_ctx homedir_ctx;
goto done;
}
"Original home directory for user: %s is empty.\n", fqname);
goto done;
}
goto done;
}
/* To be compatible with the old winbind based user lookups and IPA
* clients the user name in the home directory path will be lower-case. */
goto done;
}
&homedir_ctx);
goto done;
}
goto done;
}
done:
return ret;
}
static errno_t
{
bool in_transaction = false;
struct sysdb_attrs *attrs;
goto done;
}
goto done;
}
goto done;
}
goto done;
}
in_transaction = true;
"Failed to update homedir information!\n");
goto done;
}
"Cannot commit sysdb transaction [%d]: %s.\n",
goto done;
}
in_transaction = false;
done:
if (in_transaction) {
}
}
return ret;
}
static errno_t
struct ldb_message *msg)
{
const char *fqname;
const char *original;
size_t c;
goto done;
}
for (c = 0; c < msg_el->num_values; c++) {
break;
}
}
if (c == msg_el->num_values) {
"User objectclass not found, object is not a user.\n");
goto done;
}
goto done;
}
if (uid == 0) {
fqname);
goto done;
}
}
&homedir);
"get_subdomain_homedir_of_user failed: [%d]: [%s]\n",
if (ret == ERR_HOMEDIR_IS_NULL) {
/* This is not fatal, fallback_homedir will be used. */
}
goto done;
}
"store_homedir_of_user failed: [%d]: [%s]\n",
goto done;
}
done:
return ret;
}
struct sss_domain_info *dom,
struct be_acct_req *ar,
struct ldb_message **_msg)
{
const char *attrs[] = { SYSDB_NAME,
NULL };
char *name;
&res);
"Failed to make request to our cache: [%d]: [%s]\n",
goto done;
}
goto done;
&res);
"Failed to make request to our cache: [%d]: [%s]\n",
goto done;
}
goto done;
&res);
"Failed to make request to our cache: [%d]: [%s]\n",
goto done;
}
goto done;
errno = 0;
if (errno != 0) {
goto done;
}
case BE_REQ_GROUP:
break;
case BE_REQ_INITGROUPS:
case BE_REQ_USER:
case BE_REQ_USER_AND_GROUP:
== BE_REQ_USER_AND_GROUP) {
}
break;
default:
goto done;
}
goto done;
}
case BE_REQ_GROUP:
break;
case BE_REQ_INITGROUPS:
case BE_REQ_USER:
case BE_REQ_USER_AND_GROUP:
== BE_REQ_USER_AND_GROUP) {
}
break;
default:
goto done;
}
} else {
goto done;
}
"Failed to make request to our cache: [%d]: [%s]\n",
goto done;
}
done:
return ret;
}
static void
{
struct tevent_req);
struct ipa_get_ad_acct_state);
const char *sid;
struct be_acct_req *ar;
if (ret == ERR_SUBDOM_INACTIVE) {
return;
return;
}
return;
goto fail;
}
"apply_subdomain_homedir failed: [%d]: [%s].\n",
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
ar);
goto fail;
}
} else {
"ipa_get_ad_apply_override_step failed.\n");
goto fail;
}
}
return;
fail:
return;
}
static void
{
struct tevent_req);
struct ipa_get_ad_acct_state);
&state->override_attrs);
return;
}
goto fail;
}
return;
fail:
return;
}
{
struct ipa_get_ad_acct_state);
struct tevent_req *subreq;
const char *obj_name;
int entry_type;
size_t groups_count = 0;
const char *attrs[] = SYSDB_INITGR_ATTRS;
/* We are in ipa-server-mode, so the view is the default view by
* definition. */
return ret;
}
}
if (entry_type != BE_REQ_INITGROUPS
&& entry_type != BE_REQ_USER
&& entry_type != BE_REQ_BY_SECID) {
return EOK;
}
/* Replace ID with name in search filter */
|| (entry_type == BE_REQ_INITGROUPS
|| entry_type == BE_REQ_BY_SECID) {
"Object not found, ending request\n");
return EOK;
return ret;
}
}
NULL);
return EINVAL;
}
return ENOMEM;
}
}
/* Lookup all groups the user is a member of which do not have ORIGINALAD
* attributes set, i.e. where overrides might not have been applied. */
return ret;
}
return ENOMEM;
}
return EOK;
}
return ret;
}
return EOK;
}
{
struct tevent_req);
"IPA resolve user groups overrides failed [%d].\n", ret);
return;
}
return;
}
return;
}
{
struct ipa_get_ad_acct_state);
struct tevent_req *subreq;
/* For initgroups request we have to check IPA group memberships of AD
* users. This has to be done for other user-request as well to make sure
* IPA related attributes are not overwritten. */
return ENOMEM;
}
return EOK;
}
static void
{
struct tevent_req);
struct ipa_get_ad_acct_state);
ret);
return;
}
}
static errno_t
{
struct ipa_get_ad_acct_state);
if (dp_error_out) {
}
return EOK;
}
struct ipa_srv_ad_acct_state {
struct tevent_context *ev;
struct ipa_id_ctx *ipa_ctx;
struct sysdb_attrs *override_attrs;
struct be_acct_req *ar;
struct sss_domain_info *obj_dom;
bool retry;
int dp_error;
};
static struct tevent_req *
struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct sysdb_attrs *override_attrs,
struct be_acct_req *ar)
{
struct tevent_req *req;
struct ipa_srv_ad_acct_state *state;
return NULL;
}
goto fail;
}
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req *subreq;
struct ipa_srv_ad_acct_state);
return ENOMEM;
}
return EOK;
}
{
int dp_error = DP_ERR_FATAL;
struct tevent_req);
struct ipa_srv_ad_acct_state);
"Sudomain lookup failed, will try to reset sudomain..\n");
goto fail;
}
return;
goto fail;
}
return;
fail:
}
{
struct tevent_req);
struct ipa_srv_ad_acct_state);
}
}
}
static errno_t
{
struct ipa_srv_ad_acct_state);
if (dp_error_out) {
}
return EOK;
}