summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/db/sysdb.h9
-rw-r--r--src/db/sysdb_search.c4
-rw-r--r--src/db/sysdb_subdomains.c40
-rw-r--r--src/providers/data_provider_be.c11
-rw-r--r--src/providers/ipa/ipa_s2n_exop.c54
-rw-r--r--src/responder/nss/nsssrv_cmd.c10
-rw-r--r--src/responder/pac/pacsrv_cmd.c15
-rw-r--r--src/responder/pac/pacsrv_utils.c52
-rw-r--r--src/responder/pam/pamsrv_cmd.c5
-rw-r--r--src/util/domain_info_utils.c2
10 files changed, 167 insertions, 35 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index c701717f..6bfe3066 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -437,6 +437,15 @@ errno_t sysdb_store_domgroup(struct sss_domain_info *domain,
errno_t sysdb_delete_domgroup(struct sss_domain_info *domain,
const char *name, gid_t gid);
+int sysdb_subdom_getpwnam(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ struct ldb_result **res);
+int sysdb_subdom_getgrnam(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ struct ldb_result **res);
+
errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
size_t *range_count,
struct range_info ***range_list);
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 1ab94770..49f628bf 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -365,7 +365,9 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- ret = sysdb_getpwnam(tmp_ctx, sysdb, name, &res);
+ /* if this is a subdomain we need to search for the fully qualified
+ * name in the database */
+ ret = sysdb_subdom_getpwnam(tmp_ctx, sysdb, name, &res);
if (ret != EOK) {
DEBUG(1, ("sysdb_getpwnam failed: [%d][%s]\n",
ret, strerror(ret)));
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 2e0170f4..231d481c 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -668,3 +668,43 @@ errno_t sysdb_delete_domgroup(struct sss_domain_info *domain,
return sysdb_delete_group(domain->sysdb, name, gid);
}
+
+int sysdb_subdom_getpwnam(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ struct ldb_result **res)
+{
+ char *src_name = NULL;
+ int ret;
+
+ if (sysdb->domain->parent) {
+ src_name = talloc_asprintf(mem_ctx, sysdb->domain->names->fq_fmt,
+ name, sysdb->domain->name);
+ if (!src_name) return ENOMEM;
+ }
+
+ ret = sysdb_getpwnam(mem_ctx, sysdb, src_name ? src_name : name, res);
+ talloc_zfree(src_name);
+
+ return ret;
+}
+
+int sysdb_subdom_getgrnam(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ struct ldb_result **res)
+{
+ char *src_name = NULL;
+ int ret;
+
+ if (sysdb->domain->parent) {
+ src_name = talloc_asprintf(mem_ctx, sysdb->domain->names->fq_fmt,
+ name, sysdb->domain->name);
+ if (!src_name) return ENOMEM;
+ }
+
+ ret = sysdb_getgrnam(mem_ctx, sysdb, src_name ? src_name : name, res);
+ talloc_zfree(src_name);
+
+ return ret;
+}
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 685c666a..f4ad8536 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -2188,6 +2188,17 @@ int be_process_init(TALLOC_CTX *mem_ctx,
goto fail;
}
+ /* We need this for subdomains support, as they have to store fully
+ * qualified user and group names for now */
+ ret = sss_names_init(ctx->domain, cdb,
+ ctx->domain->name, &ctx->domain->names);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("fatal error setting fully qualified name format for %s\n",
+ ctx->domain->name));
+ goto fail;
+ }
+
ret = be_srv_init(ctx);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, ("fatal error setting up server bus\n"));
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 1a81c860..8fc22819 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -591,6 +591,9 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */
const char *homedir = NULL;
struct sysdb_attrs *user_attrs = NULL;
+ char *name;
+ char *realm;
+ char *upn;
ret = ipa_s2n_exop_recv(subreq, state, &result, &retoid, &retdata);
talloc_zfree(subreq);
@@ -640,21 +643,64 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
- ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME_ALIAS,
- attrs->a.user.pw_name);
+ /* we always use the fully qualified name for subdomain users */
+ name = talloc_asprintf(state, state->dom->names->fq_fmt,
+ attrs->a.user.pw_name, state->dom->name);
+ if (!name) {
+ DEBUG(SSSDBG_OP_FAILURE, ("failed to format user name.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME_ALIAS, name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
+ goto done;
+ }
+
+ /* We also have to store a fake UPN here, because otherwise the
+ * krb5 child later won't be able to properly construct one as
+ * the username is fully qualified but the child doesn't have
+ * access to the regex to deconstruct it */
+ /* FIXME: The real UPN is available from the PAC, we should get
+ * it from there. */
+ realm = get_uppercase_realm(state, state->dom->name);
+ if (!realm) {
+ DEBUG(SSSDBG_OP_FAILURE, ("failed to get realm.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ upn = talloc_asprintf(state, "%s@%s",
+ attrs->a.user.pw_name, realm);
+ if (!upn) {
+ DEBUG(SSSDBG_OP_FAILURE, ("failed to format UPN.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
goto done;
}
- ret = sysdb_store_domuser(state->dom, attrs->a.user.pw_name, NULL,
+ ret = sysdb_store_domuser(state->dom, name, NULL,
attrs->a.user.pw_uid,
0, NULL, /* gecos */
homedir, NULL,
user_attrs, NULL, timeout, now);
break;
case RESP_GROUP:
- ret = sysdb_store_domgroup(state->dom, attrs->a.group.gr_name,
+ /* we always use the fully qualified name for subdomain users */
+ name = talloc_asprintf(state, state->dom->names->fq_fmt,
+ attrs->a.group.gr_name, state->dom->name);
+ if (!name) {
+ DEBUG(SSSDBG_OP_FAILURE, ("failed to format user name,\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_store_domgroup(state->dom, name,
attrs->a.group.gr_gid, NULL, timeout,
now);
break;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index a453e593..db1efdd2 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -635,7 +635,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
dctx->domain = dom;
talloc_free(name);
- name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
+ name = sss_get_cased_name(cmdctx, cmdctx->name, dom->case_sensitive);
if (!name) return ENOMEM;
/* verify this user has not yet been negatively cached,
@@ -666,7 +666,9 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
return EIO;
}
- ret = sysdb_getpwnam(cmdctx, sysdb, name, &dctx->res);
+ /* if this is a subdomain we need to search for the fully qualified
+ * name in the database */
+ ret = sysdb_subdom_getpwnam(cmdctx, sysdb, name, &dctx->res);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
return EIO;
@@ -2204,7 +2206,9 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
return EIO;
}
- ret = sysdb_getgrnam(cmdctx, sysdb, name, &dctx->res);
+ /* if this is a subdomain we need to search for the fully qualified
+ * name in the database */
+ ret = sysdb_subdom_getgrnam(cmdctx, sysdb, name, &dctx->res);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
return EIO;
diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c
index 5721d926..202765a5 100644
--- a/src/responder/pac/pacsrv_cmd.c
+++ b/src/responder/pac/pacsrv_cmd.c
@@ -53,6 +53,7 @@ struct pac_req_ctx {
struct pac_ctx *pac_ctx;
const char *domain_name;
const char *user_name;
+ char *fq_name;
struct sss_domain_info *dom;
struct PAC_LOGON_INFO *logon_info;
@@ -201,6 +202,16 @@ static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx)
struct dom_sid *my_dom_sid;
struct local_mapping_ranges *my_range_map;
+ /* this is a subdomain so we need to search for the fully qualified
+ * name in the database */
+ pr_ctx->fq_name = talloc_asprintf(pr_ctx, pr_ctx->dom->names->fq_fmt,
+ pr_ctx->user_name, pr_ctx->dom->name);
+ if (!pr_ctx->fq_name) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
+ goto done;
+ }
+
ret = save_pac_user(pr_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("save_pac_user failed.\n"));
@@ -365,7 +376,7 @@ static errno_t save_pac_user(struct pac_req_ctx *pr_ctx)
goto done;
}
- ret = sysdb_search_user_by_name(tmp_ctx, sysdb, pr_ctx->user_name, attrs,
+ ret = sysdb_search_user_by_name(tmp_ctx, sysdb, pr_ctx->fq_name, attrs,
&msg);
if (ret == EOK) {
/* TODO: check id uid and gid are equal. */
@@ -423,7 +434,7 @@ struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx)
}
state->gid_iter = 0;
- state->user_dn = sysdb_user_dn(dom->sysdb, state, pr_ctx->user_name);
+ state->user_dn = sysdb_user_dn(dom->sysdb, state, pr_ctx->fq_name);
if (state->user_dn == NULL) {
ret = ENOMEM;
goto done;
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index c9551c99..53113fb0 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -502,6 +502,7 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
struct sysdb_attrs *attrs = NULL;
struct netr_SamBaseInfo *base_info;
int ret;
+ char *lname;
char *uc_realm;
char *upn;
@@ -513,36 +514,41 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
base_info = &logon_info->info3.base;
- if (base_info->account_name.size != 0) {
- /* To be compatible with winbind based lookups we have to use lower
- * case names only, effectively making the domain case-insenvitive. */
- pwd->pw_name = sss_tc_utf8_str_tolower(pwd,
- base_info->account_name.string);
- if (pwd->pw_name == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_tc_utf8_str_tolower failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- } else {
+ if (base_info->account_name.size == 0) {
DEBUG(SSSDBG_OP_FAILURE, ("Missing account name in PAC.\n"));
ret = EINVAL;
goto done;
}
-
- if (base_info->rid > 0) {
- ret = domsid_rid_to_uid(pac_ctx, dom->sysdb, dom->name,
- base_info->domain_sid,
- base_info->rid, &pwd->pw_uid);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("domsid_rid_to_uid failed.\n"));
- goto done;
- }
- } else {
+ if (base_info->rid == 0) {
DEBUG(SSSDBG_OP_FAILURE, ("Missing user RID in PAC.\n"));
ret = EINVAL;
goto done;
}
+ /* To be compatible with winbind based lookups we have to use lower
+ * case names only, effectively making the domain case-insenvitive. */
+ lname = sss_tc_utf8_str_tolower(pwd, base_info->account_name.string);
+ if (lname == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_tc_utf8_str_tolower failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ pwd->pw_name = talloc_asprintf(pwd, dom->names->fq_fmt,
+ lname, dom->name);
+ if (!pwd->pw_name) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = domsid_rid_to_uid(pac_ctx, dom->sysdb, dom->name,
+ base_info->domain_sid,
+ base_info->rid, &pwd->pw_uid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("domsid_rid_to_uid failed.\n"));
+ goto done;
+ }
+
pwd->pw_gid = 0; /* We use MPGs for sub-domains */
if (base_info->full_name.size != 0) {
@@ -559,7 +565,7 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
if (dom->subdomain_homedir) {
pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir,
- pwd->pw_name, pwd->pw_uid,
+ lname, pwd->pw_uid,
dom->name);
if (pwd->pw_dir == NULL) {
ret = ENOMEM;
@@ -583,7 +589,7 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
goto done;
}
- upn = talloc_asprintf(mem_ctx, "%s@%s", pwd->pw_name, uc_realm);
+ upn = talloc_asprintf(mem_ctx, "%s@%s", lname, uc_realm);
talloc_free(uc_realm);
if (upn == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 1702a0e9..42696422 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1217,7 +1217,10 @@ static int pam_check_user_search(struct pam_auth_req *preq)
preq->pd->pam_status = PAM_SYSTEM_ERR;
return EFAULT;
}
- ret = sysdb_getpwnam(preq, sysdb, name, &preq->res);
+
+ /* if this is a subdomain we need to search for the fully qualified
+ * name in the database */
+ ret = sysdb_subdom_getpwnam(preq, sysdb, name, &preq->res);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
return EIO;
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 6ee35455..a6aa5c73 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -73,7 +73,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
}
dom->enumerate = false;
- dom->fqnames = true;
+ dom->fqnames = false;
/* FIXME: get ranges from the server */
dom->id_min = 0;
dom->id_max = 0xffffffff;