diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 7 | ||||
-rw-r--r-- | source3/groupdb/mapping.c | 15 | ||||
-rw-r--r-- | source3/include/passdb.h | 14 | ||||
-rw-r--r-- | source3/include/smb.h | 4 | ||||
-rw-r--r-- | source3/lib/util_sid.c | 45 | ||||
-rw-r--r-- | source3/modules/vfs_afsacl.c | 35 | ||||
-rw-r--r-- | source3/nsswitch/wb_client.c | 41 | ||||
-rw-r--r-- | source3/passdb/lookup_sid.c | 399 | ||||
-rw-r--r-- | source3/passdb/machine_sid.c | 24 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 135 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 116 | ||||
-rw-r--r-- | source3/passdb/secrets.c | 2 | ||||
-rw-r--r-- | source3/passdb/util_builtin.c | 110 | ||||
-rw-r--r-- | source3/passdb/util_sam_sid.c | 238 | ||||
-rw-r--r-- | source3/passdb/util_wellknown.c | 149 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 123 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 144 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 10 |
19 files changed, 999 insertions, 614 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 888a0ebe34..c0753a76c0 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -326,7 +326,7 @@ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ - passdb/util_sam_sid.o passdb/pdb_compat.o \ + passdb/util_wellknown.o passdb/util_builtin.o passdb/pdb_compat.o \ passdb/lookup_sid.o \ passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \ lib/system_smbd.o lib/account_pol.o lib/privileges.o diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 61cb7f31cc..ce1ce31d08 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1550,7 +1550,7 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) Check for a SID in an NT_USER_TOKEN ****************************************************************************/ -BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token ) +static BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token ) { int i; @@ -1598,8 +1598,6 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid ) BOOL is_trusted_domain(const char* dom_name) { DOM_SID trustdom_sid; - char *pass = NULL; - time_t lct; BOOL ret; /* no trusted domains for a standalone server */ @@ -1613,9 +1611,8 @@ BOOL is_trusted_domain(const char* dom_name) become_root(); DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n", dom_name )); - ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct); + ret = secrets_fetch_trusted_domain_password(dom_name, NULL, NULL, NULL); unbecome_root(); - SAFE_FREE(pass); if (ret) return True; } diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 1e8586786c..14040e4f52 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -1166,11 +1166,22 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, enum SID_NAME_USE type; uint32 new_rid; gid_t gid; - + BOOL exists; GROUP_MAP map; - if (lookup_name(get_global_sam_name(), name, &sid, &type)) + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + if (mem_ctx == NULL) { + return NT_STATUS_NO_MEMORY; + } + + exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED, + NULL, NULL, &sid, &type); + talloc_free(mem_ctx); + + if (exists) { return NT_STATUS_ALIAS_EXISTS; + } if (!winbind_allocate_rid_and_gid(&new_rid, &gid)) return NT_STATUS_ACCESS_DENIED; diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 0589b9a7cd..20ea7021d0 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -376,6 +376,13 @@ typedef struct pdb_context const char **pp_names, uint32 *attrs); + NTSTATUS (*pdb_lookup_names)(struct pdb_context *context, + const DOM_SID *domain_sid, + size_t num_names, + const char **names, + uint32 *rids, + uint32 *attrs); + NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context, int policy_index, uint32 *value); @@ -499,6 +506,13 @@ typedef struct pdb_methods const char **pp_names, uint32 *attrs); + NTSTATUS (*lookup_names)(struct pdb_methods *methods, + const DOM_SID *domain_sid, + int num_names, + const char **pp_names, + uint32 *rids, + uint32 *attrs); + NTSTATUS (*get_account_policy)(struct pdb_methods *methods, int policy_index, uint32 *value); diff --git a/source3/include/smb.h b/source3/include/smb.h index 6511f10365..50b8c0369f 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -264,6 +264,10 @@ enum SID_NAME_USE SID_NAME_COMPUTER /* sid for a computer */ }; +#define LOOKUP_NAME_ISOLATED 1 /* Look up unqualified names */ +#define LOOKUP_NAME_REMOTE 2 /* Ask others */ +#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE) + /** * @brief Security Identifier * diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 4c274b5e01..92bc2fb893 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -75,11 +75,14 @@ const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */ { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +/* Unused, left here for documentary purposes */ +#if 0 #define SECURITY_NULL_SID_AUTHORITY 0 #define SECURITY_WORLD_SID_AUTHORITY 1 #define SECURITY_LOCAL_SID_AUTHORITY 2 #define SECURITY_CREATOR_SID_AUTHORITY 3 #define SECURITY_NT_AUTHORITY 5 +#endif /* * An NT compatible anonymous token. @@ -188,24 +191,6 @@ void split_domain_name(const char *fullname, char *domain, char *name) fullname, domain, name)); } -/**************************************************************************** - Test if a SID is wellknown and resolvable. -****************************************************************************/ - -BOOL resolvable_wellknown_sid(DOM_SID *sid) -{ - uint32 ia = (sid->id_auth[5]) + - (sid->id_auth[4] << 8 ) + - (sid->id_auth[3] << 16) + - (sid->id_auth[2] << 24); - - if (sid->sid_rev_num != SEC_DESC_REVISION || sid->num_auths < 1) - return False; - - return (ia == SECURITY_WORLD_SID_AUTHORITY || - ia == SECURITY_CREATOR_SID_AUTHORITY); -} - /***************************************************************** Convert a SID to an ascii string. *****************************************************************/ @@ -533,30 +518,6 @@ BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) } /***************************************************************** - 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); -} - -/***************************************************************** Calculates size of a sid. *****************************************************************/ diff --git a/source3/modules/vfs_afsacl.c b/source3/modules/vfs_afsacl.c index 41f40d1e3c..3794299b9a 100644 --- a/source3/modules/vfs_afsacl.c +++ b/source3/modules/vfs_afsacl.c @@ -105,27 +105,6 @@ static struct afs_ace *clone_afs_ace(TALLOC_CTX *mem_ctx, struct afs_ace *ace) return result; } - -/* Ok, this is sort-of a hack. We assume here that we have winbind users in - * AFS. And yet another copy of parse_domain_user.... */ - -static BOOL parse_domain_user(const char *domuser, fstring domain, - fstring user) -{ - char *p = strchr(domuser,*lp_winbind_separator()); - - if (p==NULL) { - return False; - } - - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - strupper_m(domain); - - return True; -} - static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx, BOOL positive, const char *name, uint32 rights) @@ -168,14 +147,16 @@ static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx, } else { - fstring user, domain; + fstring domain, uname; + char *p; - if (!parse_domain_user(name, domain, user)) { - fstrcpy(user, name); - fstrcpy(domain, lp_workgroup()); + p = strchr_m(name, lp_winbind_separator()); + if (p != NULL) { + *p = '\\'; } - - if (!lookup_name(domain, user, &sid, &type)) { + + if (!lookup_name(name, LOOKUP_NAME_FULL, + domain, uname, &sid, &type)) { DEBUG(10, ("Could not find AFS user %s\n", name)); sid_copy(&sid, &global_sid_NULL); diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index db56cf0444..6fe55e1209 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/nsswitch/wb_client.c @@ -64,39 +64,52 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, /* Call winbindd to convert sid to name */ -BOOL winbind_lookup_sid(const DOM_SID *sid, - fstring dom_name, fstring name, +BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + char **domain, char **name, enum SID_NAME_USE *name_type) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; - fstring sid_str; /* Initialise request */ ZERO_STRUCT(request); ZERO_STRUCT(response); - sid_to_string(sid_str, sid); - fstrcpy(request.data.sid, sid_str); + fstrcpy(request.data.sid, sid_string_static(sid)); /* Make request */ - result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); + result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, + &response); - /* Copy out result */ + if (result != NSS_STATUS_SUCCESS) { + return False; + } - if (result == NSS_STATUS_SUCCESS) { - fstrcpy(dom_name, response.data.name.dom_name); - fstrcpy(name, response.data.name.name); - *name_type = (enum SID_NAME_USE)response.data.name.type; + /* Copy out result */ - DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", - sid_str, dom_name, name)); + if (domain != NULL) { + *domain = talloc_strdup(mem_ctx, response.data.name.dom_name); + if (*domain == NULL) { + DEBUG(0, ("talloc failed\n")); + return False; + } + } + if (name != NULL) { + *name = talloc_strdup(mem_ctx, response.data.name.name); + if (*name == NULL) { + DEBUG(0, ("talloc failed\n")); + return False; + } } - return (result == NSS_STATUS_SUCCESS); + *name_type = (enum SID_NAME_USE)response.data.name.type; + + DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", + sid_string_static(sid), *domain, *name)); + return True; } /* Call winbindd to convert SID to uid */ 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; i<num_rids; i++) { - fstring name; + char *name; - if (lookup_builtin_rid(rids[i], name)) { + if (lookup_builtin_rid(names, rids[i], &name)) { attrs[i] = SID_NAME_ALIAS; - names[i] = talloc_strdup(names, name); - if (names[i] == NULL) { - return NT_STATUS_NO_MEMORY; - } + names[i] = name; DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); have_mapped = True; @@ -1680,14 +1713,69 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, } for (i = 0; i < num_rids; i++) { - fstring tmpname; - enum SID_NAME_USE type; - - if (lookup_global_sam_rid(rids[i], tmpname, &type)) { - attrs[i] = (uint32)type; - names[i] = talloc_strdup(names, tmpname); - if (names[i] == NULL) - return NT_STATUS_NO_MEMORY; + char *name; + + if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { + names[i] = name; + DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); + have_mapped = True; + } else { + have_unmapped = True; + attrs[i] = SID_NAME_UNKNOWN; + } + } + + done: + + result = NT_STATUS_NONE_MAPPED; + + if (have_mapped) + result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; + + return result; +} + +NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods, + const DOM_SID *domain_sid, + int num_names, + const char **names, + uint32 *rids, + uint32 *attrs) +{ + int i; + NTSTATUS result; + BOOL have_mapped = False; + BOOL have_unmapped = False; + + if (sid_check_is_builtin(domain_sid)) { + + for (i=0; i<num_names; i++) { + uint32 rid; + + if (lookup_builtin_name(names[i], &rid)) { + attrs[i] = SID_NAME_ALIAS; + rids[i] = rid; + DEBUG(5,("lookup_rids: %s:%d\n", + names[i], attrs[i])); + have_mapped = True; + } else { + have_unmapped = True; + attrs[i] = SID_NAME_UNKNOWN; + } + } + goto done; + } + + /* Should not happen, but better check once too many */ + if (!sid_check_is_domain(domain_sid)) { + return NT_STATUS_INVALID_HANDLE; + } + + for (i = 0; i < num_names; i++) { + char *name; + + if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { + names[i] = name; DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); have_mapped = True; } else { diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index bf57e013fc..c173a5ea86 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -359,7 +359,7 @@ BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd, if (pass_last_set_time) *pass_last_set_time = pass.mod_time; /* domain sid */ - sid_copy(sid, &pass.domain_sid); + if (sid != NULL) sid_copy(sid, &pass.domain_sid); return True; } diff --git a/source3/passdb/util_builtin.c b/source3/passdb/util_builtin.c new file mode 100644 index 0000000000..e22f5f3f58 --- /dev/null +++ b/source3/passdb/util_builtin.c @@ -0,0 +1,110 @@ +/* + Unix SMB/CIFS implementation. + Translate BUILTIN names to SIDs and vice versa + 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; +}; + +static const struct rid_name_map builtin_aliases[] = { + { BUILTIN_ALIAS_RID_ADMINS, "Administrators" }, + { BUILTIN_ALIAS_RID_USERS, "Users" }, + { BUILTIN_ALIAS_RID_GUESTS, "Guests" }, + { BUILTIN_ALIAS_RID_POWER_USERS, "Power Users" }, + { BUILTIN_ALIAS_RID_ACCOUNT_OPS, "Account Operators" }, + { BUILTIN_ALIAS_RID_SYSTEM_OPS, "Server Operators" }, + { BUILTIN_ALIAS_RID_PRINT_OPS, "Print Operators" }, + { BUILTIN_ALIAS_RID_BACKUP_OPS, "Backup Operators" }, + { BUILTIN_ALIAS_RID_REPLICATOR, "Replicator" }, + { BUILTIN_ALIAS_RID_RAS_SERVERS, "RAS Servers" }, + { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, "Pre-Windows 2000 Compatible Access" }, + { 0, NULL}}; + +/******************************************************************* + Look up a rid in the BUILTIN domain + ********************************************************************/ +BOOL lookup_builtin_rid(TALLOC_CTX *mem_ctx, uint32 rid, char **name) +{ + const struct rid_name_map *aliases = builtin_aliases; + + while (aliases->name != 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; +} diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index b56ae10914..78e9cd6211 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -135,67 +135,75 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) init_lsa_rid2s ***************************************************************************/ -static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2, - int num_entries, UNISTR2 *name, - uint32 *mapped_count, BOOL endian) +static int init_lsa_rid2s(TALLOC_CTX *mem_ctx, + DOM_R_REF *ref, DOM_RID2 *rid2, + int num_entries, UNISTR2 *name, + int flags) { - int i; - int total = 0; - *mapped_count = 0; + int mapped_count, i; SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS); + mapped_count = 0; + become_root(); /* lookup_name can require root privs */ for (i = 0; i < num_entries; i++) { BOOL status = False; DOM_SID sid; - uint32 rid = 0xffffffff; - int dom_idx = -1; - pstring full_name; - fstring dom_name, user; - enum SID_NAME_USE name_type = SID_NAME_UNKNOWN; + uint32 rid; + int dom_idx; + char *full_name, *domain; + enum SID_NAME_USE type = SID_NAME_UNKNOWN; /* Split name into domain and user component */ - unistr2_to_ascii(full_name, &name[i], sizeof(full_name)); - split_domain_name(full_name, dom_name, user); - - /* Lookup name */ + if (rpcstr_pull_unistr2_talloc(mem_ctx, &full_name, + &name[i]) < 0) { + DEBUG(0, ("pull_ucs2_talloc failed\n")); + return 0; + } DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name)); - status = lookup_name(dom_name, user, &sid, &name_type); - - if((name_type == SID_NAME_UNKNOWN) && (lp_server_role() == ROLE_DOMAIN_MEMBER) && (strncmp(dom_name, full_name, strlen(dom_name)) != 0)) { - DEBUG(5, ("init_lsa_rid2s: domain name not provided and local account not found, using member domain\n")); - fstrcpy(dom_name, lp_workgroup()); - status = lookup_name(dom_name, user, &sid, &name_type); - } + /* We can ignore the result of lookup_name, it will not touch + "type" if it's not successful */ - if (name_type == SID_NAME_WKN_GRP) { - /* BUILTIN aliases are still aliases :-) */ - name_type = SID_NAME_ALIAS; - } + lookup_name(mem_ctx, full_name, flags, &domain, NULL, + &sid, &type); DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" : "not found")); - if (status && name_type != SID_NAME_UNKNOWN) { + switch (type) { + case SID_NAME_USER: + case SID_NAME_DOM_GRP: + case SID_NAME_DOMAIN: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + /* Leave these unchanged */ + break; + default: + /* Don't hand out anything but the list above */ + type = SID_NAME_UNKNOWN; + break; + } + + rid = 0; + dom_idx = -1; + + if (type != SID_NAME_UNKNOWN) { sid_split_rid(&sid, &rid); - dom_idx = init_dom_ref(ref, dom_name, &sid); - (*mapped_count)++; - } else { - dom_idx = -1; - rid = 0; - name_type = SID_NAME_UNKNOWN; + dom_idx = init_dom_ref(ref, domain, &sid); + mapped_count++; } - init_dom_rid2(&rid2[total], rid, name_type, dom_idx); - total++; + init_dom_rid2(&rid2[i], rid, type, dom_idx); } unbecome_root(); + + return mapped_count; } /*************************************************************************** @@ -250,42 +258,44 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME DOM_SID find_sid = sid[i].sid; uint32 rid = 0xffffffff; int dom_idx = -1; - fstring name, dom_name; - enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0; + char *name, *domain; + enum SID_NAME_USE type = SID_NAME_UNKNOWN; - sid_to_string(name, &find_sid); - DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name)); + DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", + sid_string_static(&find_sid))); /* Lookup sid from winbindd */ - status = lookup_sid(&find_sid, dom_name, name, &sid_name_use); + status = lookup_sid(ctx, &find_sid, &domain, &name, &type); DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" : "not found")); if (!status) { - sid_name_use = SID_NAME_UNKNOWN; - memset(dom_name, '\0', sizeof(dom_name)); - sid_to_string(name, &find_sid); + type = SID_NAME_UNKNOWN; + domain = talloc_strdup(ctx, ""); + name = talloc_strdup(ctx, + sid_string_static(&find_sid)); dom_idx = -1; - DEBUG(10,("init_lsa_trans_names: added unknown user '%s' to " - "referenced list.\n", name )); + DEBUG(10,("init_lsa_trans_names: added unknown user " + "'%s' to referenced list.\n", name )); } else { (*mapped_count)++; /* Store domain sid in ref array */ if (find_sid.num_auths == 5) { sid_split_rid(&find_sid, &rid); } - dom_idx = init_dom_ref(ref, dom_name, &find_sid); + dom_idx = init_dom_ref(ref, domain, &find_sid); - DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' (%d) to referenced list.\n", - sid_type_lookup(sid_name_use), dom_name, name, sid_name_use )); + DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' " + "(%d) to referenced list.\n", + sid_type_lookup(type), domain, name, type)); } init_lsa_trans_name(&trn->name[total], &trn->uni_name[total], - sid_name_use, name, dom_idx); + type, name, dom_idx); total++; } @@ -697,12 +707,18 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP DOM_R_REF *ref; DOM_RID2 *rids; uint32 mapped_count = 0; + int flags = 0; if (num_entries > MAX_LOOKUP_SIDS) { num_entries = MAX_LOOKUP_SIDS; DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries)); } + /* Probably the lookup_level is some sort of bitmask. */ + if (q_u->lookup_level == 1) { + flags = LOOKUP_NAME_ALL; + } + ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries); @@ -720,10 +736,11 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP if (!ref || !rids) return NT_STATUS_NO_MEMORY; + /* set up the LSA Lookup RIDs response */ + mapped_count = init_lsa_rid2s(p->mem_ctx, ref, rids, num_entries, + names, flags); done: - /* set up the LSA Lookup RIDs response */ - init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian); if (NT_STATUS_IS_OK(r_u->status)) { if (mapped_count == 0) r_u->status = NT_STATUS_NONE_MAPPED; @@ -1109,15 +1126,13 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u) { struct lsa_info *info=NULL; - fstring name, dom_name; - enum SID_NAME_USE type; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) return NT_STATUS_INVALID_HANDLE; - if (!lookup_sid(&info->sid, dom_name, name, &type)) + if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL)) return NT_STATUS_ACCESS_DENIED; /* diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 635d870762..13f3a3284b 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1366,9 +1366,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u) { uint32 rid[MAX_SAM_ENTRIES]; - uint32 local_rid; enum SID_NAME_USE type[MAX_SAM_ENTRIES]; - enum SID_NAME_USE local_type; int i; int num_rids = q_u->num_names2; DOM_SID pol_sid; @@ -1400,42 +1398,30 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO for (i = 0; i < num_rids; i++) { fstring name; - DOM_SID sid; int ret; r_u->status = NT_STATUS_NONE_MAPPED; + type[i] = SID_NAME_UNKNOWN; rid [i] = 0xffffffff; - type[i] = SID_NAME_UNKNOWN; ret = rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0); - /* - * we are only looking for a name - * the SID we get back can be outside - * the scope of the pol_sid - * - * in clear: it prevents to reply to domain\group: yes - * when only builtin\group exists. - * - * a cleaner code is to add the sid of the domain we're looking in - * to the local_lookup_name function. - */ - - if ((ret > 0) && local_lookup_name(name, &sid, &local_type)) { - sid_split_rid(&sid, &local_rid); - - if (sid_equal(&sid, &pol_sid)) { - rid[i]=local_rid; - - /* Windows does not return WKN_GRP here, even - * on lookups in builtin */ - type[i] = (local_type == SID_NAME_WKN_GRP) ? - SID_NAME_ALIAS : local_type; - - r_u->status = NT_STATUS_OK; + if (ret <= 0) { + continue; + } + + if (sid_check_is_builtin(&pol_sid)) { + if (lookup_builtin_name(name, &rid[i])) { + type[i] = SID_NAME_ALIAS; } - } + } else { + lookup_global_sam_name(name, &rid[i], &type[i]); + } + + if (type[i] != SID_NAME_UNKNOWN) { + r_u->status = NT_STATUS_OK; + } } init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status); @@ -2247,6 +2233,41 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA return r_u->status; } +/* W2k3 seems to use the same check for all 3 objects that can be created via + * SAMR, if you try to create for example "Dialup" as an alias it says + * "NT_STATUS_USER_EXISTS". This is racy, but we can't really lock the user + * database. */ + +static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name) +{ + enum SID_NAME_USE type; + BOOL result; + + become_root(); + /* Lookup in our local databases (only LOOKUP_NAME_ISOLATED set) + * whether the name already exists */ + result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_ISOLATED, + NULL, NULL, NULL, &type); + unbecome_root(); + + if (!result) { + return NT_STATUS_OK; + } + + DEBUG(5, ("trying to create %s, exists as %s\n", + new_name, sid_type_lookup(type))); + + if (type == SID_NAME_DOM_GRP) { + return NT_STATUS_GROUP_EXISTS; + } + if (type == SID_NAME_ALIAS) { + return NT_STATUS_ALIAS_EXISTS; + } + + /* Yes, the default is NT_STATUS_USER_EXISTS */ + return NT_STATUS_USER_EXISTS; +} + /******************************************************************* _samr_create_user Create an account, can be either a normal user or a machine. @@ -2294,19 +2315,11 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0); strlower_m(account); - pdb_init_sam(&sam_pass); - - become_root(); - ret = pdb_getsampwnam(sam_pass, account); - unbecome_root(); - if (ret == True) { - /* this account exists: say so */ - pdb_free_sam(&sam_pass); - return NT_STATUS_USER_EXISTS; + nt_status = can_create(p->mem_ctx, account); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; } - pdb_free_sam(&sam_pass); - /********************************************************************* * HEADS UP! If we have to create a new user account, we have to get * a new RID from somewhere. This used to be done by the passdb @@ -2776,7 +2789,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A /* append the alias' RID to it */ if (!sid_append_rid(&sid, alias_rid)) - return NT_STATUS_NO_SUCH_USER; + return NT_STATUS_NO_SUCH_ALIAS; /*check if access can be granted as requested by client. */ @@ -2793,12 +2806,21 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A if ( !NT_STATUS_IS_OK(status) ) return status; - /* - * we should check if the rid really exist !!! - * JFM. - */ + { + /* Check we actually have the requested alias */ + enum SID_NAME_USE type; + BOOL result; - /* associate the user's SID with the new handle. */ + become_root(); + result = lookup_sid(NULL, &sid, NULL, NULL, &type); + unbecome_root(); + + if (!result || (type != SID_NAME_ALIAS)) { + return NT_STATUS_NO_SUCH_ALIAS; + } + } + + /* associate the alias SID with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) return NT_STATUS_NO_MEMORY; @@ -2814,12 +2836,11 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A /******************************************************************* set_user_info_7 ********************************************************************/ -static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd) +static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, + const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd) { fstring new_name; - SAM_ACCOUNT *check_acct = NULL; NTSTATUS rc; - BOOL check_rc; if (id7 == NULL) { DEBUG(5, ("set_user_info_7: NULL id7\n")); @@ -2842,13 +2863,9 @@ static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd) simply that the rename fails with a slightly different status code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - pdb_init_sam(&check_acct); - check_rc = pdb_getsampwnam(check_acct, new_name); - pdb_free_sam(&check_acct); - - if (check_rc == True) { - /* this account exists: say so */ - return NT_STATUS_USER_EXISTS; + rc = can_create(mem_ctx, new_name); + if (!NT_STATUS_IS_OK(rc)) { + return rc; } rc = pdb_rename_sam_account(pwd, new_name); @@ -3365,7 +3382,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ switch (switch_value) { case 7: - r_u->status = set_user_info_7(ctr->info.id7, pwd); + r_u->status = set_user_info_7(p->mem_ctx, + ctr->info.id7, pwd); break; case 16: if (!set_user_info_16(ctr->info.id16, pwd)) @@ -4199,9 +4217,10 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1); - /* check if group already exist */ - if ((grp=getgrnam(name)) != NULL) - return NT_STATUS_GROUP_EXISTS; + r_u->status = can_create(p->mem_ctx, name); + if (!NT_STATUS_IS_OK(r_u->status)) { + return r_u->status; + } se_priv_copy( &se_rights, &se_add_users ); can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); @@ -4289,6 +4308,11 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; + r_u->status = can_create(p->mem_ctx, name); + if (!NT_STATUS_IS_OK(r_u->status)) { + return r_u->status; + } + unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1); se_priv_copy( &se_rights, &se_add_users ); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 1e2a248851..90e36e2a83 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1837,9 +1837,6 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para gid_t *gids; size_t num_groups; size_t i; - fstring grp_domain; - fstring grp_name; - enum SID_NAME_USE grp_type; struct passwd *passwd; NTSTATUS result; @@ -1896,9 +1893,12 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para goto out; for (i=0; i<num_groups; i++) { + + char *grp_name; - if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) { - pstrcpy(p, grp_name); + if ( lookup_sid(sampw->mem_ctx, &sids[i], NULL, &grp_name, + NULL) ) { + pstrcpy(p, grp_name); p += 21; count++; } |