BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; extern fstring global_myworkgroup; fstring sid; char *sep = lp_winbind_separator(); *name_type = SID_NAME_UNKNOWN; if (!winbind_lookup_name(NULL, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { BOOL ret = False; DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); /* If we are looking up a domain user, make sure it is for the local machine only */ if (strchr(name, sep[0]) || strchr(name, '\\')) { fstring domain, username; split_domain_name(name, domain, username); switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: if (strequal(domain, global_myworkgroup)) { fstrcpy(domain, global_myname); ret = local_lookup_name(domain, username, psid, name_type); } /* No break is deliberate here. JRA. */ default: if (strcasecmp(global_myname, domain) != 0) { DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); ret = local_lookup_name(global_myname, username, psid, name_type); } } } else { ret = local_lookup_name(global_myname, name, psid, name_type); } if (ret) { DEBUG(10, ("lookup_name: (local) %s -> SID %s (type %u)\n", name, sid_to_string(sid,psid), (unsigned int)*name_type )); } else { DEBUG(10,("lookup name: (local) %s failed.\n", name)); } return ret; } DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", name, sid_to_string(sid, psid), (unsigned int)*name_type)); return True; }
struct sys_userlist *get_users_in_group(const char *gname) { struct sys_userlist *list_head = NULL; struct group *gptr; fstring domain; fstring groupname; DOM_SID sid; enum SID_NAME_USE name_type; /* No point using winbind if we can't split it in the first place */ if (split_domain_and_name(gname, domain, groupname)) { /* * If we're doing this via winbindd, don't do the * entire group list enumeration as we know this is * pointless (and slow). */ if (winbind_lookup_name(domain, groupname, &sid, &name_type) && name_type == SID_NAME_DOM_GRP) { if ((gptr = (struct group *)getgrnam(gname)) == NULL) return NULL; return add_members_to_userlist(list_head, gptr); } } #if !defined(BROKEN_GETGRNAM) if ((gptr = (struct group *)getgrnam(gname)) == NULL) return NULL; return add_members_to_userlist(list_head, gptr); #else /* BROKEN_GETGRNAM - True64 */ setgrent(); while((gptr = getgrent()) != NULL) { if (strequal(gname, gptr->gr_name)) { list_head = add_members_to_userlist(list_head, gptr); if (list_head == NULL) return NULL; } } endgrent(); return list_head; #endif }
bool lookup_name(TALLOC_CTX *mem_ctx, const char *full_name, int flags, const char **ret_domain, const char **ret_name, DOM_SID *ret_sid, enum lsa_SidType *ret_type) { char *p; const char *tmp; const char *domain = NULL; const char *name = NULL; uint32 rid; DOM_SID sid; enum lsa_SidType type; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (tmp_ctx == NULL) { DEBUG(0, ("talloc_new failed\n")); return false; } p = strchr_m(full_name, '\\'); if (p != NULL) { domain = talloc_strndup(tmp_ctx, full_name, PTR_DIFF(p, full_name)); name = talloc_strdup(tmp_ctx, p+1); } else { domain = talloc_strdup(tmp_ctx, ""); name = talloc_strdup(tmp_ctx, full_name); } if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", full_name, domain, name)); DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); if ((flags & LOOKUP_NAME_DOMAIN) && strequal(domain, get_global_sam_name())) { /* It's our own domain, lookup the name in passdb */ if (lookup_global_sam_name(name, flags, &rid, &type)) { sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); goto ok; } TALLOC_FREE(tmp_ctx); return false; } if ((flags & LOOKUP_NAME_BUILTIN) && 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; } TALLOC_FREE(tmp_ctx); return false; } /* Try the explicit winbind lookup first, don't let it guess the * domain yet at this point yet. This comes later. */ if ((domain[0] != '\0') && (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) && (winbind_lookup_name(domain, name, &sid, &type))) { goto ok; } if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) { if (lookup_unix_user_name(name, &sid)) { type = SID_NAME_USER; goto ok; } TALLOC_FREE(tmp_ctx); return false; } if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) { if (lookup_unix_group_name(name, &sid)) { type = SID_NAME_DOM_GRP; goto ok; } TALLOC_FREE(tmp_ctx); return false; } if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) { TALLOC_FREE(tmp_ctx); 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 */ if ((flags & LOOKUP_NAME_WKN) && lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) { type = SID_NAME_WKN_GRP; goto ok; } /* 2. Builtin domain as such */ if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) && 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 ((flags & LOOKUP_NAME_DOMAIN) && strequal(name, get_global_sam_name())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch my SID\n")); TALLOC_FREE(tmp_ctx); return false; } /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; goto ok; } /* 4. Primary domain */ if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC && strequal(name, lp_workgroup())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch the domain SID\n")); TALLOC_FREE(tmp_ctx); 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 ((flags & LOOKUP_NAME_REMOTE) && IS_DC && (pdb_get_trusteddom_pw(name, NULL, &sid, NULL))) { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; goto ok; } /* 6. Builtin aliases */ if ((flags & LOOKUP_NAME_BUILTIN) && lookup_builtin_name(name, &rid)) { domain = talloc_strdup(tmp_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 ((flags & LOOKUP_NAME_DOMAIN) && lookup_global_sam_name(name, flags, &rid, &type)) { domain = talloc_strdup(tmp_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)) { TALLOC_FREE(tmp_ctx); 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(tmp_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 lsa_SidType domain_type; if (type == SID_NAME_DOMAIN) { /* Swap name and type */ tmp = name; name = domain; domain = tmp; goto ok; } /* 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(tmp_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")); TALLOC_FREE(tmp_ctx); return false; } goto ok; } /* 10. Don't translate */ /* 11. Ok, windows would end here. Samba has two more options: Unmapped users and unmapped groups */ if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) { domain = talloc_strdup(tmp_ctx, unix_users_domain_name()); type = SID_NAME_USER; goto ok; } if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) { domain = talloc_strdup(tmp_ctx, unix_groups_domain_name()); type = SID_NAME_DOM_GRP; goto ok; } /* * Ok, all possibilities tried. Fail. */ TALLOC_FREE(tmp_ctx); return false; ok: if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } /* * Hand over the results to the talloc context we've been given. */ if ((ret_name != NULL) && !(*ret_name = talloc_strdup(mem_ctx, name))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } if (ret_domain != NULL) { char *tmp_dom; if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } strupper_m(tmp_dom); *ret_domain = tmp_dom; } if (ret_sid != NULL) { sid_copy(ret_sid, &sid); } if (ret_type != NULL) { *ret_type = type; } TALLOC_FREE(tmp_ctx); return true; }
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) { int i; /* initialize the status to avoid suprise */ for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; } for (i = 0; ids[i]; i++) { struct passwd *pw; struct group *gr; const char *name; enum lsa_SidType type; bool ret; switch (ids[i]->xid.type) { case ID_TYPE_UID: pw = getpwuid((uid_t)ids[i]->xid.id); if (!pw) { ids[i]->status = ID_UNMAPPED; continue; } name = pw->pw_name; break; case ID_TYPE_GID: gr = getgrgid((gid_t)ids[i]->xid.id); if (!gr) { ids[i]->status = ID_UNMAPPED; continue; } name = gr->gr_name; break; default: /* ?? */ ids[i]->status = ID_UNKNOWN; continue; } /* by default calls to winbindd are disabled the following call will not recurse so this is safe */ (void)winbind_on(); /* Lookup name from PDC using lsa_lookup_names() */ ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type); (void)winbind_off(); if (!ret) { /* TODO: how do we know if the name is really not mapped, * or something just failed ? */ ids[i]->status = ID_UNMAPPED; continue; } switch (type) { case SID_NAME_USER: if (ids[i]->xid.type == ID_TYPE_UID) { ids[i]->status = ID_MAPPED; } break; case SID_NAME_DOM_GRP: case SID_NAME_ALIAS: case SID_NAME_WKN_GRP: if (ids[i]->xid.type == ID_TYPE_GID) { ids[i]->status = ID_MAPPED; } break; default: ids[i]->status = ID_UNKNOWN; break; } } return NT_STATUS_OK; }
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) { TALLOC_CTX *ctx; int i; if (! dom->initialized) { return NT_STATUS_UNSUCCESSFUL; } ctx = talloc_new(dom); if ( ! ctx) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } for (i = 0; ids[i]; i++) { struct passwd *pw; struct group *gr; const char *name; enum lsa_SidType type; BOOL ret; switch (ids[i]->xid.type) { case ID_TYPE_UID: pw = getpwuid((uid_t)ids[i]->xid.id); if (!pw) { ids[i]->status = ID_UNMAPPED; continue; } name = pw->pw_name; break; case ID_TYPE_GID: gr = getgrgid((gid_t)ids[i]->xid.id); if (!gr) { ids[i]->status = ID_UNMAPPED; continue; } name = gr->gr_name; break; default: /* ?? */ ids[i]->status = ID_UNKNOWN; continue; } /* by default calls to winbindd are disabled the following call will not recurse so this is safe */ winbind_on(); /* Lookup name from PDC using lsa_lookup_names() */ ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type); winbind_off(); if (!ret) { /* TODO: how do we know if the name is really not mapped, * or something just failed ? */ ids[i]->status = ID_UNMAPPED; continue; } switch (type) { case SID_NAME_USER: if (ids[i]->xid.type == ID_TYPE_UID) { ids[i]->status = ID_MAPPED; } break; case SID_NAME_DOM_GRP: case SID_NAME_ALIAS: case SID_NAME_WKN_GRP: if (ids[i]->xid.type == ID_TYPE_GID) { ids[i]->status = ID_MAPPED; } break; default: ids[i]->status = ID_UNKNOWN; break; } } talloc_free(ctx); return NT_STATUS_OK; }