1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-11 16:58:40 +03:00

r294: checking in volker's winbindd patches; tested on domain members (Samba and AD) as well as on a Samba DC

(This used to be commit 157d53782d6a7d0b7e30676a674ff2a25a15369c)
This commit is contained in:
Gerald Carter 2004-04-20 02:37:49 +00:00 committed by Gerald (Jerry) Carter
parent 1f7900ebda
commit f7cf0aaa6f
11 changed files with 239 additions and 129 deletions

@ -880,6 +880,8 @@ int main(int argc, char **argv)
if (!idmap_init(lp_idmap_backend())) if (!idmap_init(lp_idmap_backend()))
return 1; return 1;
generate_wellknown_sids();
/* Unblock all signals we are interested in as they may have been /* Unblock all signals we are interested in as they may have been
blocked by the parent process. */ blocked by the parent process. */

@ -94,6 +94,7 @@ struct winbindd_domain {
fstring name; /* Domain name */ fstring name; /* Domain name */
fstring alt_name; /* alt Domain name (if any) */ fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */ DOM_SID sid; /* SID for this domain */
BOOL initialized; /* Did we already ask for the domain mode? */
BOOL native_mode; /* is this a win2k domain in native mode ? */ BOOL native_mode; /* is this a win2k domain in native mode ? */
BOOL active_directory; /* is this a win2k active directory ? */ BOOL active_directory; /* is this a win2k active directory ? */
BOOL primary; /* is this our primary domain ? */ BOOL primary; /* is this our primary domain ? */
@ -149,6 +150,7 @@ struct winbindd_methods {
/* convert one user or group name to a sid */ /* convert one user or group name to a sid */
NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, NTSTATUS (*name_to_sid)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type); enum SID_NAME_USE *type);
@ -157,6 +159,7 @@ struct winbindd_methods {
NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, NTSTATUS (*sid_to_name)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const DOM_SID *sid, const DOM_SID *sid,
char **domain_name,
char **name, char **name,
enum SID_NAME_USE *type); enum SID_NAME_USE *type);

@ -323,48 +323,6 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
return NT_STATUS_OK; return NT_STATUS_OK;
} }
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type)
{
ADS_STRUCT *ads;
DEBUG(3,("ads: name_to_sid\n"));
ads = ads_cached_connection(domain);
if (!ads) {
domain->last_status = NT_STATUS_SERVER_DISABLED;
return NT_STATUS_UNSUCCESSFUL;
}
return ads_name_to_sid(ads, name, sid, type);
}
/* convert a sid to a user or group name */
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
char **name,
enum SID_NAME_USE *type)
{
ADS_STRUCT *ads = NULL;
DEBUG(3,("ads: sid_to_name\n"));
ads = ads_cached_connection(domain);
if (!ads) {
domain->last_status = NT_STATUS_SERVER_DISABLED;
return NT_STATUS_UNSUCCESSFUL;
}
return ads_sid_to_name(ads, mem_ctx, sid, name, type);
}
/* convert a DN to a name, SID and name type /* convert a DN to a name, SID and name type
this might become a major speed bottleneck if groups have this might become a major speed bottleneck if groups have
lots of users, in which case we could cache the results lots of users, in which case we could cache the results
@ -1004,8 +962,8 @@ struct winbindd_methods ads_methods = {
query_user_list, query_user_list,
enum_dom_groups, enum_dom_groups,
enum_local_groups, enum_local_groups,
name_to_sid, msrpc_name_to_sid,
sid_to_name, msrpc_sid_to_name,
query_user, query_user,
lookup_usergroups, lookup_usergroups,
lookup_groupmem, lookup_groupmem,

@ -595,7 +595,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...)
} }
static void wcache_save_name_to_sid(struct winbindd_domain *domain, static void wcache_save_name_to_sid(struct winbindd_domain *domain,
NTSTATUS status, NTSTATUS status, const char *domain_name,
const char *name, const DOM_SID *sid, const char *name, const DOM_SID *sid,
enum SID_NAME_USE type) enum SID_NAME_USE type)
{ {
@ -610,13 +610,13 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
centry_put_sid(centry, sid); centry_put_sid(centry, sid);
fstrcpy(uname, name); fstrcpy(uname, name);
strupper_m(uname); strupper_m(uname);
centry_end(centry, "NS/%s/%s", domain->name, uname); centry_end(centry, "NS/%s/%s", domain_name, uname);
DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string)); DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
centry_free(centry); centry_free(centry);
} }
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status,
const DOM_SID *sid, const char *name, enum SID_NAME_USE type) const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type)
{ {
struct cache_entry *centry; struct cache_entry *centry;
fstring sid_string; fstring sid_string;
@ -626,6 +626,7 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta
return; return;
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
centry_put_uint32(centry, type); centry_put_uint32(centry, type);
centry_put_string(centry, domain_name);
centry_put_string(centry, name); centry_put_string(centry, name);
} }
centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); centry_end(centry, "SN/%s", sid_to_string(sid_string, sid));
@ -743,10 +744,12 @@ do_query:
/* when the backend is consistent we can pre-prime some mappings */ /* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid(domain, NT_STATUS_OK, wcache_save_name_to_sid(domain, NT_STATUS_OK,
(*info)[i].acct_name, (*info)[i].acct_name,
domain->name,
(*info)[i].user_sid, (*info)[i].user_sid,
SID_NAME_USER); SID_NAME_USER);
wcache_save_sid_to_name(domain, NT_STATUS_OK, wcache_save_sid_to_name(domain, NT_STATUS_OK,
(*info)[i].user_sid, (*info)[i].user_sid,
domain->name,
(*info)[i].acct_name, (*info)[i].acct_name,
SID_NAME_USER); SID_NAME_USER);
wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]);
@ -918,6 +921,7 @@ skip_save:
/* convert a single name to a sid in a domain */ /* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain, static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
@ -933,7 +937,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
fstrcpy(uname, name); fstrcpy(uname, name);
strupper_m(uname); strupper_m(uname);
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
if (!centry) if (!centry)
goto do_query; goto do_query;
*type = (enum SID_NAME_USE)centry_uint32(centry); *type = (enum SID_NAME_USE)centry_uint32(centry);
@ -969,10 +973,10 @@ do_query:
DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n", DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n",
domain->name )); domain->name ));
status = domain->backend->name_to_sid(domain, mem_ctx, name, sid, type); status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
/* and save it */ /* and save it */
wcache_save_name_to_sid(domain, status, name, sid, *type); wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
/* We can't save the sid to name mapping as we don't know the /* We can't save the sid to name mapping as we don't know the
correct case of the name without looking it up */ correct case of the name without looking it up */
@ -985,6 +989,7 @@ do_query:
static NTSTATUS sid_to_name(struct winbindd_domain *domain, static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const DOM_SID *sid, const DOM_SID *sid,
char **domain_name,
char **name, char **name,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
@ -1001,6 +1006,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
goto do_query; goto do_query;
if (NT_STATUS_IS_OK(centry->status)) { if (NT_STATUS_IS_OK(centry->status)) {
*type = (enum SID_NAME_USE)centry_uint32(centry); *type = (enum SID_NAME_USE)centry_uint32(centry);
*domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx); *name = centry_string(centry, mem_ctx);
} }
status = centry->status; status = centry->status;
@ -1013,6 +1019,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
do_query: do_query:
*name = NULL; *name = NULL;
*domain_name = NULL;
/* If the seq number check indicated that there is a problem /* If the seq number check indicated that there is a problem
* with this DC, then return that status... except for * with this DC, then return that status... except for
@ -1028,12 +1035,12 @@ do_query:
DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n", DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n",
domain->name )); domain->name ));
status = domain->backend->sid_to_name(domain, mem_ctx, sid, name, type); status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
/* and save it */ /* and save it */
refresh_sequence_number(domain, False); refresh_sequence_number(domain, False);
wcache_save_sid_to_name(domain, status, sid, *name, *type); wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type);
wcache_save_name_to_sid(domain, status, *name, sid, *type); wcache_save_name_to_sid(domain, status, *domain_name, *name, sid, *type);
return status; return status;
} }

@ -77,6 +77,9 @@ struct winbindd_cm_conn {
static struct winbindd_cm_conn *cm_conns = NULL; static struct winbindd_cm_conn *cm_conns = NULL;
static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain,
const char *pipe_name,
struct winbindd_cm_conn **conn_out);
/* Choose between anonymous or authenticated connections. We need to use /* Choose between anonymous or authenticated connections. We need to use
an authenticated connection if DCs have the RestrictAnonymous registry an authenticated connection if DCs have the RestrictAnonymous registry
@ -133,6 +136,53 @@ static NTSTATUS setup_schannel(struct cli_state *cli)
return ret; return ret;
} }
static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
fstring dcname, struct in_addr *dc_ip)
{
struct winbindd_domain *our_domain;
NTSTATUS result;
struct winbindd_cm_conn *conn;
TALLOC_CTX *mem_ctx;
fstring tmp;
char *p;
if (IS_DC)
return False;
if (domain->primary)
return False;
if ((our_domain = find_our_domain()) == NULL)
return False;
result = get_connection_from_cache(our_domain, PIPE_NETLOGON, &conn);
if (!NT_STATUS_IS_OK(result))
return False;
if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
return False;
result = cli_netlogon_getdcname(conn->cli, mem_ctx, domain->name, tmp);
talloc_destroy(mem_ctx);
if (!NT_STATUS_IS_OK(result))
return False;
/* cli_netlogon_getdcname gives us a name with \\ */
p = tmp;
if (*p == '\\') p+=1;
if (*p == '\\') p+=1;
fstrcpy(dcname, p);
if (!resolve_name(dcname, dc_ip, 0x20))
return False;
return True;
}
/* Open a connction to the remote server, cache failures for 30 seconds */ /* Open a connction to the remote server, cache failures for 30 seconds */
static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index, static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index,
@ -148,15 +198,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
ZERO_STRUCT(dc_ip); ZERO_STRUCT(dc_ip);
fstrcpy(new_conn->domain, domain->name); fstrcpy(new_conn->domain, domain->name);
/* connection failure cache has been moved inside of get_dc_name
so we can deal with half dead DC's --jerry */
if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL, if (!get_dc_name_via_netlogon(domain, new_conn->controller, &dc_ip)) {
new_conn->controller, &dc_ip)) {
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; /* connection failure cache has been moved inside of
add_failed_connection_entry(domain->name, "", result); get_dc_name so we can deal with half dead DC's --jerry */
return result;
if (!get_dc_name(domain->name, domain->alt_name[0] ?
domain->alt_name : NULL,
new_conn->controller, &dc_ip)) {
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
add_failed_connection_entry(domain->name, "", result);
return result;
}
} }
/* Initialise SMB connection */ /* Initialise SMB connection */
@ -282,7 +336,7 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
failed. This allows existing setups to continue working, failed. This allows existing setups to continue working,
while solving the win2003 '100 user' limit for systems that while solving the win2003 '100 user' limit for systems that
are joined properly */ are joined properly */
if (NT_STATUS_IS_OK(result)) { if (NT_STATUS_IS_OK(result) && (domain->primary)) {
NTSTATUS status = setup_schannel(new_conn->cli); NTSTATUS status = setup_schannel(new_conn->cli);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("schannel refused - continuing without schannel (%s)\n", DEBUG(3,("schannel refused - continuing without schannel (%s)\n",
@ -461,10 +515,16 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
domain->native_mode = False; domain->native_mode = False;
domain->active_directory = False; domain->active_directory = False;
if (domain->internal) {
domain->initialized = True;
return;
}
if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
domain->name, nt_errstr(result))); domain->name, nt_errstr(result)));
domain->initialized = True;
return; return;
} }
@ -551,6 +611,8 @@ done:
cli_shutdown( conn.cli ); cli_shutdown( conn.cli );
talloc_destroy(mem_ctx); talloc_destroy(mem_ctx);
domain->initialized = True;
return; return;
} }

@ -292,7 +292,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
/* Get rid and name type from name */ /* Get rid and name type from name */
if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid, if (!winbindd_lookup_sid_by_name(domain, domain->name, name_group, &group_sid,
&name_type)) { &name_type)) {
DEBUG(1, ("group %s in domain %s does not exist\n", DEBUG(1, ("group %s in domain %s does not exist\n",
name_group, name_domain)); name_group, name_domain));
@ -446,17 +446,16 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
for (domain = domain_list(); domain != NULL; domain = domain->next) { for (domain = domain_list(); domain != NULL; domain = domain->next) {
struct getent_state *domain_state; struct getent_state *domain_state;
/* Create a state record for this domain */
/* don't add our domaina if we are a PDC or if we /* don't add our domaina if we are a PDC or if we
are a member of a Samba domain */ are a member of a Samba domain */
if ( (IS_DC || lp_winbind_trusted_domains_only()) if ( lp_winbind_trusted_domains_only() && domain->primary )
&& domain->primary )
{ {
continue; continue;
} }
/* Create a state record for this domain */
if ((domain_state = (struct getent_state *) if ((domain_state = (struct getent_state *)
malloc(sizeof(struct getent_state))) == NULL) { malloc(sizeof(struct getent_state))) == NULL) {
@ -945,12 +944,10 @@ static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0))) if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0)))
add_gid_to_array_unique(gid, gids, num); add_gid_to_array_unique(gid, gids, num);
/* Don't expand aliases if not explicitly activated -- for now */ /* Don't expand aliases if not explicitly activated -- for now
/* we don't support windows local nested groups if we are a DC.
refer to to sid_to_gid() in the smbd server code to see why
-- jerry */ -- jerry */
if (!lp_winbind_nested_groups() || IS_DC) if (!lp_winbind_nested_groups())
return; return;
/* Add nested group memberships */ /* Add nested group memberships */
@ -1021,7 +1018,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
/* Get rid and name type from name. The following costs 1 packet */ /* Get rid and name type from name. The following costs 1 packet */
if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid,
&name_type)) { &name_type)) {
DEBUG(1, ("user '%s' does not exist\n", name_user)); DEBUG(1, ("user '%s' does not exist\n", name_user));
goto done; goto done;

@ -52,6 +52,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
struct winbindd_domain *domain; struct winbindd_domain *domain;
int i; int i;
char *domain_name = NULL;
char *name = NULL; char *name = NULL;
enum SID_NAME_USE type; enum SID_NAME_USE type;
@ -72,7 +73,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
sid_copy(&dom_sid, sid); sid_copy(&dom_sid, sid);
sid_split_rid(&dom_sid, &rid); sid_split_rid(&dom_sid, &rid);
domain = find_domain_from_sid(&dom_sid); domain = find_lookup_domain_from_sid(sid);
if (domain == NULL) { if (domain == NULL) {
DEBUG(3, ("Could not find domain for sid %s\n", DEBUG(3, ("Could not find domain for sid %s\n",
@ -81,7 +82,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
} }
result = domain->methods->sid_to_name(domain, mem_ctx, sid, result = domain->methods->sid_to_name(domain, mem_ctx, sid,
&name, &type); &domain_name, &name, &type);
if (!NT_STATUS_IS_OK(result)) { if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("sid_to_name failed for sid %s\n", DEBUG(3, ("sid_to_name failed for sid %s\n",
@ -92,7 +93,7 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
DEBUG(10, ("Found name %s, type %d\n", name, type)); DEBUG(10, ("Found name %s, type %d\n", name, type));
if (type == SID_NAME_USER) { if (type == SID_NAME_USER) {
add_member(domain->name, name, members, num_members); add_member(domain_name, name, members, num_members);
goto done; goto done;
} }
@ -102,7 +103,15 @@ add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
goto done; goto done;
} }
/* Expand the domain group */ /* Expand the domain group, this must be done via the target domain */
domain = find_domain_from_sid(sid);
if (domain == NULL) {
DEBUG(3, ("Could not find domain from SID %s\n",
sid_string_static(sid)));
goto done;
}
result = domain->methods->lookup_groupmem(domain, mem_ctx, result = domain->methods->lookup_groupmem(domain, mem_ctx,
sid, &num_names, sid, &num_names,
@ -221,6 +230,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
/* convert a single name to a sid in a domain */ /* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain, static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
@ -240,6 +250,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
static NTSTATUS sid_to_name(struct winbindd_domain *domain, static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const DOM_SID *sid, const DOM_SID *sid,
char **domain_name,
char **name, char **name,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
@ -250,6 +261,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
if (!pdb_get_aliasinfo(sid, &info)) if (!pdb_get_aliasinfo(sid, &info))
return NT_STATUS_NONE_MAPPED; return NT_STATUS_NONE_MAPPED;
*domain_name = talloc_strdup(mem_ctx, domain->name);
*name = talloc_strdup(mem_ctx, info.acct_name); *name = talloc_strdup(mem_ctx, info.acct_name);
*type = SID_NAME_ALIAS; *type = SID_NAME_ALIAS;
@ -300,7 +312,45 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
char ***alt_names, char ***alt_names,
DOM_SID **dom_sids) DOM_SID **dom_sids)
{ {
return NT_STATUS_OK; NTSTATUS nt_status;
int enum_ctx = 0;
int num_sec_domains;
TRUSTDOM **domains;
*num_domains = 0;
*names = NULL;
*alt_names = NULL;
*dom_sids = NULL;
do {
int i;
nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1,
&num_sec_domains,
&domains);
*names = talloc_realloc(mem_ctx, *names,
sizeof(*names) *
(num_sec_domains + *num_domains));
*alt_names = talloc_realloc(mem_ctx, *alt_names,
sizeof(*alt_names) *
(num_sec_domains + *num_domains));
*dom_sids = talloc_realloc(mem_ctx, *dom_sids,
sizeof(**dom_sids) *
(num_sec_domains + *num_domains));
for (i=0; i< num_sec_domains; i++) {
if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains],
domains[i]->name) == -1) {
return NT_STATUS_NO_MEMORY;
}
(*alt_names)[*num_domains] = NULL;
(*dom_sids)[*num_domains] = domains[i]->sid;
(*num_domains)++;
}
} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
return NT_STATUS_OK;
}
return nt_status;
} }
/* find the domain sid for a domain */ /* find the domain sid for a domain */

@ -274,8 +274,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
} }
/* convert a single name to a sid in a domain */ /* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain, NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
@ -289,14 +290,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
DEBUG(3,("rpc: name_to_sid name=%s\n", name)); DEBUG(3,("rpc: name_to_sid name=%s\n", name));
full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name); full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
if (!full_name) { if (!full_name) {
DEBUG(0, ("talloc_asprintf failed!\n")); DEBUG(0, ("talloc_asprintf failed!\n"));
return NT_STATUS_NO_MEMORY; return NT_STATUS_NO_MEMORY;
} }
DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name )); DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
retry = 0; retry = 0;
do { do {
@ -322,9 +323,10 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
/* /*
convert a domain SID to a user or group name convert a domain SID to a user or group name
*/ */
static NTSTATUS sid_to_name(struct winbindd_domain *domain, NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
const DOM_SID *sid, const DOM_SID *sid,
char **domain_name,
char **name, char **name,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
@ -350,14 +352,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
if (NT_STATUS_IS_OK(result)) { if (NT_STATUS_IS_OK(result)) {
*type = (enum SID_NAME_USE)types[0]; *type = (enum SID_NAME_USE)types[0];
*domain_name = domains[0];
*name = names[0]; *name = names[0];
DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
/* Paranoia */
if (!strequal(domain->name, domains[0])) {
DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
return NT_STATUS_UNSUCCESSFUL;
}
} }
return result; return result;
@ -995,8 +992,8 @@ struct winbindd_methods msrpc_methods = {
query_user_list, query_user_list,
enum_dom_groups, enum_dom_groups,
enum_local_groups, enum_local_groups,
name_to_sid, msrpc_name_to_sid,
sid_to_name, msrpc_sid_to_name,
query_user, query_user,
lookup_usergroups, lookup_usergroups,
lookup_groupmem, lookup_groupmem,

@ -95,14 +95,14 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
name_domain, lp_winbind_separator(), name_user)); name_domain, lp_winbind_separator(), name_user));
if ((domain = find_domain_from_name(name_domain)) == NULL) { if ((domain = find_lookup_domain_from_name(name_domain)) == NULL) {
DEBUG(0, ("could not find domain entry for domain %s\n", DEBUG(0, ("could not find domain entry for domain %s\n",
name_domain)); name_domain));
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
/* Lookup name from PDC using lsa_lookup_names() */ /* Lookup name from PDC using lsa_lookup_names() */
if (!winbindd_lookup_sid_by_name(domain, name_user, &sid, &type)) { if (!winbindd_lookup_sid_by_name(domain, name_domain, name_user, &sid, &type)) {
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
@ -335,7 +335,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
if ( !winbindd_lookup_sid_by_name(domain, pw->pw_name, &sid, &type) ) if ( !winbindd_lookup_sid_by_name(domain, domain->name, pw->pw_name, &sid, &type) )
return WINBINDD_ERROR; return WINBINDD_ERROR;
if ( type != SID_NAME_USER ) if ( type != SID_NAME_USER )
@ -405,7 +405,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
if ( !winbindd_lookup_sid_by_name(domain, grp->gr_name, &sid, &type) ) if ( !winbindd_lookup_sid_by_name(domain, domain->name, grp->gr_name, &sid, &type) )
return WINBINDD_ERROR; return WINBINDD_ERROR;
if ( type!=SID_NAME_DOM_GRP && type!=SID_NAME_ALIAS ) if ( type!=SID_NAME_DOM_GRP && type!=SID_NAME_ALIAS )

@ -153,7 +153,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* Get rid and name type from name */ /* Get rid and name type from name */
if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) { if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid, &name_type)) {
DEBUG(1, ("user '%s' does not exist\n", name_user)); DEBUG(1, ("user '%s' does not exist\n", name_user));
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }

@ -85,13 +85,15 @@ void free_domain_list(void)
static BOOL is_internal_domain(const DOM_SID *sid) static BOOL is_internal_domain(const DOM_SID *sid)
{ {
DOM_SID tmp_sid; extern DOM_SID global_sid_Builtin;
if (sid_equal(sid, get_global_sam_sid())) if (sid == NULL)
return False;
if (sid_compare_domain(sid, get_global_sam_sid()) == 0)
return True; return True;
string_to_sid(&tmp_sid, "S-1-5-32"); if (sid_compare_domain(sid, &global_sid_Builtin) == 0)
if (sid_equal(sid, &tmp_sid))
return True; return True;
return False; return False;
@ -160,15 +162,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
domain->internal = is_internal_domain(sid); domain->internal = is_internal_domain(sid);
domain->sequence_number = DOM_SEQUENCE_NONE; domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0; domain->last_seq_check = 0;
domain->initialized = False;
if (sid) { if (sid) {
sid_copy(&domain->sid, sid); sid_copy(&domain->sid, sid);
} }
/* set flags about native_mode, active_directory */
if (!domain->internal)
set_dc_type_and_flags( domain );
DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
domain->active_directory ? "ADS" : "NT4", domain->active_directory ? "ADS" : "NT4",
domain->native_mode ? "native mode" : domain->native_mode ? "native mode" :
@ -190,6 +188,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
static void add_trusted_domains( struct winbindd_domain *domain ) static void add_trusted_domains( struct winbindd_domain *domain )
{ {
extern struct winbindd_methods cache_methods;
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
NTSTATUS result; NTSTATUS result;
time_t t; time_t t;
@ -226,7 +225,7 @@ static void add_trusted_domains( struct winbindd_domain *domain )
for(i = 0; i < num_domains; i++) { for(i = 0; i < num_domains; i++) {
DEBUG(10,("Found domain %s\n", names[i])); DEBUG(10,("Found domain %s\n", names[i]));
add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
domain->methods, &dom_sids[i]); &cache_methods, &dom_sids[i]);
/* if the SID was empty, we better set it now */ /* if the SID was empty, we better set it now */
@ -290,16 +289,28 @@ void rescan_trusted_domains( void )
/* Look up global info for the winbind daemon */ /* Look up global info for the winbind daemon */
BOOL init_domain_list(void) BOOL init_domain_list(void)
{ {
extern DOM_SID global_sid_Builtin;
extern struct winbindd_methods cache_methods; extern struct winbindd_methods cache_methods;
extern struct winbindd_methods passdb_methods;
struct winbindd_domain *domain; struct winbindd_domain *domain;
/* Free existing list */ /* Free existing list */
free_domain_list(); free_domain_list();
/* Add ourselves as the first entry. */ /* Add ourselves as the first entry. */
if (IS_DC) {
domain = add_trusted_domain(get_global_sam_name(), NULL,
&passdb_methods, get_global_sam_sid());
} else {
domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL); domain = add_trusted_domain( lp_workgroup(), lp_realm(),
&cache_methods, NULL);
/* set flags about native_mode, active_directory */
set_dc_type_and_flags(domain);
}
domain->primary = True; domain->primary = True;
/* get any alternate name for the primary domain */ /* get any alternate name for the primary domain */
@ -320,27 +331,15 @@ BOOL init_domain_list(void)
/* do an initial scan for trusted domains */ /* do an initial scan for trusted domains */
add_trusted_domains(domain); add_trusted_domains(domain);
/* Don't expand aliases if not explicitly activated -- for now */
/* we don't support windows local nested groups if we are a DC.
refer to to sid_to_gid() in the smbd server code to see why
-- jerry */
/* Add our local SAM domains */
if (lp_winbind_nested_groups() || IS_DC) { add_trusted_domain("BUILTIN", NULL, &passdb_methods,
&global_sid_Builtin);
/* Add our local SAM domains */ if (!IS_DC) {
DOM_SID sid; add_trusted_domain(get_global_sam_name(), NULL,
extern struct winbindd_methods passdb_methods; &passdb_methods, get_global_sam_sid());
struct winbindd_domain *dom;
string_to_sid(&sid, "S-1-5-32");
dom = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
&sid);
dom = add_trusted_domain(get_global_sam_name(), NULL,
&passdb_methods,
get_global_sam_sid());
} }
/* avoid rescanning this right away */ /* avoid rescanning this right away */
@ -369,6 +368,9 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name)
for (domain = domain_list(); domain != NULL; domain = domain->next) { for (domain = domain_list(); domain != NULL; domain = domain->next) {
if (strequal(domain_name, domain->name) || if (strequal(domain_name, domain->name) ||
(domain->alt_name[0] && strequal(domain_name, domain->alt_name))) { (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) {
if (!domain->initialized)
set_dc_type_and_flags(domain);
return domain; return domain;
} }
} }
@ -387,8 +389,11 @@ struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
/* Search through list */ /* Search through list */
for (domain = domain_list(); domain != NULL; domain = domain->next) { for (domain = domain_list(); domain != NULL; domain = domain->next) {
if (sid_compare_domain(sid, &domain->sid) == 0) if (sid_compare_domain(sid, &domain->sid) == 0) {
if (!domain->initialized)
set_dc_type_and_flags(domain);
return domain; return domain;
}
} }
/* Not found */ /* Not found */
@ -414,21 +419,49 @@ struct winbindd_domain *find_our_domain(void)
return NULL; return NULL;
} }
/* Find the appropriate domain to lookup a name or SID */
struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
{
/* A DC can't ask the local smbd for remote SIDs, here winbindd is the
* one to contact the external DC's. On member servers the internal
* domains are different: These are part of the local SAM. */
if (IS_DC || is_internal_domain(sid))
return find_domain_from_sid(sid);
/* On a member server a query for SID or name can always go to our
* primary DC. */
return find_our_domain();
}
struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
{
if (IS_DC || strequal(domain_name, "BUILTIN") ||
strequal(domain_name, get_global_sam_name()))
return find_domain_from_name(domain_name);
return find_our_domain();
}
/* Lookup a sid in a domain from a name */ /* Lookup a sid in a domain from a name */
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
const char *domain_name,
const char *name, DOM_SID *sid, const char *name, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
NTSTATUS result; NTSTATUS result;
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); mem_ctx = talloc_init("lookup_sid_by_name for %s\\%s\n",
domain_name, name);
if (!mem_ctx) if (!mem_ctx)
return False; return False;
/* Lookup name */ /* Lookup name */
result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type); result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
talloc_destroy(mem_ctx); talloc_destroy(mem_ctx);
@ -457,12 +490,13 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
char *names; char *names;
char *dom_names;
NTSTATUS result; NTSTATUS result;
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
BOOL rv = False; BOOL rv = False;
struct winbindd_domain *domain; struct winbindd_domain *domain;
domain = find_domain_from_sid(sid); domain = find_lookup_domain_from_sid(sid);
if (!domain) { if (!domain) {
DEBUG(1,("Can't find domain from sid\n")); DEBUG(1,("Can't find domain from sid\n"));
@ -474,12 +508,12 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid"))) if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid")))
return False; return False;
result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type); result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type);
/* Return name and type if successful */ /* Return name and type if successful */
if ((rv = NT_STATUS_IS_OK(result))) { if ((rv = NT_STATUS_IS_OK(result))) {
fstrcpy(dom_name, domain->name); fstrcpy(dom_name, dom_names);
fstrcpy(name, names); fstrcpy(name, names);
} else { } else {
*type = SID_NAME_UNKNOWN; *type = SID_NAME_UNKNOWN;