diff options
author | Volker Lendecke <vlendec@samba.org> | 2005-12-03 18:34:13 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:05:43 -0500 |
commit | 05ac2de0df78d22ad5afb42ea5c72ba17bef8395 (patch) | |
tree | f4968eaab779b3f09dfac41e34f6088f32c38463 /source3/passdb/lookup_sid.c | |
parent | 678f13c761bea7b4dc4b96c4c1a7d65ee143181c (diff) | |
download | samba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.tar.gz samba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.tar.bz2 samba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.zip |
r12051: Merge across the lookup_name and lookup_sid work. Lets see how the build farm
reacts :-)
Volker
(This used to be commit 9f99d04a54588cd9d1a1ab163ebb304437f932f7)
Diffstat (limited to 'source3/passdb/lookup_sid.c')
-rw-r--r-- | source3/passdb/lookup_sid.c | 399 |
1 files changed, 307 insertions, 92 deletions
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index b397e084c3..bad5d278ae 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -22,43 +22,247 @@ #include "includes.h" /***************************************************************** - *THE CANONICAL* convert name to SID function. - Tries local lookup first - for local domains - then uses winbind. + Dissect a user-provided name into domain, name, sid and type. + + If an explicit domain name was given in the form domain\user, it + has to try that. If no explicit domain name was given, we have + to do guesswork. *****************************************************************/ -BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +BOOL lookup_name(TALLOC_CTX *mem_ctx, + const char *full_name, int flags, + char **ret_domain, char **ret_name, + DOM_SID *ret_sid, enum SID_NAME_USE *ret_type) { - fstring sid; - BOOL local_lookup = False; - - *name_type = SID_NAME_UNKNOWN; + char *p, *tmp; + char *domain = NULL; + char *name = NULL; + uint32 rid; + DOM_SID sid; + enum SID_NAME_USE type; + + p = strchr_m(full_name, '\\'); + + if (p != NULL) { + domain = talloc_strndup(mem_ctx, full_name, + PTR_DIFF(p, full_name)); + name = talloc_strdup(mem_ctx, p+1); + } else { + domain = talloc_strdup(mem_ctx, ""); + name = talloc_strdup(mem_ctx, full_name); + } + + if ((domain == NULL) || (name == NULL)) { + DEBUG(0, ("talloc failed\n")); + return False; + } - /* If we are looking up a domain user, make sure it is - for the local machine only */ - if (strequal(domain, get_global_sam_name())) { - if (local_lookup_name(name, psid, name_type)) { - DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", - domain, name, sid_to_string(sid,psid), - sid_type_lookup(*name_type), (unsigned int)*name_type)); - return True; + + /* It's our own domain, lookup the name in passdb */ + if (lookup_global_sam_name(name, &rid, &type)) { + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, rid); + goto ok; } - } else { - /* Remote */ - if (winbind_lookup_name(domain, name, psid, name_type)) { - - DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid, psid), - (unsigned int)*name_type)); - return True; + return False; + } + + if (strequal(domain, builtin_domain_name())) { + + /* Explicit request for a name in BUILTIN */ + if (lookup_builtin_name(name, &rid)) { + sid_copy(&sid, &global_sid_Builtin); + sid_append_rid(&sid, rid); + type = SID_NAME_ALIAS; + goto ok; } + return False; } - - DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", - local_lookup ? "local" : "winbind", domain, name)); + + if (domain[0] != '\0') { + /* An explicit domain name was given, here our last resort is + * winbind. */ + if (winbind_lookup_name(domain, name, &sid, &type)) { + goto ok; + } + return False; + } + + if (!(flags & LOOKUP_NAME_ISOLATED)) { + return False; + } + + /* Now the guesswork begins, we haven't been given an explicit + * domain. Try the sequence as documented on + * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp + * November 27, 2005 */ + + /* 1. well-known names */ + + { + tmp = domain; + if (lookup_wellknown_name(mem_ctx, name, &sid, &domain)) { + talloc_free(tmp); + type = SID_NAME_WKN_GRP; + goto ok; + } + } + + /* 2. Builtin domain as such */ + + if (strequal(name, builtin_domain_name())) { + /* Swap domain and name */ + tmp = name; name = domain; domain = tmp; + sid_copy(&sid, &global_sid_Builtin); + type = SID_NAME_DOMAIN; + goto ok; + } + + /* 3. Account domain */ + + if (strequal(name, get_global_sam_name())) { + if (!secrets_fetch_domain_sid(name, &sid)) { + DEBUG(3, ("Could not fetch my SID\n")); + return False; + } + /* Swap domain and name */ + tmp = name; name = domain; domain = tmp; + type = SID_NAME_DOMAIN; + goto ok; + } + + /* 4. Primary domain */ + + if (!IS_DC && strequal(name, lp_workgroup())) { + if (!secrets_fetch_domain_sid(name, &sid)) { + DEBUG(3, ("Could not fetch the domain SID\n")); + return False; + } + /* Swap domain and name */ + tmp = name; name = domain; domain = tmp; + type = SID_NAME_DOMAIN; + goto ok; + } + + /* 5. Trusted domains as such, to me it looks as if members don't do + this, tested an XP workstation in a NT domain -- vl */ + + if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL, + &sid, NULL))) { + /* Swap domain and name */ + tmp = name; name = domain; domain = tmp; + type = SID_NAME_DOMAIN; + goto ok; + } + + /* 6. Builtin aliases */ + + if (lookup_builtin_name(name, &rid)) { + domain = talloc_strdup(mem_ctx, builtin_domain_name()); + sid_copy(&sid, &global_sid_Builtin); + sid_append_rid(&sid, rid); + type = SID_NAME_ALIAS; + goto ok; + } + + /* 7. Local systems' SAM (DCs don't have a local SAM) */ + /* 8. Primary SAM (On members, this is the domain) */ + + /* Both cases are done by looking at our passdb */ + + if (lookup_global_sam_name(name, &rid, &type)) { + domain = talloc_strdup(mem_ctx, get_global_sam_name()); + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, rid); + goto ok; + } + + /* Now our local possibilities are exhausted. */ + + if (!(flags & LOOKUP_NAME_REMOTE)) { + return False; + } + + /* If we are not a DC, we have to ask in our primary domain. Let + * winbind do that. */ + + if (!IS_DC && + (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) { + domain = talloc_strdup(mem_ctx, lp_workgroup()); + goto ok; + } + + /* 9. Trusted domains */ + + /* If we're a DC we have to ask all trusted DC's. Winbind does not do + * that (yet), but give it a chance. */ + + if (IS_DC && winbind_lookup_name("", name, &sid, &type)) { + DOM_SID dom_sid; + uint32 tmp_rid; + enum SID_NAME_USE domain_type; + + if (type == SID_NAME_DOMAIN) { + /* Swap name and type */ + tmp = name; name = domain; domain = tmp; + goto ok; + } + + talloc_free(domain); + + /* Here we have to cope with a little deficiency in the + * winbind API: We have to ask it again for the name of the + * domain it figured out itself. Maybe fix that later... */ + + sid_copy(&dom_sid, &sid); + sid_split_rid(&dom_sid, &tmp_rid); + + if (!winbind_lookup_sid(mem_ctx, &dom_sid, &domain, NULL, + &domain_type) || + (domain_type != SID_NAME_DOMAIN)) { + DEBUG(2, ("winbind could not find the domain's name it " + "just looked up for us\n")); + return False; + } + + talloc_free(domain); + goto ok; + } + + /* 10. Don't translate */ return False; + + ok: + if ((domain == NULL) || (name == NULL)) { + DEBUG(0, ("talloc failed\n")); + return False; + } + + strupper_m(domain); + + if (ret_name != NULL) { + *ret_name = name; + } else { + talloc_free(name); + } + + if (ret_domain != NULL) { + *ret_domain = domain; + } else { + talloc_free(domain); + } + + if (ret_sid != NULL) { + sid_copy(ret_sid, &sid); + } + + if (ret_type != NULL) { + *ret_type = type; + } + + return True; } /***************************************************************** @@ -66,22 +270,21 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N Tries local lookup first - for local sids, then tries winbind. *****************************************************************/ -BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, - enum SID_NAME_USE *name_type) +BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **ret_domain, char **ret_name, + enum SID_NAME_USE *ret_type) { - if (!name_type) - return False; - - *name_type = SID_NAME_UNKNOWN; - + char *domain = NULL; + char *name = NULL; + enum SID_NAME_USE type; /* Check if this is our own sid. This should perhaps be done by winbind? For the moment handle it here. */ if (sid_check_is_domain(sid)) { - fstrcpy(dom_name, get_global_sam_name()); - fstrcpy(name, ""); - *name_type = SID_NAME_DOMAIN; - return True; + domain = talloc_strdup(mem_ctx, get_global_sam_name()); + name = talloc_strdup(mem_ctx, ""); + type = SID_NAME_DOMAIN; + goto ok; } if (sid_check_is_in_our_domain(sid)) { @@ -89,22 +292,22 @@ BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, SMB_ASSERT(sid_peek_rid(sid, &rid)); /* For our own domain passdb is responsible */ - fstrcpy(dom_name, get_global_sam_name()); - return lookup_global_sam_rid(rid, name, name_type); + if (!lookup_global_sam_rid(mem_ctx, rid, &name, &type)) { + return False; + } + + domain = talloc_strdup(mem_ctx, get_global_sam_name()); + goto ok; } if (sid_check_is_builtin(sid)) { - /* Got through map_domain_sid_to_name here so that the mapping - * of S-1-5-32 to the name "BUILTIN" in as few places as - * possible. We might add i18n... */ - SMB_ASSERT(map_domain_sid_to_name(sid, dom_name)); + domain = talloc_strdup(mem_ctx, builtin_domain_name()); /* Yes, W2k3 returns "BUILTIN" both as domain and name here */ - fstrcpy(name, dom_name); - - *name_type = SID_NAME_DOMAIN; - return True; + name = talloc_strdup(mem_ctx, builtin_domain_name()); + type = SID_NAME_DOMAIN; + goto ok; } if (sid_check_is_in_builtin(sid)) { @@ -112,39 +315,56 @@ BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, SMB_ASSERT(sid_peek_rid(sid, &rid)); - /* Got through map_domain_sid_to_name here so that the mapping - * of S-1-5-32 to the name "BUILTIN" in as few places as - * possible. We might add i18n... */ - SMB_ASSERT(map_domain_sid_to_name(&global_sid_Builtin, - dom_name)); + if (!lookup_builtin_rid(mem_ctx, rid, &name)) { + return False; + } /* There's only aliases in S-1-5-32 */ - *name_type = SID_NAME_ALIAS; + type = SID_NAME_ALIAS; + domain = talloc_strdup(mem_ctx, builtin_domain_name()); - return lookup_builtin_rid(rid, name); + goto ok; } - if (winbind_lookup_sid(sid, dom_name, name, name_type)) { - return True; + if (winbind_lookup_sid(mem_ctx, sid, &domain, &name, &type)) { + goto ok; } DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying " "special SIDs.\n", sid_string_static(sid))); - { - const char *dom, *obj_name; - - if (lookup_special_sid(sid, &dom, &obj_name, name_type)) { - DEBUG(10, ("found %s\\%s\n", dom, obj_name)); - fstrcpy(dom_name, dom); - fstrcpy(name, obj_name); - return True; - } + if (lookup_wellknown_sid(mem_ctx, sid, &domain, &name)) { + type = SID_NAME_WKN_GRP; + goto ok; } - DEBUG(10, ("lookup_sid failed\n")); - + DEBUG(10, ("Failed to lookup sid %s\n", sid_string_static(sid))); return False; + + ok: + + if ((domain == NULL) || (name == NULL)) { + DEBUG(0, ("talloc failed\n")); + return False; + } + + if (ret_domain != NULL) { + *ret_domain = domain; + } else { + talloc_free(domain); + } + + if (ret_name != NULL) { + *ret_name = name; + } else { + talloc_free(name); + } + + if (ret_type != NULL) { + *ret_type = type; + } + + return True; } /***************************************************************** @@ -187,10 +407,9 @@ static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) for (pc = uid_sid_cache_head; pc; pc = pc->next) { if (pc->uid == uid) { - fstring sid; *psid = pc->sid; DEBUG(3,("fetch sid from uid cache %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); + (unsigned int)uid, sid_string_static(psid))); DLIST_PROMOTE(uid_sid_cache_head, pc); return True; } @@ -208,10 +427,9 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) for (pc = uid_sid_cache_head; pc; pc = pc->next) { if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; *puid = pc->uid; DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*puid, sid_to_string(sid, psid))); + (unsigned int)*puid, sid_string_static(psid))); DLIST_PROMOTE(uid_sid_cache_head, pc); return True; } @@ -261,10 +479,9 @@ static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) for (pc = gid_sid_cache_head; pc; pc = pc->next) { if (pc->gid == gid) { - fstring sid; *psid = pc->sid; DEBUG(3,("fetch sid from gid cache %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); + (unsigned int)gid, sid_string_static(psid))); DLIST_PROMOTE(gid_sid_cache_head, pc); return True; } @@ -282,10 +499,9 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) for (pc = gid_sid_cache_head; pc; pc = pc->next) { if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; *pgid = pc->gid; DEBUG(3,("fetch gid from cache %u -> %s\n", - (unsigned int)*pgid, sid_to_string(sid, psid))); + (unsigned int)*pgid, sid_string_static(psid))); DLIST_PROMOTE(gid_sid_cache_head, pc); return True; } @@ -331,7 +547,6 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) { - fstring sid; uid_t low, high; ZERO_STRUCTP(psid); @@ -348,7 +563,7 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) if (winbind_uid_to_sid(psid, uid)) { DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); + (unsigned int)uid, sid_string_static(psid))); if (psid) store_uid_sid_cache(psid, uid); @@ -361,7 +576,8 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) return NT_STATUS_UNSUCCESSFUL; } - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, + sid_string_static(psid))); store_uid_sid_cache(psid, uid); return NT_STATUS_OK; @@ -373,7 +589,6 @@ NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) { - fstring sid; gid_t low, high; ZERO_STRUCTP(psid); @@ -390,7 +605,7 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) if (winbind_gid_to_sid(psid, gid)) { DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); + (unsigned int)gid, sid_string_static(psid))); if (psid) store_gid_sid_cache(psid, gid); @@ -403,7 +618,8 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) return NT_STATUS_UNSUCCESSFUL; } - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, + sid_string_static(psid))); store_gid_sid_cache(psid, gid); return NT_STATUS_OK; @@ -415,7 +631,6 @@ NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) { - fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; if (fetch_uid_from_cache(puid, psid)) @@ -437,7 +652,7 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) /* If it is not our local domain, only hope is winbindd */ - if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { + if ( !winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type) ) { DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", sid_string_static(psid) )); @@ -456,12 +671,12 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) if ( !winbind_sid_to_uid(puid, psid) ) { DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", - sid_to_string(sid_str, psid) )); + sid_string_static(psid))); return NT_STATUS_UNSUCCESSFUL; } success: - DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), + DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid), (unsigned int)*puid )); store_uid_sid_cache(psid, *puid); @@ -475,7 +690,6 @@ success: NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) { - fstring dom_name, name, sid_str; enum SID_NAME_USE name_type; if (fetch_gid_from_cache(pgid, psid)) @@ -489,8 +703,9 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) if ( local_sid_to_gid(pgid, psid, &name_type) ) goto success; - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then winbind)\n", sid_to_string(sid_str, psid))); + if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type)) { + DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then " + "winbind)\n", sid_string_static(psid))); return NT_STATUS_UNSUCCESSFUL; } @@ -514,13 +729,13 @@ NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) if ( !winbind_sid_to_gid(pgid, psid) ) { DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid for sid %s\n", - sid_to_string(sid_str, psid) )); + sid_string_static(psid))); return NT_STATUS_UNSUCCESSFUL; } success: - DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), - (unsigned int)*pgid )); + DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid), + (unsigned int)*pgid )); store_gid_sid_cache(psid, *pgid); |