summaryrefslogtreecommitdiffstats
path: root/src/responder/pac/pacsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/pac/pacsrv_cmd.c')
-rw-r--r--src/responder/pac/pacsrv_cmd.c649
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);