diff options
-rw-r--r-- | source3/auth/auth_util.c | 26 | ||||
-rw-r--r-- | source3/passdb/lookup_sid.c | 103 | ||||
-rw-r--r-- | source3/passdb/lookup_sid.h | 3 |
3 files changed, 126 insertions, 6 deletions
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 1cc78f0757..b7ec9fff70 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -447,10 +447,12 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, DATA_BLOB *session_key, struct auth_serversupplied_info **session_info_out) { + struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct auth_serversupplied_info *session_info; + struct wbcUnixId *ids; /* Ensure we can't possible take a code path leading to a * null defref. */ @@ -516,18 +518,30 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, session_info->utok.ngroups = 0; session_info->utok.groups = NULL; + t = session_info->security_token; + + ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, + t->num_sids); + if (ids == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) { + TALLOC_FREE(ids); + return NT_STATUS_NO_MEMORY; + } + /* Start at index 1, where the groups start. */ - for (i=1; i<session_info->security_token->num_sids; i++) { - gid_t gid; - struct dom_sid *sid = &session_info->security_token->sids[i]; + for (i=1; i<t->num_sids; i++) { - if (!sid_to_gid(sid, &gid)) { + if (ids[i].type != WBC_ID_TYPE_GID) { DEBUG(10, ("Could not convert SID %s to gid, " - "ignoring it\n", sid_string_dbg(sid))); + "ignoring it\n", + sid_string_dbg(&t->sids[i]))); continue; } - if (!add_gid_to_array_unique(session_info, gid, + if (!add_gid_to_array_unique(session_info, ids[i].id.gid, &session_info->utok.groups, &session_info->utok.ngroups)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 677566187c..5cf391f11c 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1395,6 +1395,109 @@ void gid_to_sid(struct dom_sid *psid, gid_t gid) return; } +bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids, + struct wbcUnixId *ids) +{ + struct wbcDomainSid *wbc_sids = NULL; + struct wbcUnixId *wbc_ids = NULL; + uint32_t i, num_not_cached; + wbcErr err; + bool ret = false; + + wbc_sids = TALLOC_ARRAY(talloc_tos(), struct wbcDomainSid, num_sids); + if (wbc_sids == NULL) { + return false; + } + + num_not_cached = 0; + + for (i=0; i<num_sids; i++) { + bool expired; + uint32_t rid; + + if (fetch_uid_from_cache(&ids[i].id.uid, &sids[i])) { + ids[i].type = WBC_ID_TYPE_UID; + continue; + } + if (fetch_gid_from_cache(&ids[i].id.gid, &sids[i])) { + ids[i].type = WBC_ID_TYPE_GID; + continue; + } + if (sid_peek_check_rid(&global_sid_Unix_Users, + &sids[i], &rid)) { + ids[i].type = WBC_ID_TYPE_UID; + ids[i].id.uid = rid; + continue; + } + if (sid_peek_check_rid(&global_sid_Unix_Groups, + &sids[i], &rid)) { + ids[i].type = WBC_ID_TYPE_GID; + ids[i].id.gid = rid; + continue; + } + if (idmap_cache_find_sid2uid(&sids[i], &ids[i].id.uid, + &expired) + && !expired) { + ids[i].type = WBC_ID_TYPE_UID; + continue; + } + if (idmap_cache_find_sid2gid(&sids[i], &ids[i].id.gid, + &expired) + && !expired) { + ids[i].type = WBC_ID_TYPE_GID; + continue; + } + ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED; + memcpy(&wbc_sids[num_not_cached], &sids[i], + ndr_size_dom_sid(&sids[i], 0)); + num_not_cached += 1; + } + if (num_not_cached == 0) { + goto done; + } + wbc_ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, num_not_cached); + if (wbc_ids == NULL) { + goto fail; + } + for (i=0; i<num_not_cached; i++) { + wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED; + } + err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids); + if (!WBC_ERROR_IS_OK(err)) { + DEBUG(10, ("wbcSidsToUnixIds returned %s\n", + wbcErrorString(err))); + } + + num_not_cached = 0; + + for (i=0; i<num_sids; i++) { + if (ids[i].type == WBC_ID_TYPE_NOT_SPECIFIED) { + ids[i] = wbc_ids[num_not_cached]; + num_not_cached += 1; + } + } + + for (i=0; i<num_sids; i++) { + if (ids[i].type != WBC_ID_TYPE_NOT_SPECIFIED) { + continue; + } + if (legacy_sid_to_gid(&sids[i], &ids[i].id.gid)) { + ids[i].type = WBC_ID_TYPE_GID; + continue; + } + if (legacy_sid_to_uid(&sids[i], &ids[i].id.uid)) { + ids[i].type = WBC_ID_TYPE_UID; + continue; + } + } +done: + ret = true; +fail: + TALLOC_FREE(wbc_ids); + TALLOC_FREE(wbc_sids); + return ret; +} + /***************************************************************** *THE CANONICAL* convert SID to uid function. *****************************************************************/ diff --git a/source3/passdb/lookup_sid.h b/source3/passdb/lookup_sid.h index 3c3d278c2a..b56aaba039 100644 --- a/source3/passdb/lookup_sid.h +++ b/source3/passdb/lookup_sid.h @@ -24,6 +24,7 @@ #define _PASSDB_LOOKUP_SID_H_ #include "../librpc/gen_ndr/lsa.h" +#include "../nsswitch/libwbclient/wbclient.h" #define LOOKUP_NAME_NONE 0x00000000 #define LOOKUP_NAME_ISOLATED 0x00000001 /* Look up unqualified names */ @@ -84,6 +85,8 @@ void uid_to_sid(struct dom_sid *psid, uid_t uid); void gid_to_sid(struct dom_sid *psid, gid_t gid); bool sid_to_uid(const struct dom_sid *psid, uid_t *puid); bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid); +bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids, + struct wbcUnixId *ids); NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx, const char *username, struct passwd **_pwd, |