diff options
author | Simo Sorce <ssorce@redhat.com> | 2010-05-29 10:51:40 -0400 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2010-06-07 22:53:08 +1000 |
commit | 0a7ff146171abd2dee4aac44e4f2c6c812f1027e (patch) | |
tree | 09e1c1bc5cd5fd55ff1b00ae0a5a3e90453193b2 /source3 | |
parent | aaf45cd48ecf8e9f640a6f487b66785d47b8154a (diff) | |
download | samba-0a7ff146171abd2dee4aac44e4f2c6c812f1027e.tar.gz samba-0a7ff146171abd2dee4aac44e4f2c6c812f1027e.tar.bz2 samba-0a7ff146171abd2dee4aac44e4f2c6c812f1027e.zip |
s3:passdb Export function to calculate the proper primary group sid
Don't keep it buried in passdb, this function need to be available
for use in places where we do not want to construct an artificial
samu struct just to play tricks.
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/passdb/lookup_sid.c | 124 | ||||
-rw-r--r-- | source3/passdb/pdb_get_set.c | 94 |
3 files changed, 136 insertions, 86 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 393e7e277c..dc6b555fd2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4351,6 +4351,10 @@ 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); +NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx, + const char *username, + struct passwd **_pwd, + struct dom_sid **_group_sid); /* The following definitions come from passdb/machine_sid.c */ diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 14494cbeec..d523055b9d 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1514,3 +1514,127 @@ bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid) store_gid_sid_cache(psid, *pgid); return true; } + +/** + * @brief This function gets the primary group SID mapping the primary + * GID of the user as obtained by an actual getpwnam() call. + * This is necessary to avoid issues with arbitrary group SIDs + * stored in passdb. We try as hard as we can to get the SID + * corresponding to the GID, including trying group mapping. + * If nothing else works, we will force "Domain Users" as the + * primary group. + * This is needed because we must always be able to lookup the + * primary group SID, so we cannot settle for an arbitrary SID. + * + * This call can be expensive. Use with moderation. + * If you have a "samu" struct around use pdb_get_group_sid() + * instead as it does properly cache results. + * + * @param mem_ctx[in] The memory context iused to allocate the result. + * @param username[in] The user's name + * @param _pwd[in|out] If available, pass in user's passwd struct. + * It will contain a tallocated passwd if NULL was + * passed in. + * @param _group_sid[out] The user's Primary Group SID + * + * @return NTSTATUS error code. + */ +NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx, + const char *username, + struct passwd **_pwd, + struct dom_sid **_group_sid) +{ + TALLOC_CTX *tmp_ctx; + bool need_lookup_sid = false; + struct dom_sid *group_sid; + struct passwd *pwd = *_pwd; + + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + + if (!pwd) { + pwd = Get_Pwnam_alloc(mem_ctx, username); + if (!pwd) { + DEBUG(0, ("Failed to find a Unix account for %s", + username)); + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_SUCH_USER; + } + } + + group_sid = talloc_zero(mem_ctx, struct dom_sid); + if (!group_sid) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + gid_to_sid(group_sid, pwd->pw_gid); + if (!is_null_sid(group_sid)) { + struct dom_sid domain_sid; + uint32_t rid; + + /* We need a sid within our domain */ + sid_copy(&domain_sid, group_sid); + sid_split_rid(&domain_sid, &rid); + if (sid_equal(&domain_sid, get_global_sam_sid())) { + /* + * As shortcut for the expensive lookup_sid call + * compare the domain sid part + */ + switch (rid) { + case DOMAIN_RID_ADMINS: + case DOMAIN_RID_USERS: + goto done; + default: + need_lookup_sid = true; + break; + } + } else { + /* Try group mapping */ + ZERO_STRUCTP(group_sid); + if (pdb_gid_to_sid(pwd->pw_gid, group_sid)) { + need_lookup_sid = true; + } + } + } + + /* We must verify that this is a valid SID that resolves to a + * group of the correct type */ + if (need_lookup_sid) { + enum lsa_SidType type = SID_NAME_UNKNOWN; + bool lookup_ret; + + DEBUG(10, ("do lookup_sid(%s) for group of user %s\n", + sid_string_dbg(group_sid), username)); + + /* Now check that it's actually a domain group and + * not something else */ + lookup_ret = lookup_sid(tmp_ctx, group_sid, + NULL, NULL, &type); + + if (lookup_ret && (type == SID_NAME_DOM_GRP)) { + goto done; + } + + DEBUG(3, ("Primary group %s for user %s is" + " a %s and not a domain group\n", + sid_string_dbg(group_sid), username, + sid_type_lookup(type))); + } + + /* Everything else, failed. + * Just set it to the 'Domain Users' RID of 513 which will + always resolve to a name */ + DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n", + username)); + + sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS); + +done: + *_pwd = talloc_move(mem_ctx, &pwd); + *_group_sid = talloc_move(mem_ctx, &group_sid); + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; +} diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 57d95138e3..3e2510e74c 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -182,105 +182,27 @@ const struct dom_sid *pdb_get_user_sid(const struct samu *sampass) const struct dom_sid *pdb_get_group_sid(struct samu *sampass) { - struct dom_sid *gsid; - struct passwd *pwd; - bool need_lookup_sid = false; + NTSTATUS status; /* Return the cached group SID if we have that */ - if ( sampass->group_sid ) { + if (sampass->group_sid) { return sampass->group_sid; } - /* generate the group SID from the user's primary Unix group */ - - if ( !(gsid = TALLOC_ZERO_P( sampass, struct dom_sid )) ) { - return NULL; - } - /* No algorithmic mapping, meaning that we have to figure out the primary group SID according to group mapping and the user SID must be a newly allocated one. We rely on the user's Unix primary gid. We have no choice but to fail if we can't find it. */ - - if ( sampass->unix_pw ) { - pwd = sampass->unix_pw; - } else { - pwd = Get_Pwnam_alloc( sampass, pdb_get_username(sampass) ); - sampass->unix_pw = pwd; - } - - if ( !pwd ) { - DEBUG(0,("pdb_get_group_sid: Failed to find Unix account for %s\n", pdb_get_username(sampass) )); + status = get_primary_group_sid(sampass, + pdb_get_username(sampass), + &sampass->unix_pw, + &sampass->group_sid); + if (!NT_STATUS_IS_OK(status)) { return NULL; } - gid_to_sid(gsid, pwd->pw_gid); - if (!is_null_sid(gsid)) { - struct dom_sid dgsid; - uint32_t rid; - - sid_copy(&dgsid, gsid); - sid_split_rid(&dgsid, &rid); - if (sid_equal(&dgsid, get_global_sam_sid())) { - /* - * As shortcut for the expensive lookup_sid call - * compare the domain sid part - */ - switch (rid) { - case DOMAIN_RID_ADMINS: - case DOMAIN_RID_USERS: - sampass->group_sid = gsid; - return sampass->group_sid; - default: - need_lookup_sid = true; - break; - } - } else { - ZERO_STRUCTP(gsid); - if (pdb_gid_to_sid(pwd->pw_gid, gsid)) { - need_lookup_sid = true; - } - } - } - - if (need_lookup_sid) { - enum lsa_SidType type = SID_NAME_UNKNOWN; - TALLOC_CTX *mem_ctx; - bool lookup_ret; - const struct dom_sid *usid = pdb_get_user_sid(sampass); - - mem_ctx = talloc_init("pdb_get_group_sid"); - if (!mem_ctx) { - return NULL; - } - - DEBUG(10,("do lookup_sid(%s) for group of user %s\n", - sid_string_dbg(gsid), sid_string_dbg(usid))); - - /* Now check that it's actually a domain group and not something else */ - - lookup_ret = lookup_sid(mem_ctx, gsid, NULL, NULL, &type); - - TALLOC_FREE( mem_ctx ); - - if ( lookup_ret && (type == SID_NAME_DOM_GRP) ) { - sampass->group_sid = gsid; - return sampass->group_sid; - } - - DEBUG(3, ("Primary group %s for user %s is a %s and not a domain group\n", - sid_string_dbg(gsid), pwd->pw_name, sid_type_lookup(type))); - } - - /* Just set it to the 'Domain Users' RID of 513 which will - always resolve to a name */ - - sid_compose(gsid, get_global_sam_sid(), DOMAIN_RID_USERS); - - sampass->group_sid = gsid; - return sampass->group_sid; -} +} /** * Get flags showing what is initalised in the struct samu |