From 05ac2de0df78d22ad5afb42ea5c72ba17bef8395 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 3 Dec 2005 18:34:13 +0000 Subject: r12051: Merge across the lookup_name and lookup_sid work. Lets see how the build farm reacts :-) Volker (This used to be commit 9f99d04a54588cd9d1a1ab163ebb304437f932f7) --- source3/passdb/lookup_sid.c | 399 +++++++++++++++++++++++++++++++--------- source3/passdb/machine_sid.c | 24 +++ source3/passdb/passdb.c | 135 ++++++++------ source3/passdb/pdb_interface.c | 116 ++++++++++-- source3/passdb/secrets.c | 2 +- source3/passdb/util_builtin.c | 110 +++++++++++ source3/passdb/util_sam_sid.c | 238 ------------------------ source3/passdb/util_wellknown.c | 149 +++++++++++++++ 8 files changed, 769 insertions(+), 404 deletions(-) create mode 100644 source3/passdb/util_builtin.c delete mode 100644 source3/passdb/util_sam_sid.c create mode 100644 source3/passdb/util_wellknown.c (limited to 'source3/passdb') 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); diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c index 87ec27d34e..074a516bcb 100644 --- a/source3/passdb/machine_sid.c +++ b/source3/passdb/machine_sid.c @@ -198,3 +198,27 @@ void reset_global_sam_sid(void) { SAFE_FREE(global_sam_sid); } + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ + +BOOL sid_check_is_domain(const DOM_SID *sid) +{ + return sid_equal(sid, get_global_sam_sid()); +} + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ + +BOOL sid_check_is_in_our_domain(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, get_global_sam_sid()); +} diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index e073db3499..3ca26a57c7 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -735,7 +735,7 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid) Look up a rid in the SAM we're responsible for (i.e. passdb) ********************************************************************/ -BOOL lookup_global_sam_rid(uint32 rid, fstring name, +BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, char **name, enum SID_NAME_USE *psid_name_use) { SAM_ACCOUNT *sam_account = NULL; @@ -760,7 +760,7 @@ BOOL lookup_global_sam_rid(uint32 rid, fstring name, become_root(); if (pdb_getsampwsid(sam_account, &sid)) { unbecome_root(); /* -----> EXIT BECOME_ROOT() */ - fstrcpy(name, pdb_get_username(sam_account)); + *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; pdb_free_sam(&sam_account); @@ -784,14 +784,14 @@ BOOL lookup_global_sam_rid(uint32 rid, fstring name, map.nt_name)); } - fstrcpy(name, map.nt_name); + *name = talloc_strdup(mem_ctx, map.nt_name); *psid_name_use = map.sid_name_use; return True; } if (rid == DOMAIN_USER_RID_ADMIN) { *psid_name_use = SID_NAME_USER; - fstrcpy(name, "Administrator"); + *name = talloc_strdup(mem_ctx, "Administrator"); return True; } @@ -807,13 +807,15 @@ BOOL lookup_global_sam_rid(uint32 rid, fstring name, DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n", (unsigned int)uid, pw ? "succeeded" : "failed" )); - if ( !pw ) - fstr_sprintf(name, "unix_user.%u", (unsigned int)uid); - else - fstrcpy( name, pw->pw_name ); + if ( !pw ) { + *name = talloc_asprintf(mem_ctx, "unix_user.%u", + (unsigned int)uid); + } else { + *name = talloc_strdup(mem_ctx, pw->pw_name ); + } DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n", - name, (unsigned int)rid )); + *name, (unsigned int)rid )); *psid_name_use = SID_NAME_USER; @@ -830,13 +832,15 @@ BOOL lookup_global_sam_rid(uint32 rid, fstring name, DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n", (unsigned int)gid, gr ? "succeeded" : "failed" )); - if( !gr ) - fstr_sprintf(name, "unix_group.%u", (unsigned int)gid); - else - fstrcpy( name, gr->gr_name); + if( !gr ) { + *name = talloc_asprintf(mem_ctx, "unix_group.%u", + (unsigned int)gid); + } else { + *name = talloc_strdup(mem_ctx, gr->gr_name); + } DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n", - name, (unsigned int)rid )); + *name, (unsigned int)rid )); /* assume algorithmic groups are domain global groups */ @@ -850,17 +854,13 @@ BOOL lookup_global_sam_rid(uint32 rid, fstring name, Convert a name into a SID. Used in the lookup name rpc. ********************************************************************/ -BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use) +BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE *type) { - DOM_SID local_sid; - DOM_SID sid; fstring user; SAM_ACCOUNT *sam_account = NULL; struct group *grp; GROUP_MAP map; - *psid_name_use = SID_NAME_UNKNOWN; - /* * user may be quoted a const string, and map_username and * friends can modify it. Make a modifiable copy. JRA. @@ -868,17 +868,6 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi fstrcpy(user, c_user); - sid_copy(&local_sid, get_global_sam_sid()); - - if (map_name_to_wellknown_sid(&sid, psid_name_use, user)){ - fstring sid_str; - sid_copy( psid, &sid); - sid_to_string(sid_str, &sid); - DEBUG(10,("lookup_name: name %s = SID %s, type = %u\n", user, sid_str, - (unsigned int)*psid_name_use )); - return True; - } - (void)map_username(user); if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { @@ -889,10 +878,28 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi become_root(); if (pdb_getsampwnam(sam_account, user)) { + const DOM_SID *user_sid; + unbecome_root(); - sid_copy(psid, pdb_get_user_sid(sam_account)); - *psid_name_use = SID_NAME_USER; - + + user_sid = pdb_get_user_sid(sam_account); + + if (!sid_check_is_in_our_domain(user_sid)) { + DEBUG(0, ("User %s with invalid SID %s in passdb\n", + user, sid_string_static(user_sid))); + return False; + } + + sid_peek_rid(user_sid, rid); + + if (pdb_get_acct_ctrl(sam_account) & + (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST)) { + /* We have to filter them out in lsa_lookupnames, + * indicate that this is not a real user. */ + *type = SID_NAME_COMPUTER; + } else { + *type = SID_NAME_USER; + } pdb_free_sam(&sam_account); return True; } @@ -905,41 +912,51 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi /* check if it's a mapped group */ if (pdb_getgrnam(&map, user)) { - /* yes it's a mapped group */ - sid_copy(&local_sid, &map.sid); - *psid_name_use = map.sid_name_use; - } else { - /* it's not a mapped group */ - grp = getgrnam(user); - if(!grp) { - unbecome_root(); /* ---> exit form block */ + + unbecome_root(); + + /* BUILTIN groups are looked up elsewhere */ + if (!sid_check_is_in_our_domain(&map.sid)) { + DEBUG(10, ("Found group %s (%s) not in our domain -- " + "ignoring.", user, + sid_string_static(&map.sid))); return False; } - /* - *check if it's mapped, if it is reply it doesn't exist - * - * that's to prevent this case: - * - * unix group ug is mapped to nt group ng - * someone does a lookup on ug - * we must not reply as it doesn't "exist" anymore - * for NT. For NT only ng exists. - * JFM, 30/11/2001 - */ + /* yes it's a mapped group */ + sid_peek_rid(&map.sid, rid); + *type = map.sid_name_use; + return True; + } + + /* it's not a mapped group */ + grp = getgrnam(user); + if(!grp) { + unbecome_root(); /* ---> exit form block */ + return False; + } - if (pdb_getgrgid(&map, grp->gr_gid)){ - unbecome_root(); /* ---> exit form block */ - return False; - } + /* + *check if it's mapped, if it is reply it doesn't exist + * + * that's to prevent this case: + * + * unix group ug is mapped to nt group ng + * someone does a lookup on ug + * we must not reply as it doesn't "exist" anymore + * for NT. For NT only ng exists. + * JFM, 30/11/2001 + */ - sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); - *psid_name_use = SID_NAME_ALIAS; + if (pdb_getgrgid(&map, grp->gr_gid)) { + unbecome_root(); /* ---> exit form block */ + return False; } unbecome_root(); /* END ROOT BLOCK */ - sid_copy( psid, &local_sid); + *rid = pdb_gid_to_group_rid(grp->gr_gid); + *type = SID_NAME_ALIAS; return True; } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 875e264bf0..6ac5a3e965 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -699,6 +699,25 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context, rids, pp_names, pp_attrs); } +static NTSTATUS context_lookup_names(struct pdb_context *context, + const DOM_SID *domain_sid, + size_t num_names, + const char **pp_names, + uint32 *rids, + uint32 *pp_attrs) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->lookup_names(context->pdb_methods, + domain_sid, num_names, + pp_names, rids, pp_attrs); +} + static NTSTATUS context_get_account_policy(struct pdb_context *context, int policy_index, uint32 *value) { @@ -906,6 +925,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_enum_aliasmem = context_enum_aliasmem; (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; (*context)->pdb_lookup_rids = context_lookup_rids; + (*context)->pdb_lookup_names = context_lookup_names; (*context)->pdb_get_account_policy = context_get_account_policy; (*context)->pdb_set_account_policy = context_set_account_policy; @@ -1413,6 +1433,22 @@ NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid, num_rids, rids, names, attrs); } +NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid, + int num_names, + const char **names, + uint32 *rids, + uint32 *attrs) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return pdb_context->pdb_lookup_names(pdb_context, domain_sid, + num_names, names, rids, attrs); +} + BOOL pdb_get_account_policy(int policy_index, uint32 *value) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -1655,14 +1691,11 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, if (sid_check_is_builtin(domain_sid)) { for (i=0; iname != NULL) { + if (rid == aliases->rid) { + *name = talloc_strdup(mem_ctx, aliases->name); + return True; + } + aliases++; + } + + return False; +} + +/******************************************************************* + Look up a name in the BUILTIN domain + ********************************************************************/ +BOOL lookup_builtin_name(const char *name, uint32 *rid) +{ + const struct rid_name_map *aliases = builtin_aliases; + + while (aliases->name != NULL) { + if (strequal(name, aliases->name)) { + *rid = aliases->rid; + return True; + } + aliases++; + } + + return False; +} + +/***************************************************************** + Return the name of the BUILTIN domain +*****************************************************************/ + +const char *builtin_domain_name(void) +{ + return "BUILTIN"; +} + +/***************************************************************** + Check if the SID is the builtin SID (S-1-5-32). +*****************************************************************/ + +BOOL sid_check_is_builtin(const DOM_SID *sid) +{ + return sid_equal(sid, &global_sid_Builtin); +} + +/***************************************************************** + Check if the SID is one of the builtin SIDs (S-1-5-32-a). +*****************************************************************/ + +BOOL sid_check_is_in_builtin(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, &global_sid_Builtin); +} + diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c deleted file mode 100644 index 822b7f6a34..0000000000 --- a/source3/passdb/util_sam_sid.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 - Copyright (C) Jeremy Allison 1999 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#define MAX_SID_NAMES 7 - -typedef struct _known_sid_users { - uint32 rid; - enum SID_NAME_USE sid_name_use; - const char *known_user_name; -} known_sid_users; - -struct sid_name_map_info -{ - const DOM_SID *sid; - const char *name; - const known_sid_users *known_users; -}; - -static const known_sid_users everyone_users[] = { - { 0, SID_NAME_WKN_GRP, "Everyone" }, - {0, (enum SID_NAME_USE)0, NULL}}; - -static const known_sid_users creator_owner_users[] = { - { 0, SID_NAME_WKN_GRP, "Creator Owner" }, - { 1, SID_NAME_WKN_GRP, "Creator Group" }, - {0, (enum SID_NAME_USE)0, NULL}}; - -static const known_sid_users nt_authority_users[] = { - { 1, SID_NAME_WKN_GRP, "Dialup" }, - { 2, SID_NAME_WKN_GRP, "Network"}, - { 3, SID_NAME_WKN_GRP, "Batch"}, - { 4, SID_NAME_WKN_GRP, "Interactive"}, - { 6, SID_NAME_WKN_GRP, "Service"}, - { 7, SID_NAME_WKN_GRP, "AnonymousLogon"}, - { 8, SID_NAME_WKN_GRP, "Proxy"}, - { 9, SID_NAME_WKN_GRP, "ServerLogon"}, - { 10, SID_NAME_WKN_GRP, "Self"}, - { 11, SID_NAME_WKN_GRP, "Authenticated Users"}, - { 12, SID_NAME_WKN_GRP, "Restricted"}, - { 13, SID_NAME_WKN_GRP, "Terminal Server User"}, - { 14, SID_NAME_WKN_GRP, "Remote Interactive Logon"}, - { 15, SID_NAME_WKN_GRP, "This Organization"}, - { 18, SID_NAME_WKN_GRP, "SYSTEM"}, - { 19, SID_NAME_WKN_GRP, "Local Service"}, - { 20, SID_NAME_WKN_GRP, "Network Service"}, - { 0, (enum SID_NAME_USE)0, NULL}}; - -static const known_sid_users builtin_groups[] = { - { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" }, - { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" }, - { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" }, - { BUILTIN_ALIAS_RID_POWER_USERS, SID_NAME_ALIAS, "Power Users" }, - { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" }, - { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" }, - { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" }, - { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" }, - { BUILTIN_ALIAS_RID_REPLICATOR, SID_NAME_ALIAS, "Replicator" }, - { BUILTIN_ALIAS_RID_RAS_SERVERS, SID_NAME_ALIAS, "RAS Servers" }, - { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" }, - { 0, (enum SID_NAME_USE)0, NULL}}; - -static struct sid_name_map_info special_domains[] = { - { &global_sid_Builtin, "BUILTIN", builtin_groups }, - { &global_sid_World_Domain, "", everyone_users }, - { &global_sid_Creator_Owner_Domain, "", creator_owner_users }, - { &global_sid_NT_Authority, "NT Authority", nt_authority_users }, - { NULL, NULL, NULL }}; - -/************************************************************************** - Turns a domain SID into a name, returned in the nt_domain argument. -***************************************************************************/ - -BOOL map_domain_sid_to_name(const DOM_SID *sid, fstring nt_domain) -{ - fstring sid_str; - int i = 0; - - sid_to_string(sid_str, sid); - - DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); - - while (special_domains[i].sid != NULL) { - DEBUG(5,("map_domain_sid_to_name: compare: %s\n", - sid_string_static(special_domains[i].sid))); - if (sid_equal(special_domains[i].sid, sid)) { - fstrcpy(nt_domain, special_domains[i].name); - DEBUG(5,("map_domain_sid_to_name: found '%s'\n", - nt_domain)); - return True; - } - i++; - } - - DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", - sid_string_static(sid))); - - return False; -} - -/************************************************************************** - Looks up a known username from one of the known domains. -***************************************************************************/ - -BOOL lookup_special_sid(const DOM_SID *sid, const char **domain, - const char **name, enum SID_NAME_USE *type) -{ - int i; - DOM_SID dom_sid; - uint32 rid; - const known_sid_users *users = NULL; - - sid_copy(&dom_sid, sid); - if (!sid_split_rid(&dom_sid, &rid)) { - DEBUG(2, ("Could not split rid from SID\n")); - return False; - } - - for (i=0; special_domains[i].sid != NULL; i++) { - if (sid_equal(&dom_sid, special_domains[i].sid)) { - *domain = special_domains[i].name; - users = special_domains[i].known_users; - break; - } - } - - if (users == NULL) { - DEBUG(10, ("SID %s is no special sid\n", - sid_string_static(sid))); - return False; - } - - for (i=0; users[i].known_user_name != NULL; i++) { - if (rid == users[i].rid) { - *name = users[i].known_user_name; - *type = users[i].sid_name_use; - return True; - } - } - - DEBUG(10, ("RID of special SID %s not found\n", - sid_string_static(sid))); - - return False; -} - -/******************************************************************* - Look up a rid in the BUILTIN domain - ********************************************************************/ -BOOL lookup_builtin_rid(uint32 rid, fstring name) -{ - const known_sid_users *aliases = builtin_groups; - int i; - - for (i=0; aliases[i].known_user_name != NULL; i++) { - if (rid == aliases[i].rid) { - fstrcpy(name, aliases[i].known_user_name); - return True; - } - } - - return False; -} - -/***************************************************************** - Check if the SID is our domain SID (S-1-5-21-x-y-z). -*****************************************************************/ - -BOOL sid_check_is_domain(const DOM_SID *sid) -{ - return sid_equal(sid, get_global_sam_sid()); -} - -/***************************************************************** - Check if the SID is our domain SID (S-1-5-21-x-y-z). -*****************************************************************/ - -BOOL sid_check_is_in_our_domain(const DOM_SID *sid) -{ - DOM_SID dom_sid; - uint32 rid; - - sid_copy(&dom_sid, sid); - sid_split_rid(&dom_sid, &rid); - - return sid_equal(&dom_sid, get_global_sam_sid()); -} - -/************************************************************************** - Try and map a name to one of the well known SIDs. -***************************************************************************/ - -BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char *name) -{ - int i, j; - - DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); - - for (i=0; special_domains[i].sid != NULL; i++) { - const known_sid_users *users = special_domains[i].known_users; - - if (users == NULL) - continue; - - for (j=0; users[j].known_user_name != NULL; j++) { - if ( strequal(users[j].known_user_name, name) ) { - sid_copy(sid, special_domains[i].sid); - sid_append_rid(sid, users[j].rid); - *use = users[j].sid_name_use; - return True; - } - } - } - - return False; -} - - diff --git a/source3/passdb/util_wellknown.c b/source3/passdb/util_wellknown.c new file mode 100644 index 0000000000..b1eb8b4237 --- /dev/null +++ b/source3/passdb/util_wellknown.c @@ -0,0 +1,149 @@ +/* + Unix SMB/CIFS implementation. + Lookup routines for well-known SIDs + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 + Copyright (C) Jeremy Allison 1999 + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +struct rid_name_map { + uint32 rid; + const char *name; +}; + +struct sid_name_map_info +{ + const DOM_SID *sid; + const char *name; + const struct rid_name_map *known_users; +}; + +static const struct rid_name_map everyone_users[] = { + { 0, "Everyone" }, + { 0, NULL}}; + +static const struct rid_name_map creator_owner_users[] = { + { 0, "Creator Owner" }, + { 1, "Creator Group" }, + { 0, NULL}}; + +static const struct rid_name_map nt_authority_users[] = { + { 1, "Dialup" }, + { 2, "Network"}, + { 3, "Batch"}, + { 4, "Interactive"}, + { 6, "Service"}, + { 7, "AnonymousLogon"}, + { 8, "Proxy"}, + { 9, "ServerLogon"}, + { 10, "Self"}, + { 11, "Authenticated Users"}, + { 12, "Restricted"}, + { 13, "Terminal Server User"}, + { 14, "Remote Interactive Logon"}, + { 15, "This Organization"}, + { 18, "SYSTEM"}, + { 19, "Local Service"}, + { 20, "Network Service"}, + { 0, NULL}}; + +static struct sid_name_map_info special_domains[] = { + { &global_sid_World_Domain, "", everyone_users }, + { &global_sid_Creator_Owner_Domain, "", creator_owner_users }, + { &global_sid_NT_Authority, "NT Authority", nt_authority_users }, + { NULL, NULL, NULL }}; + +/************************************************************************** + Looks up a known username from one of the known domains. +***************************************************************************/ + +BOOL lookup_wellknown_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain, char **name) +{ + int i; + DOM_SID dom_sid; + uint32 rid; + const struct rid_name_map *users = NULL; + + sid_copy(&dom_sid, sid); + if (!sid_split_rid(&dom_sid, &rid)) { + DEBUG(2, ("Could not split rid from SID\n")); + return False; + } + + for (i=0; special_domains[i].sid != NULL; i++) { + if (sid_equal(&dom_sid, special_domains[i].sid)) { + *domain = talloc_strdup(mem_ctx, + special_domains[i].name); + users = special_domains[i].known_users; + break; + } + } + + if (users == NULL) { + DEBUG(10, ("SID %s is no special sid\n", + sid_string_static(sid))); + return False; + } + + for (i=0; users[i].name != NULL; i++) { + if (rid == users[i].rid) { + *name = talloc_strdup(mem_ctx, users[i].name); + return True; + } + } + + DEBUG(10, ("RID of special SID %s not found\n", + sid_string_static(sid))); + + return False; +} + +/************************************************************************** + Try and map a name to one of the well known SIDs. +***************************************************************************/ + +BOOL lookup_wellknown_name(TALLOC_CTX *mem_ctx, const char *name, + DOM_SID *sid, char **domain) +{ + int i, j; + + DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); + + for (i=0; special_domains[i].sid != NULL; i++) { + const struct rid_name_map *users = + special_domains[i].known_users; + + if (users == NULL) + continue; + + for (j=0; users[j].name != NULL; j++) { + if ( strequal(users[j].name, name) ) { + sid_copy(sid, special_domains[i].sid); + sid_append_rid(sid, users[j].rid); + *domain = talloc_strdup( + mem_ctx, special_domains[i].name); + return True; + } + } + } + + return False; +} -- cgit