diff options
Diffstat (limited to 'src/responder/pac/pacsrv_cmd.c')
-rw-r--r-- | src/responder/pac/pacsrv_cmd.c | 649 |
1 files changed, 474 insertions, 175 deletions
diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c index 3f2420273..f4fec85f8 100644 --- a/src/responder/pac/pacsrv_cmd.c +++ b/src/responder/pac/pacsrv_cmd.c @@ -19,18 +19,18 @@ 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 <stdbool.h> +#include <util/data_blob.h> +#include <ndr.h> +#include <gen_ndr/krb5pac.h> +#include <gen_ndr/ndr_krb5pac.h> #include "util/util.h" +#include "util/sss_nss.h" #include "responder/pac/pacsrv.h" #include "confdb/confdb.h" #include "db/sysdb.h" -#include <util/data_blob.h> -#include <ndr.h> - -#include "gen_ndr/krb5pac.h" -#include "gen_ndr/ndr_krb5pac.h" - #define PAC_USER_OFFSET 200000 #define PAC_HOME_PATH "/home/" #define PAC_DEFAULT_SHELL "/bin/bash" @@ -59,39 +59,301 @@ static errno_t pac_cmd_done(struct cli_ctx *cctx, int cmd_ret) return EOK; } -static errno_t domsid_rid_to_uid(struct dom_sid2 *domsid, uint32_t rid, - uid_t *uid) +static void *idmap_talloc(size_t size, void *pvt) { - /* Replace with a proper mapping */ - *uid = (uid_t) rid + PAC_USER_OFFSET; - return EOK; + return talloc_size(pvt, size); +} + +static void idmap_free(void *ptr, void *pvt) +{ + talloc_free(ptr); } -static errno_t domsid_rid_to_gid(struct dom_sid2 *domsid, uint32_t rid, - gid_t *gid) +static errno_t add_idmap_domain(struct sss_idmap_ctx *idmap_ctx, + struct sysdb_ctx *sysdb, + const char *domain_name, + const char *dom_sid_str) { - /* Replace with a proper mapping */ - *gid = (gid_t) rid + PAC_USER_OFFSET; + struct sss_idmap_range range; + enum idmap_error_code err; + + /* TODO: read range form sysdb if + * https://fedorahosted.org/freeipa/ticket/2185 is fixed */ + range.min = 200000; + range.max = 400000; + + err = sss_idmap_add_domain(idmap_ctx, domain_name, dom_sid_str, &range); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_add_domain failed.\n")); + return EFAULT; + } + return EOK; } +static errno_t domsid_rid_to_uid(struct pac_ctx *pac_ctx, + struct sysdb_ctx *sysdb, + const char *domain_name, + struct dom_sid2 *domsid, uint32_t rid, + uid_t *uid) +{ + enum idmap_error_code err; + char *sid_str = NULL; + char *dom_sid_str = NULL; + uint32_t id; + int ret; + + if (pac_ctx->idmap_ctx == NULL) { + err = sss_idmap_init(idmap_talloc, pac_ctx, idmap_free, + &pac_ctx->idmap_ctx); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_init failed.\n")); + return EFAULT; + } + } + + err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domsid, + &dom_sid_str); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n")); + ret = EFAULT; + goto done; + } + + sid_str = talloc_asprintf(NULL, "%s-%lu", dom_sid_str, (unsigned long) rid); + if (sid_str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("dom_sid_and_rid_string failed.\n")); + return ENOMEM; + } + + err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domsid, &sid_str); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n")); + ret = EFAULT; + goto done; + } + + err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id); + if (err == IDMAP_NO_DOMAIN) { + ret = add_idmap_domain(pac_ctx->idmap_ctx, sysdb, domain_name, + dom_sid_str); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("add_idmap_domain failed.\n")); + goto done; + } + + err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_sid_to_unix failed " + "even in the second attempt.\n")); + ret = ENOENT; + goto done; + } + } else if (err != IDMAP_SUCCESS && err != IDMAP_NO_DOMAIN) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_unix failed.\n")); + ret = EFAULT; + goto done; + } + + *uid = (uid_t) id; + + ret = EOK; + +done: + talloc_free(dom_sid_str); + talloc_free(sid_str); + return ret; +} + +static errno_t get_my_domain_sid(struct pac_ctx *pac_ctx, + struct sss_domain_info *dom, + struct dom_sid **_sid) +{ + struct sysdb_ctx *sysdb; + int ret; + struct ldb_dn *basedn; + const char *attrs[] = {SYSDB_SUBDOMAIN_ID, + NULL}; + size_t msgs_count; + const char *sid_str; + struct ldb_message **msgs; + TALLOC_CTX *tmp_ctx = NULL; + struct dom_sid *sid = NULL; + char *dom_name; + enum idmap_error_code err; + + if (pac_ctx->my_dom_sid == NULL) { + if (dom->parent != NULL) { + sysdb = dom->parent->sysdb; + dom_name = dom->parent->name; + } else { + sysdb = dom->sysdb; + dom_name = dom->name; + } + + if (sysdb == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Missing sysdb context.\n")); + ret = EINVAL; + goto done; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n")); + ret = ENOMEM; + goto done; + } + + basedn = sysdb_domain_dn(sysdb, tmp_ctx, dom_name); + if (basedn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL, + attrs, &msgs_count, &msgs); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + if (msgs_count != 1) { + DEBUG(SSSDBG_OP_FAILURE, ("Base search returned [%d] results, " + "expected 1.\n", msgs_count)); + ret = EINVAL; + goto done; + } + + sid_str = ldb_msg_find_attr_as_string(msgs[0], SYSDB_SUBDOMAIN_ID, NULL); + if (sid_str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("SID of my domain is not available.\n")); + ret = EINVAL; + goto done; + } + + err = sss_idmap_sid_to_smb_sid(pac_ctx->idmap_ctx, sid_str, &sid); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_smb_sid failed.\n")); + ret = EFAULT; + goto done; + } + + pac_ctx->my_dom_sid = talloc_memdup(pac_ctx, sid, + sizeof(struct dom_sid)); + if (pac_ctx->my_dom_sid == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_memdup failed.\n")); + ret = ENOMEM; + goto done; + } + } + + *_sid = pac_ctx->my_dom_sid; + + ret = EOK; + +done: + talloc_free(sid); + talloc_free(tmp_ctx); + + return ret; +} + +static bool dom_sid_in_domain(const struct dom_sid *domain_sid, + const struct dom_sid *sid) +{ + size_t c; + + if (!domain_sid || !sid) { + return false; + } + + if (domain_sid->sid_rev_num != sid->sid_rev_num) { + return false; + } + + for (c = 0; c < 6; c++) { + if (domain_sid->id_auth[c] != sid->id_auth[c]) { + return false; + } + } + + if (domain_sid->num_auths > sid->num_auths) { + return false; + } + + for (c = 0; c < domain_sid->num_auths-1; c++) { + if (domain_sid->sub_auths[c] != sid->sub_auths[c]) { + return false; + } + } + + return true; +} + +static errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx, + struct local_mapping_ranges *range_map, + struct dom_sid *domain_sid, + struct PAC_LOGON_INFO *logon_info, + size_t *_gid_count, gid_t **_gids) +{ + int ret; + size_t g; + size_t s; + struct netr_SamInfo3 *info3; + gid_t *gids = NULL; + + info3 = &logon_info->info3; + + g = 0; + if (info3->sidcount == 0) { + DEBUG(SSSDBG_TRACE_ALL, ("No extra groups found.\n")); + ret = EOK; + goto done; + } + + gids = talloc_array(mem_ctx, gid_t, info3->sidcount); + if (gids == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n")); + ret = ENOMEM; + goto done; + } + + for(s = 0; s < info3->sidcount; s++) { + if (dom_sid_in_domain(domain_sid, info3->sids[s].sid)) { + ret = local_sid_to_id(range_map, info3->sids[s].sid, &gids[g]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("get_rid failed.\n")); + goto done; + } + DEBUG(SSSDBG_TRACE_ALL, ("Found extra group " + "with gid [%d].\n", gids[g])); + g++; + } + } + + ret = EOK; + +done: + if (ret == EOK) { + *_gid_count = g; + *_gids = gids; + } else { + talloc_free(gids); + } + + return ret; +} + static errno_t get_data_from_pac(TALLOC_CTX *mem_ctx, - uint8_t *pac_blob, size_t pac_len, - struct passwd **_pwd, char **domain, - struct dom_sid2 **domain_sid, - int *_rid_count, uint32_t **_rids) + uint8_t *pac_blob, size_t pac_len, + struct PAC_LOGON_INFO **_logon_info) { DATA_BLOB blob; struct ndr_pull *ndr_pull; struct PAC_DATA *pac_data; enum ndr_err_code ndr_err; - struct passwd *pwd = NULL; size_t c; - struct netr_SamBaseInfo *base_info; int ret; - int i, j; - uint32_t *rids; - uint32_t attrs; blob.data = pac_blob; blob.length = pac_len; @@ -106,7 +368,6 @@ static errno_t get_data_from_pac(TALLOC_CTX *mem_ctx, pac_data = talloc_zero(mem_ctx, struct PAC_DATA); if (pac_data == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); - return EOK; return ENOMEM; } @@ -116,146 +377,126 @@ static errno_t get_data_from_pac(TALLOC_CTX *mem_ctx, return EBADMSG; } - pwd = talloc_zero(mem_ctx, struct passwd); - if (pwd == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); - return ENOMEM; - } - for(c = 0; c < pac_data->num_buffers; c++) { if (pac_data->buffers[c].type == PAC_TYPE_LOGON_INFO) { - base_info = &pac_data->buffers[c].info->logon_info.info->info3.base; - - if (base_info->account_name.size != 0) { - pwd->pw_name = talloc_strdup(pwd, - base_info->account_name.string); - if (pwd->pw_name == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } - } else { - DEBUG(SSSDBG_OP_FAILURE, ("Missing account name in PAC.\n")); - ret = EINVAL; - goto done; - } + *_logon_info = pac_data->buffers[c].info->logon_info.info; - if (base_info->rid > 0) { - ret = domsid_rid_to_uid(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 { - DEBUG(SSSDBG_OP_FAILURE, ("Missing user RID in PAC.\n")); - ret = EINVAL; - goto done; - } + return EOK; + } + } - if (base_info->primary_gid > 0) { - ret = domsid_rid_to_gid(base_info->domain_sid, - base_info->primary_gid, - &pwd->pw_gid); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("domsid_rid_to_gid failed.\n")); - goto done; - } - } else { - DEBUG(SSSDBG_OP_FAILURE, ("Missing primary GID in PAC.\n")); - ret = EINVAL; - goto done; - } + ret = EINVAL; - if (base_info->full_name.size != 0) { - pwd->pw_gecos = talloc_strdup(pwd, base_info->full_name.string); - } else { - DEBUG(SSSDBG_OP_FAILURE, ("Missing full name in PAC " - "using account name for gecos.\n")); - pwd->pw_gecos = talloc_strdup(pwd, - base_info->account_name.string); - } - if (pwd->pw_gecos == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } + talloc_free(pac_data); + return ret; +} - pwd->pw_dir = talloc_asprintf(mem_ctx, PAC_HOME_PATH"%s", - base_info->account_name.string); - if (pwd->pw_dir == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n")); - ret = ENOMEM; - goto done; - } +static errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx, + struct pac_ctx *pac_ctx, + struct sss_domain_info *dom, + struct PAC_LOGON_INFO *logon_info, + struct passwd **_pwd) +{ + struct passwd *pwd = NULL; + struct netr_SamBaseInfo *base_info; + int ret; - pwd->pw_shell = talloc_strdup(pwd, PAC_DEFAULT_SHELL); - if (pwd->pw_shell == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } + pwd = talloc_zero(mem_ctx, struct passwd); + if (pwd == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); + return ENOMEM; + } - *domain = talloc_strdup(mem_ctx, base_info->logon_domain.string); - if (*domain == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } + base_info = &logon_info->info3.base; - *_pwd = pwd; + if (base_info->account_name.size != 0) { + pwd->pw_name = talloc_strdup(pwd, + base_info->account_name.string); + if (pwd->pw_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + } else { + DEBUG(SSSDBG_OP_FAILURE, ("Missing account name in PAC.\n")); + ret = EINVAL; + goto done; + } - rids = talloc_array(mem_ctx, uint32_t, base_info->groups.count); - if (rids == NULL) { - ret = ENOMEM; - 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 { + DEBUG(SSSDBG_OP_FAILURE, ("Missing user RID in PAC.\n")); + ret = EINVAL; + goto done; + } - j = 0; - for (i = 0; i < base_info->groups.count; i++) { - attrs = base_info->groups.rids[i].attributes; - if (((attrs & SE_GROUP_ENABLED) != 0 || - (attrs & SE_GROUP_MANDATORY) != 0) && - (attrs & SE_GROUP_RESOURCE) == 0) { - rids[j] = base_info->groups.rids[i].rid; - j++; - } - } + pwd->pw_gid = 0; /* We use MPGs for sub-domains */ + + if (base_info->full_name.size != 0) { + pwd->pw_gecos = talloc_strdup(pwd, base_info->full_name.string); + } else { + DEBUG(SSSDBG_OP_FAILURE, ("Missing full name in PAC " + "using account name for gecos.\n")); + pwd->pw_gecos = talloc_strdup(pwd, + base_info->account_name.string); + } + if (pwd->pw_gecos == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } - *_rids = rids; - *_rid_count = j; - return EOK; + if (dom->subdomain_homedir) { + pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir, + pwd->pw_name, pwd->pw_uid, + dom->name); + if (pwd->pw_dir == NULL) { + ret = ENOMEM; + goto done; } } - ret = EINVAL; + pwd->pw_shell = NULL; /* Using default */ done: - talloc_free(pwd); + if (ret != EOK) { + talloc_free(pwd); + } + return ret; } struct pac_req_ctx { struct cli_ctx *cctx; - struct passwd *pwd; - char *domain_name; + struct pac_ctx *pac_ctx; + const char *domain_name; + const char *user_name; struct sss_domain_info *dom; - int rid_count; - uint32_t *rids; + struct PAC_LOGON_INFO *logon_info; struct dom_sid2 *domain_sid; + + size_t gid_count; + gid_t *gids; }; +static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx); static void pac_get_domains_done(struct tevent_req *req); -errno_t save_pac_user(struct pac_req_ctx *pr_ctx); +static errno_t save_pac_user(struct pac_req_ctx *pr_ctx); static void pac_get_group_done(struct tevent_req *subreq); static errno_t pac_save_memberships_next(struct tevent_req *req); static errno_t pac_store_memberships(struct pac_req_ctx *pr_ctx, struct sysdb_ctx *group_sysdb, struct ldb_dn *user_dn, - int rid_iter); + int gid_iter); struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx); static void pac_save_memberships_done(struct tevent_req *req); @@ -278,20 +519,34 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx) pr_ctx->cctx = cctx; + pr_ctx->pac_ctx = talloc_get_type(cctx->rctx->pvt_ctx, struct pac_ctx); + if (pr_ctx->pac_ctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Cannot find pac responder context.\n")); + return EINVAL; + } + ret = get_data_from_pac(pr_ctx, body, blen, - &pr_ctx->pwd, &pr_ctx->domain_name, - &pr_ctx->domain_sid, - &pr_ctx->rid_count, &pr_ctx->rids); + &pr_ctx->logon_info); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("get_pwd_from_pac failed.\n")); + DEBUG(SSSDBG_OP_FAILURE, ("get_data_from_pac failed.\n")); goto done; } + + pr_ctx->domain_name = pr_ctx->logon_info->info3.base.logon_domain.string; if (pr_ctx->domain_name == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, ("No domain name in PAC")); ret = EINVAL; goto done; } + pr_ctx->user_name = pr_ctx->logon_info->info3.base.account_name.string; + if (pr_ctx->user_name == NULL) { + ret = EINVAL; + DEBUG(SSSDBG_FATAL_FAILURE, ("Missing account name in PAC.\n")); + goto done; + } + + pr_ctx->dom = responder_get_domain(pr_ctx, cctx->rctx, pr_ctx->domain_name); if (pr_ctx->dom == NULL) { req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, @@ -305,23 +560,7 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx) goto done; } - ret = save_pac_user(pr_ctx); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("save_pac_user failed.\n")); - goto done; - } - - - req = pac_save_memberships_send(pr_ctx); - if (req == NULL) { - ret = ENOMEM; - goto done; - } - - tevent_req_set_callback(req, pac_save_memberships_done, pr_ctx); - - - ret = EAGAIN; + ret = pac_add_user_next(pr_ctx); done: return pac_cmd_done(cctx, ret); @@ -346,12 +585,38 @@ static void pac_get_domains_done(struct tevent_req *req) goto done; } + ret = pac_add_user_next(pr_ctx); + +done: + pac_cmd_done(cctx, ret); +} + +static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx) +{ + int ret; + struct tevent_req *req; + struct dom_sid *my_dom_sid; + ret = save_pac_user(pr_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("save_pac_user failed.\n")); goto done; } + ret = get_my_domain_sid(pr_ctx->pac_ctx, pr_ctx->dom, &my_dom_sid); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("get_my_domain_sid failed.\n")); + goto done; + } + + ret = get_gids_from_pac(pr_ctx, pr_ctx->pac_ctx->range_map, my_dom_sid, + pr_ctx->logon_info, &pr_ctx->gid_count, + &pr_ctx->gids); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("get_gids_from_pac failed.\n")); + goto done; + } + req = pac_save_memberships_send(pr_ctx); if (req == NULL) { ret = ENOMEM; @@ -360,18 +625,20 @@ static void pac_get_domains_done(struct tevent_req *req) tevent_req_set_callback(req, pac_save_memberships_done, pr_ctx); - return; + ret = EAGAIN; done: - pac_cmd_done(cctx, ret); + return ret; } -errno_t save_pac_user(struct pac_req_ctx *pr_ctx) +static errno_t save_pac_user(struct pac_req_ctx *pr_ctx) { struct sysdb_ctx *sysdb; - struct passwd *pwd = pr_ctx->pwd; - struct cli_ctx *cctx = pr_ctx->cctx; int ret; + const char *attrs[] = {SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM, NULL}; + struct ldb_message *msg; + struct passwd *pwd = NULL; + TALLOC_CTX *tmp_ctx = NULL; sysdb = pr_ctx->dom->sysdb; if (sysdb == NULL) { @@ -380,21 +647,49 @@ errno_t save_pac_user(struct pac_req_ctx *pr_ctx) goto done; } - ret = sysdb_store_user(sysdb, pwd->pw_name, NULL, - pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, - pwd->pw_shell, NULL, NULL, 3600, 0); /* FIXME: cache_timeout */ - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_store_user failed [%d][%s].\n", - ret, strerror(ret))); + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n")); + goto done; + } + + ret = sysdb_search_user_by_name(tmp_ctx, sysdb, pr_ctx->user_name, attrs, + &msg); + if (ret == EOK) { + /* TODO: check id uid and gid are equal. */ + } else if (ret == ENOENT) { + ret = get_pwd_from_pac(tmp_ctx, pr_ctx->pac_ctx, pr_ctx->dom, + pr_ctx->logon_info, &pwd); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("get_pwd_from_pac failed.\n")); + goto done; + } + + ret = sysdb_store_user(sysdb, pwd->pw_name, NULL, + pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell, NULL, NULL, + 3600, 0); /* FIXME: cache_timeout */ + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_store_user failed [%d][%s].\n", + ret, strerror(ret))); + goto done; + } + } else { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_search_user_by_name failed.\n")); goto done; } + ret = EOK; + done: - return pac_cmd_done(cctx, ret); + talloc_free(tmp_ctx); + return ret; } struct pac_save_memberships_state { - int rid_iter; + int gid_iter; struct ldb_dn *user_dn; struct pac_req_ctx *pr_ctx; @@ -413,9 +708,9 @@ struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx) return NULL; } - state->rid_iter = 0; + state->gid_iter = 0; state->user_dn = sysdb_user_dn(dom->sysdb, state, dom->name, - pr_ctx->pwd->pw_name); + pr_ctx->user_name); if (state->user_dn == NULL) { ret = ENOMEM; goto done; @@ -430,6 +725,10 @@ struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx) } ret = pac_save_memberships_next(req); + if (ret == EOK) { + tevent_req_done(req); + tevent_req_post(req, pr_ctx->cctx->ev); + } done: if (ret != EOK && ret != EAGAIN) { @@ -452,18 +751,18 @@ errno_t pac_save_memberships_next(struct tevent_req *req) state = tevent_req_data(req, struct pac_save_memberships_state); pr_ctx = state->pr_ctx; - while (state->rid_iter < pr_ctx->rid_count) { - gid = pr_ctx->rids[state->rid_iter]; + while (state->gid_iter < pr_ctx->gid_count) { + gid = pr_ctx->gids[state->gid_iter]; ret = sysdb_search_group_by_gid(pr_ctx, state->group_dom->sysdb, gid, NULL, &group); if (ret == EOK) { ret = pac_store_memberships(state->pr_ctx, state->group_dom->sysdb, - state->user_dn, state->rid_iter); + state->user_dn, state->gid_iter); if (ret != EOK) { goto done; } - state->rid_iter++; + state->gid_iter++; continue; } else if (ret != ENOENT) { goto done; @@ -510,11 +809,11 @@ static void pac_get_group_done(struct tevent_req *subreq) } ret = pac_store_memberships(state->pr_ctx, state->group_dom->sysdb, - state->user_dn, state->rid_iter); + state->user_dn, state->gid_iter); if (ret != EOK) { goto error; } - state->rid_iter++; + state->gid_iter++; ret = pac_save_memberships_next(req); if (ret == EOK) { @@ -533,7 +832,7 @@ static errno_t pac_store_memberships(struct pac_req_ctx *pr_ctx, struct sysdb_ctx *group_sysdb, struct ldb_dn *user_dn, - int rid_iter) + int gid_iter) { TALLOC_CTX *tmp_ctx; const char *group_name; @@ -547,7 +846,7 @@ pac_store_memberships(struct pac_req_ctx *pr_ctx, return ENOMEM; } - gid = pr_ctx->rids[rid_iter]; + gid = pr_ctx->gids[gid_iter]; ret = sysdb_search_group_by_gid(tmp_ctx, group_sysdb, gid, NULL, &group); |