1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-02 00:22:11 +03:00

Merge HEAD's winbind into 3.0.

This includes the 'SIDs Rule' patch, mimir's trusted domains cacheing code,
the winbind_idmap abstraction (not idmap proper, but the stuff that held up
the winbind LDAP backend in HEAD).

Andrew Bartlett
(This used to be commit d4d5e6c2ee)
This commit is contained in:
Andrew Bartlett
2003-04-23 11:54:56 +00:00
parent 656d2c75c9
commit 1a9394195d
16 changed files with 729 additions and 931 deletions

View File

@ -218,6 +218,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \ libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
libsmb/passchange.o libsmb/doserr.o \ libsmb/passchange.o libsmb/doserr.o \
libsmb/trustdom_cache.o \
$(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
@ -227,7 +228,7 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \
rpc_client/cli_ds.o rpc_client/cli_echo.o libsmb/namequery_dc.o rpc_client/cli_ds.o rpc_client/cli_echo.o libsmb/namequery_dc.o
LIBMSRPC_SERVER_OBJ = libsmb/trust_passwd.o LIBMSRPC_SERVER_OBJ = libsmb/trusts_util.o
REGOBJS_OBJ = registry/reg_objects.o REGOBJS_OBJ = registry/reg_objects.o
REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \
@ -277,8 +278,8 @@ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
passdb/machine_sid.o passdb/util_sam_sid.o \ passdb/machine_sid.o passdb/util_sam_sid.o passdb/pdb_compat.o \
passdb/pdb_compat.o @PDB_STATIC@ @PDB_STATIC@
XML_OBJ = passdb/pdb_xml.o XML_OBJ = passdb/pdb_xml.o
MYSQL_OBJ = passdb/pdb_mysql.o MYSQL_OBJ = passdb/pdb_mysql.o
@ -574,6 +575,7 @@ WINBINDD_OBJ1 = \
nsswitch/winbindd_user.o \ nsswitch/winbindd_user.o \
nsswitch/winbindd_group.o \ nsswitch/winbindd_group.o \
nsswitch/winbindd_idmap.o \ nsswitch/winbindd_idmap.o \
nsswitch/winbindd_idmap_tdb.o \
nsswitch/winbindd_util.o \ nsswitch/winbindd_util.o \
nsswitch/winbindd_cache.o \ nsswitch/winbindd_cache.o \
nsswitch/winbindd_pam.o \ nsswitch/winbindd_pam.o \
@ -589,8 +591,8 @@ WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_GET_SET_OBJ) \ $(WINBINDD_OBJ1) $(PASSDB_GET_SET_OBJ) \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
$(PROFILE_OBJ) $(UNIGRP_OBJ) $(POPT_LIB_OBJ) \ $(PROFILE_OBJ) $(UNIGRP_OBJ) $(IDMAP_OBJ) \
$(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o $(POPT_LIB_OBJ) WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o $(POPT_LIB_OBJ)
@ -608,7 +610,8 @@ NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(POPT_LIB_O
###################################################################### ######################################################################
# now the rules... # now the rules...
###################################################################### ######################################################################
all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) $(MODULES) @EXTRA_ALL_TARGETS@ all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \
$(MODULES) @EXTRA_ALL_TARGETS@
pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@ pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@
@ -638,7 +641,7 @@ smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@
talloctort : SHOWFLAGS bin/talloctort@EXEEXT@ talloctort : SHOWFLAGS bin/talloctort@EXEEXT@
nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ nsswitch/libnss_winbind.@SHLIBEXT@ nsswitch/pam_winbind.@SHLIBEXT@ nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ nsswitch/@WINBIND_NSS@.@SHLIBEXT@ nsswitch/pam_winbind.@SHLIBEXT@
wins : SHOWFLAGS nsswitch/libnss_wins.@SHLIBEXT@ wins : SHOWFLAGS nsswitch/libnss_wins.@SHLIBEXT@

View File

@ -630,3 +630,21 @@ void print_guid(GUID *guid)
d_printf("%02x", guid->info[i]); d_printf("%02x", guid->info[i]);
d_printf("\n"); d_printf("\n");
} }
/*******************************************************************
Tallocs a duplicate SID.
********************************************************************/
DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
{
DOM_SID *dst;
if(!src)
return NULL;
if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
sid_copy( dst, src);
}
return dst;
}

View File

@ -22,6 +22,7 @@
*/ */
#include "includes.h" #include "includes.h"
#define UNIGROUP_PREFIX "UNIGROUP"
/* /*
Handle for netlogon_unigrp.tdb database. It is used internally Handle for netlogon_unigrp.tdb database. It is used internally
@ -50,17 +51,22 @@ BOOL uni_group_cache_init(void)
BOOL uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user) BOOL uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
{ {
TDB_DATA key,data; TDB_DATA key,data;
fstring keystr; fstring keystr, sid_string;
int i; DOM_SID user_sid;
unsigned int i;
if (!uni_group_cache_init()) { if (!uni_group_cache_init()) {
DEBUG(0,("uni_group_cache_store_netlogon: cannot open netlogon_unigrp.tdb for write!\n")); DEBUG(0,("uni_group_cache_store_netlogon: cannot open netlogon_unigrp.tdb for write!\n"));
return False; return False;
} }
/* Prepare key as DOMAIN-SID/USER-RID string */ sid_copy(&user_sid, &user->dom_sid.sid);
slprintf(keystr, sizeof(keystr), "%s/%d", sid_append_rid(&user_sid, user->user_rid);
sid_string_static(&user->dom_sid.sid), user->user_rid);
/* Prepare key as USER-SID string */
slprintf(keystr, sizeof(keystr), "%s/%s",
UNIGROUP_PREFIX,
sid_to_string(sid_string, &user_sid));
key.dptr = keystr; key.dptr = keystr;
key.dsize = strlen(keystr) + 1; key.dsize = strlen(keystr) + 1;
@ -90,14 +96,15 @@ BOOL uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
and elements are array[0] ... array[num_elements-1] and elements are array[0] ... array[num_elements-1]
*/ */
uint32* uni_group_cache_fetch(DOM_SID *domain, uint32 user_rid, DOM_SID **uni_group_cache_fetch(DOM_SID *domain, DOM_SID *user_sid,
TALLOC_CTX *mem_ctx, uint32 *num_groups) TALLOC_CTX *mem_ctx, uint32 *num_groups)
{ {
TDB_DATA key,data; TDB_DATA key,data;
fstring keystr; fstring keystr;
uint32 *groups; DOM_SID **groups;
uint32 i; uint32 i;
uint32 group_count; uint32 group_count;
fstring sid_string;
if (!domain) { if (!domain) {
DEBUG(1,("uni_group_cache_fetch: expected non-null domain sid\n")); DEBUG(1,("uni_group_cache_fetch: expected non-null domain sid\n"));
@ -123,8 +130,9 @@ uint32* uni_group_cache_fetch(DOM_SID *domain, uint32 user_rid,
*num_groups = 0; *num_groups = 0;
/* Fetch universal groups */ /* Fetch universal groups */
slprintf(keystr, sizeof(keystr), "%s/%d", slprintf(keystr, sizeof(keystr), "%s/%s",
sid_string_static(domain), user_rid); UNIGROUP_PREFIX,
sid_to_string(sid_string, user_sid));
key.dptr = keystr; key.dptr = keystr;
key.dsize = strlen(keystr) + 1; key.dsize = strlen(keystr) + 1;
data = tdb_fetch(netlogon_unigrp_tdb, key); data = tdb_fetch(netlogon_unigrp_tdb, key);
@ -136,12 +144,17 @@ uint32* uni_group_cache_fetch(DOM_SID *domain, uint32 user_rid,
/* Transfer data to receiver's memory context */ /* Transfer data to receiver's memory context */
group_count = IVAL(&((uint32*)data.dptr)[0],0); group_count = IVAL(&((uint32*)data.dptr)[0],0);
groups = talloc(mem_ctx, (group_count)*sizeof(uint32)); groups = talloc(mem_ctx, (group_count)*sizeof(*groups));
if (groups) { if (groups) {
for(i=0; i<group_count; i++) { for(i=0; i<group_count; i++) {
groups[i] = IVAL(&((uint32*)data.dptr)[i+1],0); groups[i] = talloc(mem_ctx, sizeof(**groups));
if (!groups[i]) {
DEBUG(1,("uni_group_cache_fetch: cannot allocate uni groups in receiver's memory context\n"));
return NULL;
}
sid_copy(groups[i], domain);
sid_append_rid(groups[i], IVAL(&((uint32*)data.dptr)[i+1],0));
} }
} else { } else {
DEBUG(1,("uni_group_cache_fetch: cannot allocate uni groups in receiver's memory context\n")); DEBUG(1,("uni_group_cache_fetch: cannot allocate uni groups in receiver's memory context\n"));
} }

View File

@ -1,124 +0,0 @@
/*
* Unix SMB/CIFS implementation.
* Routines to operate on various trust relationships
* Copyright (C) Andrew Bartlett 2001
*
* 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"
/*********************************************************
Change the domain password on the PDC.
Just changes the password betwen the two values specified.
Caller must have the cli connected to the netlogon pipe
already.
**********************************************************/
static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx,
unsigned char orig_trust_passwd_hash[16],
unsigned char new_trust_passwd_hash[16],
uint32 sec_channel_type)
{
NTSTATUS result;
uint32 neg_flags = 0x000001ff;
result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",
nt_errstr(result)));
return result;
}
result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
nt_errstr(result)));
}
return result;
}
/*********************************************************
Change the domain password on the PDC.
Store the password ourselves, but use the supplied password
Caller must have already setup the connection to the NETLOGON pipe
**********************************************************/
NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx,
const char *domain,
unsigned char orig_trust_passwd_hash[16],
uint32 sec_channel_type)
{
unsigned char new_trust_passwd_hash[16];
char *new_trust_passwd;
char *str;
NTSTATUS nt_status;
/* Create a random machine account password */
str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_trust_passwd = talloc_strdup(mem_ctx, str);
E_md4hash(new_trust_passwd, new_trust_passwd_hash);
nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
new_trust_passwd_hash, sec_channel_type);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
timestring(False)));
/*
* Return the result of trying to write the new password
* back into the trust account file.
*/
if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
nt_status = NT_STATUS_UNSUCCESSFUL;
}
}
return nt_status;
}
/*********************************************************
Change the domain password on the PDC.
Do most of the legwork ourselfs. Caller must have
already setup the connection to the NETLOGON pipe
**********************************************************/
NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli,
TALLOC_CTX *mem_ctx,
const char *domain)
{
unsigned char old_trust_passwd_hash[16];
char *up_domain;
uint32 sec_channel_type = 0;
up_domain = talloc_strdup(mem_ctx, domain);
if (!secrets_fetch_trust_account_password(domain,
old_trust_passwd_hash,
NULL, &sec_channel_type)) {
DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
return NT_STATUS_UNSUCCESSFUL;
}
return trust_pw_change_and_store_it(cli, mem_ctx, domain,
old_trust_passwd_hash,
sec_channel_type);
}

View File

@ -895,12 +895,13 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
poptFreeContext(pc); poptFreeContext(pc);
register_msg_pool_usage();
/* Loop waiting for requests */ /* Loop waiting for requests */
process_loop(); process_loop();
trustdom_cache_shutdown();
uni_group_cache_shutdown(); uni_group_cache_shutdown();
return 0; return 0;
} }

View File

@ -4,6 +4,7 @@
Winbind daemon for ntdom nss module Winbind daemon for ntdom nss module
Copyright (C) Tim Potter 2000 Copyright (C) Tim Potter 2000
Copyright (C) Anthony Liguori 2003
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
@ -65,7 +66,8 @@ struct getent_state {
struct getpwent_user { struct getpwent_user {
fstring name; /* Account name */ fstring name; /* Account name */
fstring gecos; /* User information */ fstring gecos; /* User information */
uint32 user_rid, group_rid; /* NT user and group rids */ DOM_SID user_sid; /* NT user and primary group SIDs */
DOM_SID group_sid;
}; };
/* Server state structure */ /* Server state structure */
@ -83,8 +85,8 @@ extern struct winbindd_state server_state; /* Server information */
typedef struct { typedef struct {
char *acct_name; char *acct_name;
char *full_name; char *full_name;
uint32 user_rid; DOM_SID *user_sid; /* NT user and primary group SIDs */
uint32 group_rid; /* primary group */ DOM_SID *group_sid;
} WINBIND_USERINFO; } WINBIND_USERINFO;
/* Structures to hold per domain information */ /* Structures to hold per domain information */
@ -140,6 +142,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,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type); enum SID_NAME_USE *type);
@ -151,10 +154,10 @@ struct winbindd_methods {
char **name, char **name,
enum SID_NAME_USE *type); enum SID_NAME_USE *type);
/* lookup user info for a given rid */ /* lookup user info for a given SID */
NTSTATUS (*query_user)(struct winbindd_domain *domain, NTSTATUS (*query_user)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
WINBIND_USERINFO *user_info); WINBIND_USERINFO *user_info);
/* lookup all groups that a user is a member of. The backend /* lookup all groups that a user is a member of. The backend
@ -162,14 +165,15 @@ struct winbindd_methods {
function */ function */
NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
uint32 *num_groups, uint32 **user_gids); uint32 *num_groups, DOM_SID ***user_gids);
/* find all members of the group with the specified group_rid */ /* find all members of the group with the specified group_rid */
NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 group_rid, uint32 *num_names, DOM_SID *group_sid,
uint32 **rid_mem, char ***names, uint32 *num_names,
DOM_SID ***sid_mem, char ***names,
uint32 **name_types); uint32 **name_types);
/* return the current global sequence number */ /* return the current global sequence number */
@ -198,6 +202,23 @@ typedef struct {
POLICY_HND pol; POLICY_HND pol;
} CLI_POLICY_HND; } CLI_POLICY_HND;
/* Filled out by IDMAP backends */
struct winbindd_idmap_methods {
/* Called when backend is first loaded */
BOOL (*init)(void);
BOOL (*get_sid_from_uid)(uid_t uid, DOM_SID *sid);
BOOL (*get_sid_from_gid)(gid_t gid, DOM_SID *sid);
BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid);
BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid);
/* Called when backend is unloaded */
BOOL (*close)(void);
/* Called to dump backend status */
void (*status)(void);
};
#include "winbindd_proto.h" #include "winbindd_proto.h"
#include "rpc_parse.h" #include "rpc_parse.h"

View File

@ -4,6 +4,7 @@
Winbind ADS backend functions Winbind ADS backend functions
Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Tridgell 2001
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -88,13 +89,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
return ads; return ads;
} }
/* useful utility */
static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *sid)
{
sid_copy(sid, &domain->sid);
sid_append_rid(sid, rid);
}
/* Query display info for a realm. This is the basic user list fn */ /* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain, static NTSTATUS query_user_list(struct winbindd_domain *domain,
@ -143,7 +137,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
char *name, *gecos; char *name, *gecos;
DOM_SID sid; DOM_SID sid;
uint32 rid, group; DOM_SID *sid2;
DOM_SID *group_sid;
uint32 group;
uint32 atype; uint32 atype;
if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
@ -163,15 +159,20 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
continue; continue;
} }
if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { sid2 = talloc(mem_ctx, sizeof(*sid2));
DEBUG(1,("No rid for %s !?\n", name)); if (!sid2) {
continue; status = NT_STATUS_NO_MEMORY;
goto done;
} }
sid_copy(sid2, &sid);
group_sid = rid_to_talloced_sid(domain, mem_ctx, group);
(*info)[i].acct_name = name; (*info)[i].acct_name = name;
(*info)[i].full_name = gecos; (*info)[i].full_name = gecos;
(*info)[i].user_rid = rid; (*info)[i].user_sid = sid2;
(*info)[i].group_rid = group; (*info)[i].group_sid = group_sid;
i++; i++;
} }
@ -296,6 +297,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,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
@ -328,13 +330,13 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
} }
/* convert a DN to a name, rid 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
*/ */
static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
const char *dn, const char *dn,
char **name, uint32 *name_type, uint32 *rid) char **name, uint32 *name_type, DOM_SID *sid)
{ {
char *exp; char *exp;
void *res = NULL; void *res = NULL;
@ -342,7 +344,6 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
"objectSid", "sAMAccountType", NULL}; "objectSid", "sAMAccountType", NULL};
ADS_STATUS rc; ADS_STATUS rc;
uint32 atype; uint32 atype;
DOM_SID sid;
char *escaped_dn = escape_ldap_string_alloc(dn); char *escaped_dn = escape_ldap_string_alloc(dn);
if (!escaped_dn) { if (!escaped_dn) {
@ -365,8 +366,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
} }
(*name_type) = ads_atype_map(atype); (*name_type) = ads_atype_map(atype);
if (!ads_pull_sid(ads, res, "objectSid", &sid) || if (!ads_pull_sid(ads, res, "objectSid", sid)) {
!sid_peek_rid(&sid, rid)) {
goto failed; goto failed;
} }
@ -381,60 +381,63 @@ failed:
/* Lookup user information from a rid */ /* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *sid,
WINBIND_USERINFO *info) WINBIND_USERINFO *info)
{ {
ADS_STRUCT *ads = NULL; ADS_STRUCT *ads = NULL;
const char *attrs[] = {"userPrincipalName", const char *attrs[] = {"userPrincipalName",
"sAMAccountName", "sAMAccountName",
"name", "objectSid", "name",
"primaryGroupID", NULL}; "primaryGroupID", NULL};
ADS_STATUS rc; ADS_STATUS rc;
int count; int count;
void *msg = NULL; void *msg = NULL;
char *exp; char *exp;
DOM_SID sid;
char *sidstr; char *sidstr;
uint32 group_rid;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
DOM_SID *sid2;
fstring sid_string;
DEBUG(3,("ads: query_user\n")); DEBUG(3,("ads: query_user\n"));
sid_from_rid(domain, user_rid, &sid);
ads = ads_cached_connection(domain); ads = ads_cached_connection(domain);
if (!ads) goto done; if (!ads) goto done;
sidstr = sid_binstring(&sid); sidstr = sid_binstring(sid);
asprintf(&exp, "(objectSid=%s)", sidstr); asprintf(&exp, "(objectSid=%s)", sidstr);
rc = ads_search_retry(ads, &msg, exp, attrs); rc = ads_search_retry(ads, &msg, exp, attrs);
free(exp); free(exp);
free(sidstr); free(sidstr);
if (!ADS_ERR_OK(rc)) { if (!ADS_ERR_OK(rc)) {
DEBUG(1,("query_user(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc)));
goto done; goto done;
} }
count = ads_count_replies(ads, msg); count = ads_count_replies(ads, msg);
if (count != 1) { if (count != 1) {
DEBUG(1,("query_user(rid=%d): Not found\n", user_rid)); DEBUG(1,("query_user(sid=%s): Not found\n", sid_to_string(sid_string, sid)));
goto done; goto done;
} }
info->acct_name = ads_pull_username(ads, mem_ctx, msg); info->acct_name = ads_pull_username(ads, mem_ctx, msg);
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
DEBUG(1,("No sid for %d !?\n", user_rid)); if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
goto done; DEBUG(1,("No primary group for %s !?\n", sid_to_string(sid_string, sid)));
}
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &info->group_rid)) {
DEBUG(1,("No primary group for %d !?\n", user_rid));
goto done; goto done;
} }
if (!sid_peek_check_rid(&domain->sid,&sid, &info->user_rid)) { sid2 = talloc(mem_ctx, sizeof(*sid2));
DEBUG(1,("No rid for %d !?\n", user_rid)); if (!sid2) {
status = NT_STATUS_NO_MEMORY;
goto done; goto done;
} }
sid_copy(sid2, sid);
info->user_sid = sid2;
info->group_sid = rid_to_talloced_sid(domain, mem_ctx, group_rid);
status = NT_STATUS_OK; status = NT_STATUS_OK;
@ -445,12 +448,91 @@ done:
return status; return status;
} }
/* Lookup groups a user is a member of - alternate method, for when
tokenGroups are not available. */
static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const char *user_dn,
DOM_SID *primary_group,
uint32 *num_groups, DOM_SID ***user_gids)
{
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
int count;
void *res = NULL;
void *msg = NULL;
char *exp;
ADS_STRUCT *ads;
const char *group_attrs[] = {"objectSid", NULL};
ads = ads_cached_connection(domain);
if (!ads) goto done;
/* buggy server, no tokenGroups. Instead lookup what groups this user
is a member of by DN search on member*/
if (asprintf(&exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) {
DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
return NT_STATUS_NO_MEMORY;
}
rc = ads_search_retry(ads, &res, exp, group_attrs);
free(exp);
if (!ADS_ERR_OK(rc)) {
DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
return ads_ntstatus(rc);
}
count = ads_count_replies(ads, res);
if (count == 0) {
DEBUG(5,("lookup_usergroups: No supp groups found\n"));
status = ads_ntstatus(rc);
goto done;
}
(*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1));
(*user_gids)[0] = primary_group;
*num_groups = 1;
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
DOM_SID group_sid;
if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
DEBUG(1,("No sid for this group ?!?\n"));
continue;
}
if (sid_equal(&group_sid, primary_group)) continue;
(*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids));
if (!(*user_gids)[*num_groups]) {
status = NT_STATUS_NO_MEMORY;
goto done;
}
sid_copy((*user_gids)[*num_groups], &group_sid);
(*num_groups)++;
}
status = NT_STATUS_OK;
DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn));
done:
if (res) ads_msgfree(ads, res);
if (msg) ads_msgfree(ads, msg);
return status;
}
/* Lookup groups a user is a member of. */ /* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *sid,
uint32 *num_groups, uint32 **user_gids) uint32 *num_groups, DOM_SID ***user_gids)
{ {
ADS_STRUCT *ads = NULL; ADS_STRUCT *ads = NULL;
const char *attrs[] = {"distinguishedName", NULL}; const char *attrs[] = {"distinguishedName", NULL};
@ -462,63 +544,94 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
char *user_dn; char *user_dn;
DOM_SID *sids; DOM_SID *sids;
int i; int i;
uint32 primary_group; DOM_SID *primary_group;
DOM_SID sid; uint32 primary_group_rid;
char *sidstr; char *sidstr;
fstring sid_string;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
*num_groups = 0;
DEBUG(3,("ads: lookup_usergroups\n")); DEBUG(3,("ads: lookup_usergroups\n"));
*num_groups = 0;
(*num_groups) = 0;
sid_from_rid(domain, user_rid, &sid);
ads = ads_cached_connection(domain); ads = ads_cached_connection(domain);
if (!ads) goto done; if (!ads) goto done;
sidstr = sid_binstring(&sid); if (!(sidstr = sid_binstring(sid))) {
asprintf(&exp, "(objectSid=%s)", sidstr); DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid)));
status = NT_STATUS_NO_MEMORY;
goto done;
}
if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) {
free(sidstr);
DEBUG(1,("lookup_usergroups(sid=%s) asprintf failed!\n", sid_to_string(sid_string, sid)));
status = NT_STATUS_NO_MEMORY;
goto done;
}
rc = ads_search_retry(ads, &msg, exp, attrs); rc = ads_search_retry(ads, &msg, exp, attrs);
free(exp); free(exp);
free(sidstr); free(sidstr);
if (!ADS_ERR_OK(rc)) { if (!ADS_ERR_OK(rc)) {
DEBUG(1,("lookup_usergroups(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); DEBUG(1,("lookup_usergroups(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc)));
goto done; goto done;
} }
user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName");
if (!user_dn) {
DEBUG(1,("lookup_usergroups(sid=%s) ads_search did not return a a distinguishedName!\n", sid_to_string(sid_string, sid)));
if (msg) ads_msgfree(ads, msg);
goto done;
}
if (msg) ads_msgfree(ads, msg); if (msg) ads_msgfree(ads, msg);
rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2);
if (!ADS_ERR_OK(rc)) { if (!ADS_ERR_OK(rc)) {
DEBUG(1,("lookup_usergroups(rid=%d) ads_search tokenGroups: %s\n", user_rid, ads_errstr(rc))); DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc)));
goto done; goto done;
} }
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group)) { if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
DEBUG(1,("%s: No primary group for rid=%d !?\n", domain->name, user_rid)); DEBUG(1,("%s: No primary group for sid=%s !?\n", domain->name, sid_to_string(sid_string, sid)));
goto done; goto done;
} }
count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids) + 1; primary_group = rid_to_talloced_sid(domain, mem_ctx, primary_group_rid);
(*user_gids) = (uint32 *)talloc_zero(mem_ctx, sizeof(uint32) * count);
(*user_gids)[(*num_groups)++] = primary_group;
for (i=1;i<count;i++) { count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
uint32 rid;
if (!sid_peek_check_rid(&domain->sid, &sids[i-1], &rid)) continue; if (msg) ads_msgfree(ads, msg);
(*user_gids)[*num_groups] = rid;
/* there must always be at least one group in the token,
unless we are talking to a buggy Win2k server */
if (count == 0) {
return lookup_usergroups_alt(domain, mem_ctx, user_dn,
primary_group,
num_groups, user_gids);
}
(*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1));
(*user_gids)[0] = primary_group;
*num_groups = 1;
for (i=0;i<count;i++) {
if (sid_equal(&sids[i], primary_group)) continue;
(*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids));
if (!(*user_gids)[*num_groups]) {
status = NT_STATUS_NO_MEMORY;
goto done;
}
sid_copy((*user_gids)[*num_groups], &sids[i]);
(*num_groups)++; (*num_groups)++;
} }
status = NT_STATUS_OK; status = NT_STATUS_OK;
DEBUG(3,("ads lookup_usergroups for rid=%d\n", user_rid)); DEBUG(3,("ads lookup_usergroups for sid=%s\n", sid_to_string(sid_string, sid)));
done: done:
if (msg) ads_msgfree(ads, msg);
return status; return status;
} }
@ -527,11 +640,10 @@ done:
*/ */
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 group_rid, uint32 *num_names, DOM_SID *group_sid, uint32 *num_names,
uint32 **rid_mem, char ***names, DOM_SID ***sid_mem, char ***names,
uint32 **name_types) uint32 **name_types)
{ {
DOM_SID group_sid;
ADS_STATUS rc; ADS_STATUS rc;
int count; int count;
void *res=NULL; void *res=NULL;
@ -542,14 +654,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
const char *attrs[] = {"member", NULL}; const char *attrs[] = {"member", NULL};
char **members; char **members;
int i, num_members; int i, num_members;
fstring sid_string;
*num_names = 0; *num_names = 0;
ads = ads_cached_connection(domain); ads = ads_cached_connection(domain);
if (!ads) goto done; if (!ads) goto done;
sid_from_rid(domain, group_rid, &group_sid); sidstr = sid_binstring(group_sid);
sidstr = sid_binstring(&group_sid);
/* search for all members of the group */ /* search for all members of the group */
asprintf(&exp, "(objectSid=%s)",sidstr); asprintf(&exp, "(objectSid=%s)",sidstr);
@ -581,24 +693,30 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
for (i=0;members[i];i++) /* noop */ ; for (i=0;members[i];i++) /* noop */ ;
num_members = i; num_members = i;
(*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); (*sid_mem) = talloc_zero(mem_ctx, sizeof(**sid_mem) * num_members);
(*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); (*name_types) = talloc_zero(mem_ctx, sizeof(**name_types) * num_members);
(*names) = talloc_zero(mem_ctx, sizeof(char *) * num_members); (*names) = talloc_zero(mem_ctx, sizeof(**names) * num_members);
for (i=0;i<num_members;i++) { for (i=0;i<num_members;i++) {
uint32 name_type, rid; uint32 name_type;
char *name; char *name;
DOM_SID sid;
if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &rid)) { if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &sid)) {
(*names)[*num_names] = name; (*names)[*num_names] = name;
(*name_types)[*num_names] = name_type; (*name_types)[*num_names] = name_type;
(*rid_mem)[*num_names] = rid; (*sid_mem)[*num_names] = talloc(mem_ctx, sizeof(***sid_mem));
if (!(*sid_mem)[*num_names]) {
status = NT_STATUS_NO_MEMORY;
goto done;
}
sid_copy((*sid_mem)[*num_names], &sid);
(*num_names)++; (*num_names)++;
} }
} }
status = NT_STATUS_OK; status = NT_STATUS_OK;
DEBUG(3,("ads lookup_groupmem for rid=%d\n", group_rid)); DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid)));
done: done:
if (res) ads_msgfree(ads, res); if (res) ads_msgfree(ads, res);

View File

@ -192,6 +192,23 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
return ret; return ret;
} }
/* pull a string from a cache entry, using the supplied
talloc context
*/
static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
{
DOM_SID *sid;
char *sid_string;
sid = talloc(mem_ctx, sizeof(*sid));
if (!sid) return NULL;
sid_string = centry_string(centry, mem_ctx);
if (!string_to_sid(sid, sid_string)) {
return NULL;
}
return sid;
}
/* the server is considered down if it can't give us a sequence number */ /* the server is considered down if it can't give us a sequence number */
static BOOL wcache_server_down(struct winbindd_domain *domain) static BOOL wcache_server_down(struct winbindd_domain *domain)
{ {
@ -258,6 +275,9 @@ static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *c
fetch an entry from the cache, with a varargs key. auto-fetch the sequence fetch an entry from the cache, with a varargs key. auto-fetch the sequence
number and return status number and return status
*/ */
static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
struct winbindd_domain *domain,
const char *format, ...) PRINTF_ATTRIBUTE(3,4);
static struct cache_entry *wcache_fetch(struct winbind_cache *cache, static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
struct winbindd_domain *domain, struct winbindd_domain *domain,
const char *format, ...) const char *format, ...)
@ -370,6 +390,12 @@ static void centry_put_string(struct cache_entry *centry, const char *s)
centry->ofs += len; centry->ofs += len;
} }
static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid)
{
fstring sid_string;
centry_put_string(centry, sid_to_string(sid_string, sid));
}
/* /*
start a centry for output. When finished, call centry_end() start a centry for output. When finished, call centry_end()
*/ */
@ -393,6 +419,7 @@ struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status
/* /*
finish a centry and write it to the tdb finish a centry and write it to the tdb
*/ */
static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
static void centry_end(struct cache_entry *centry, const char *format, ...) static void centry_end(struct cache_entry *centry, const char *format, ...)
{ {
va_list ap; va_list ap;
@ -412,39 +439,29 @@ static void centry_end(struct cache_entry *centry, const char *format, ...)
free(kstr); free(kstr);
} }
/* form a sid from the domain plus rid */ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
static DOM_SID *form_sid(struct winbindd_domain *domain, uint32 rid) NTSTATUS status,
{ const char *name, DOM_SID *sid,
static DOM_SID sid; enum SID_NAME_USE type)
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, rid);
return &sid;
}
static void wcache_save_name_to_sid(struct winbindd_domain *domain, NTSTATUS status,
const char *name, DOM_SID *sid, enum SID_NAME_USE type)
{ {
struct cache_entry *centry; struct cache_entry *centry;
uint32 len;
fstring uname; fstring uname;
fstring sid_string;
centry = centry_start(domain, status); centry = centry_start(domain, status);
if (!centry) return; if (!centry) return;
len = sid_size(sid); centry_put_sid(centry, sid);
centry_expand(centry, len);
centry_put_uint32(centry, type);
sid_linearize(centry->data + centry->ofs, len, sid);
centry->ofs += len;
fstrcpy(uname, name); fstrcpy(uname, name);
strupper(uname); strupper(uname);
centry_end(centry, "NS/%s/%s", domain->name, uname); centry_end(centry, "NS/%s", sid_to_string(sid_string, sid));
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,
DOM_SID *sid, const char *name, enum SID_NAME_USE type, uint32 rid) DOM_SID *sid, const char *name, enum SID_NAME_USE type)
{ {
struct cache_entry *centry; struct cache_entry *centry;
fstring sid_string;
centry = centry_start(domain, status); centry = centry_start(domain, status);
if (!centry) return; if (!centry) return;
@ -452,7 +469,7 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta
centry_put_uint32(centry, type); centry_put_uint32(centry, type);
centry_put_string(centry, name); centry_put_string(centry, name);
} }
centry_end(centry, "SN/%s/%d", domain->name, rid); centry_end(centry, "SN/%s", sid_to_string(sid_string, sid));
centry_free(centry); centry_free(centry);
} }
@ -460,14 +477,15 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta
static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info) static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info)
{ {
struct cache_entry *centry; struct cache_entry *centry;
fstring sid_string;
centry = centry_start(domain, status); centry = centry_start(domain, status);
if (!centry) return; if (!centry) return;
centry_put_string(centry, info->acct_name); centry_put_string(centry, info->acct_name);
centry_put_string(centry, info->full_name); centry_put_string(centry, info->full_name);
centry_put_uint32(centry, info->user_rid); centry_put_sid(centry, info->user_sid);
centry_put_uint32(centry, info->group_rid); centry_put_sid(centry, info->group_sid);
centry_end(centry, "U/%s/%d", domain->name, info->user_rid); centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid));
centry_free(centry); centry_free(centry);
} }
@ -481,7 +499,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
int i; unsigned int i;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
@ -497,8 +515,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
for (i=0; i<(*num_entries); i++) { for (i=0; i<(*num_entries); i++) {
(*info)[i].acct_name = centry_string(centry, mem_ctx); (*info)[i].acct_name = centry_string(centry, mem_ctx);
(*info)[i].full_name = centry_string(centry, mem_ctx); (*info)[i].full_name = centry_string(centry, mem_ctx);
(*info)[i].user_rid = centry_uint32(centry); (*info)[i].user_sid = centry_sid(centry, mem_ctx);
(*info)[i].group_rid = centry_uint32(centry); (*info)[i].group_sid = centry_sid(centry, mem_ctx);
} }
do_cached: do_cached:
@ -524,18 +542,18 @@ do_query:
for (i=0; i<(*num_entries); i++) { for (i=0; i<(*num_entries); i++) {
centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].acct_name);
centry_put_string(centry, (*info)[i].full_name); centry_put_string(centry, (*info)[i].full_name);
centry_put_uint32(centry, (*info)[i].user_rid); centry_put_sid(centry, (*info)[i].user_sid);
centry_put_uint32(centry, (*info)[i].group_rid); centry_put_sid(centry, (*info)[i].group_sid);
if (cache->backend->consistent) { if (cache->backend->consistent) {
/* 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,
form_sid(domain, (*info)[i].user_rid), (*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,
form_sid(domain, (*info)[i].user_rid), (*info)[i].user_sid,
(*info)[i].acct_name, (*info)[i].acct_name,
SID_NAME_USER, (*info)[i].user_rid); SID_NAME_USER);
wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]);
} }
} }
@ -555,7 +573,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
int i; unsigned int i;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
@ -615,7 +633,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
int i; unsigned int i;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
@ -669,7 +687,7 @@ do_query:
centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].acct_name);
centry_put_string(centry, (*info)[i].acct_desc); centry_put_string(centry, (*info)[i].acct_desc);
centry_put_uint32(centry, (*info)[i].rid); centry_put_uint32(centry, (*info)[i].rid);
} }
centry_end(centry, "GL/%s/local", domain->name); centry_end(centry, "GL/%s/local", domain->name);
centry_free(centry); centry_free(centry);
@ -679,6 +697,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,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
@ -687,6 +706,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
fstring uname; fstring uname;
DOM_SID *sid2;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
@ -695,7 +715,12 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname);
if (!centry) goto do_query; if (!centry) goto do_query;
*type = centry_uint32(centry); *type = centry_uint32(centry);
sid_parse(centry->data + centry->ofs, centry->len - centry->ofs, sid); sid2 = centry_sid(centry, mem_ctx);
if (!sid2) {
ZERO_STRUCTP(sid);
} else {
sid_copy(sid, sid2);
}
status = centry->status; status = centry->status;
centry_free(centry); centry_free(centry);
@ -707,7 +732,7 @@ do_query:
if (wcache_server_down(domain)) { if (wcache_server_down(domain)) {
return NT_STATUS_SERVER_DISABLED; return NT_STATUS_SERVER_DISABLED;
} }
status = cache->backend->name_to_sid(domain, name, sid, type); status = cache->backend->name_to_sid(domain, mem_ctx, 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, name, sid, *type);
@ -729,14 +754,11 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
uint32 rid = 0; fstring sid_string;
if (!sid_peek_check_rid(&domain->sid, sid, &rid))
return NT_STATUS_INVALID_PARAMETER;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
centry = wcache_fetch(cache, domain, "SN/%s/%d", domain->name, rid); centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid));
if (!centry) goto do_query; if (!centry) goto do_query;
if (NT_STATUS_IS_OK(centry->status)) { if (NT_STATUS_IS_OK(centry->status)) {
*type = centry_uint32(centry); *type = centry_uint32(centry);
@ -756,7 +778,7 @@ do_query:
/* and save it */ /* and save it */
refresh_sequence_number(domain, True); refresh_sequence_number(domain, True);
wcache_save_sid_to_name(domain, status, sid, *name, *type, rid); wcache_save_sid_to_name(domain, status, sid, *name, *type);
wcache_save_name_to_sid(domain, status, *name, sid, *type); wcache_save_name_to_sid(domain, status, *name, sid, *type);
return status; return status;
@ -766,22 +788,23 @@ do_query:
/* Lookup user information from a rid */ /* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
WINBIND_USERINFO *info) WINBIND_USERINFO *info)
{ {
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
fstring sid_string;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
centry = wcache_fetch(cache, domain, "U/%s/%d", domain->name, user_rid); centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid));
if (!centry) goto do_query; if (!centry) goto do_query;
info->acct_name = centry_string(centry, mem_ctx); info->acct_name = centry_string(centry, mem_ctx);
info->full_name = centry_string(centry, mem_ctx); info->full_name = centry_string(centry, mem_ctx);
info->user_rid = centry_uint32(centry); info->user_sid = centry_sid(centry, mem_ctx);
info->group_rid = centry_uint32(centry); info->group_sid = centry_sid(centry, mem_ctx);
status = centry->status; status = centry->status;
centry_free(centry); centry_free(centry);
return status; return status;
@ -793,7 +816,7 @@ do_query:
return NT_STATUS_SERVER_DISABLED; return NT_STATUS_SERVER_DISABLED;
} }
status = cache->backend->query_user(domain, mem_ctx, user_rid, info); status = cache->backend->query_user(domain, mem_ctx, user_sid, info);
/* and save it */ /* and save it */
refresh_sequence_number(domain, True); refresh_sequence_number(domain, True);
@ -806,17 +829,18 @@ do_query:
/* Lookup groups a user is a member of. */ /* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
uint32 *num_groups, uint32 **user_gids) uint32 *num_groups, DOM_SID ***user_gids)
{ {
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
int i; unsigned int i;
fstring sid_string;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
centry = wcache_fetch(cache, domain, "UG/%s/%d", domain->name, user_rid); centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid));
if (!centry) goto do_query; if (!centry) goto do_query;
*num_groups = centry_uint32(centry); *num_groups = centry_uint32(centry);
@ -826,7 +850,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
(*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups)); (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups));
if (! (*user_gids)) smb_panic("lookup_usergroups out of memory"); if (! (*user_gids)) smb_panic("lookup_usergroups out of memory");
for (i=0; i<(*num_groups); i++) { for (i=0; i<(*num_groups); i++) {
(*user_gids)[i] = centry_uint32(centry); (*user_gids)[i] = centry_sid(centry, mem_ctx);
} }
do_cached: do_cached:
@ -841,7 +865,7 @@ do_query:
if (wcache_server_down(domain)) { if (wcache_server_down(domain)) {
return NT_STATUS_SERVER_DISABLED; return NT_STATUS_SERVER_DISABLED;
} }
status = cache->backend->lookup_usergroups(domain, mem_ctx, user_rid, num_groups, user_gids); status = cache->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids);
/* and save it */ /* and save it */
refresh_sequence_number(domain, True); refresh_sequence_number(domain, True);
@ -849,9 +873,9 @@ do_query:
if (!centry) goto skip_save; if (!centry) goto skip_save;
centry_put_uint32(centry, *num_groups); centry_put_uint32(centry, *num_groups);
for (i=0; i<(*num_groups); i++) { for (i=0; i<(*num_groups); i++) {
centry_put_uint32(centry, (*user_gids)[i]); centry_put_sid(centry, (*user_gids)[i]);
} }
centry_end(centry, "UG/%s/%d", domain->name, user_rid); centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid));
centry_free(centry); centry_free(centry);
skip_save: skip_save:
@ -861,34 +885,35 @@ skip_save:
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 group_rid, uint32 *num_names, DOM_SID *group_sid, uint32 *num_names,
uint32 **rid_mem, char ***names, DOM_SID ***sid_mem, char ***names,
uint32 **name_types) uint32 **name_types)
{ {
struct winbind_cache *cache = get_cache(domain); struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL; struct cache_entry *centry = NULL;
NTSTATUS status; NTSTATUS status;
int i; unsigned int i;
fstring sid_string;
if (!cache->tdb) goto do_query; if (!cache->tdb) goto do_query;
centry = wcache_fetch(cache, domain, "GM/%s/%d", domain->name, group_rid); centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid));
if (!centry) goto do_query; if (!centry) goto do_query;
*num_names = centry_uint32(centry); *num_names = centry_uint32(centry);
if (*num_names == 0) goto do_cached; if (*num_names == 0) goto do_cached;
(*rid_mem) = talloc(mem_ctx, sizeof(**rid_mem) * (*num_names)); (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names));
(*names) = talloc(mem_ctx, sizeof(**names) * (*num_names)); (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names));
(*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names)); (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names));
if (! (*rid_mem) || ! (*names) || ! (*name_types)) { if (! (*sid_mem) || ! (*names) || ! (*name_types)) {
smb_panic("lookup_groupmem out of memory"); smb_panic("lookup_groupmem out of memory");
} }
for (i=0; i<(*num_names); i++) { for (i=0; i<(*num_names); i++) {
(*rid_mem)[i] = centry_uint32(centry); (*sid_mem)[i] = centry_sid(centry, mem_ctx);
(*names)[i] = centry_string(centry, mem_ctx); (*names)[i] = centry_string(centry, mem_ctx);
(*name_types)[i] = centry_uint32(centry); (*name_types)[i] = centry_uint32(centry);
} }
@ -900,7 +925,7 @@ do_cached:
do_query: do_query:
(*num_names) = 0; (*num_names) = 0;
(*rid_mem) = NULL; (*sid_mem) = NULL;
(*names) = NULL; (*names) = NULL;
(*name_types) = NULL; (*name_types) = NULL;
@ -908,8 +933,8 @@ do_query:
if (wcache_server_down(domain)) { if (wcache_server_down(domain)) {
return NT_STATUS_SERVER_DISABLED; return NT_STATUS_SERVER_DISABLED;
} }
status = cache->backend->lookup_groupmem(domain, mem_ctx, group_rid, num_names, status = cache->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names,
rid_mem, names, name_types); sid_mem, names, name_types);
/* and save it */ /* and save it */
refresh_sequence_number(domain, True); refresh_sequence_number(domain, True);
@ -917,11 +942,11 @@ do_query:
if (!centry) goto skip_save; if (!centry) goto skip_save;
centry_put_uint32(centry, *num_names); centry_put_uint32(centry, *num_names);
for (i=0; i<(*num_names); i++) { for (i=0; i<(*num_names); i++) {
centry_put_uint32(centry, (*rid_mem)[i]); centry_put_sid(centry, (*sid_mem)[i]);
centry_put_string(centry, (*names)[i]); centry_put_string(centry, (*names)[i]);
centry_put_uint32(centry, (*name_types)[i]); centry_put_uint32(centry, (*name_types)[i]);
} }
centry_end(centry, "GM/%s/%d", domain->name, group_rid); centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid));
centry_free(centry); centry_free(centry);
skip_save: skip_save:

View File

@ -373,7 +373,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
} }
result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
&dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, &retry); ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, &retry);
secrets_named_mutex_release(new_conn->controller); secrets_named_mutex_release(new_conn->controller);

View File

@ -49,43 +49,44 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
return True; return True;
} }
/* Fill in the group membership field of a NT group given by group_rid */ /* Fill in the group membership field of a NT group given by group_sid */
static BOOL fill_grent_mem(struct winbindd_domain *domain, static BOOL fill_grent_mem(struct winbindd_domain *domain,
uint32 group_rid, DOM_SID *group_sid,
enum SID_NAME_USE group_name_type, enum SID_NAME_USE group_name_type,
int *num_gr_mem, char **gr_mem, int *gr_mem_len) int *num_gr_mem, char **gr_mem, int *gr_mem_len)
{ {
uint32 *rid_mem = NULL, num_names = 0; DOM_SID **sid_mem = NULL;
uint32 num_names = 0;
uint32 *name_types = NULL; uint32 *name_types = NULL;
int buf_len, buf_ndx, i; unsigned int buf_len, buf_ndx, i;
char **names = NULL, *buf; char **names = NULL, *buf;
BOOL result = False; BOOL result = False;
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
NTSTATUS status; NTSTATUS status;
fstring sid_string;
if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name)))
return False; return False;
/* Initialise group membership information */ /* Initialise group membership information */
DEBUG(10, ("group %s rid 0x%x\n", domain ? domain->name : "NULL", DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid)));
group_rid));
*num_gr_mem = 0; *num_gr_mem = 0;
if (group_name_type != SID_NAME_DOM_GRP) { if (group_name_type != SID_NAME_DOM_GRP) {
DEBUG(1, ("rid %d in domain %s isn't a domain group\n", DEBUG(1, ("SID %s in domain %s isn't a domain group\n",
group_rid, domain->name)); sid_to_string(sid_string, group_sid), domain->name));
goto done; goto done;
} }
/* Lookup group members */ /* Lookup group members */
status = domain->methods->lookup_groupmem(domain, mem_ctx, group_rid, &num_names, status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names,
&rid_mem, &names, &name_types); &sid_mem, &names, &name_types);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("could not lookup membership for group rid %d in domain %s (error: %s)\n", DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n",
group_rid, domain->name, nt_errstr(status))); sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status)));
goto done; goto done;
} }
@ -94,7 +95,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
if (DEBUGLEVEL >= 10) { if (DEBUGLEVEL >= 10) {
for (i = 0; i < num_names; i++) for (i = 0; i < num_names; i++)
DEBUG(10, ("\t%20s %x %d\n", names[i], rid_mem[i], DEBUG(10, ("\t%20s %s %d\n", names[i], sid_to_string(sid_string, sid_mem[i]),
name_types[i])); name_types[i]));
} }
@ -190,7 +191,6 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
DOM_SID group_sid; DOM_SID group_sid;
struct winbindd_domain *domain; struct winbindd_domain *domain;
enum SID_NAME_USE name_type; enum SID_NAME_USE name_type;
uint32 group_rid;
fstring name_domain, name_group; fstring name_domain, name_group;
char *tmp, *gr_mem; char *tmp, *gr_mem;
gid_t gid; gid_t gid;
@ -233,10 +233,6 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
/* Fill in group structure */
if (!sid_peek_check_rid(&domain->sid, &group_sid, &group_rid))
return WINBINDD_ERROR;
if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) { if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) {
DEBUG(1, ("error converting unix gid to sid\n")); DEBUG(1, ("error converting unix gid to sid\n"));
return WINBINDD_ERROR; return WINBINDD_ERROR;
@ -244,7 +240,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
if (!fill_grent(&state->response.data.gr, name_domain, if (!fill_grent(&state->response.data.gr, name_domain,
name_group, gid) || name_group, gid) ||
!fill_grent_mem(domain, group_rid, name_type, !fill_grent_mem(domain, &group_sid, name_type,
&state->response.data.gr.num_gr_mem, &state->response.data.gr.num_gr_mem,
&gr_mem, &gr_mem_len)) { &gr_mem, &gr_mem_len)) {
return WINBINDD_ERROR; return WINBINDD_ERROR;
@ -269,7 +265,6 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
enum SID_NAME_USE name_type; enum SID_NAME_USE name_type;
fstring dom_name; fstring dom_name;
fstring group_name; fstring group_name;
uint32 group_rid;
int gr_mem_len; int gr_mem_len;
char *gr_mem; char *gr_mem;
@ -284,17 +279,13 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
/* Get rid from gid */ /* Get rid from gid */
if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid, if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &group_sid)) {
&group_rid, &domain)) {
DEBUG(1, ("could not convert gid %d to rid\n", DEBUG(1, ("could not convert gid %d to rid\n",
state->request.data.gid)); state->request.data.gid));
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
/* Get sid from gid */ /* Get name from sid */
sid_copy(&group_sid, &domain->sid);
sid_append_rid(&group_sid, group_rid);
if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) { if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) {
DEBUG(1, ("could not lookup sid\n")); DEBUG(1, ("could not lookup sid\n"));
@ -310,9 +301,16 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
/* Fill in group structure */ /* Fill in group structure */
domain = find_domain_from_sid(&group_sid);
if (!domain) {
DEBUG(1,("Can't find domain from sid\n"));
return WINBINDD_ERROR;
}
if (!fill_grent(&state->response.data.gr, dom_name, group_name, if (!fill_grent(&state->response.data.gr, dom_name, group_name,
state->request.data.gid) || state->request.data.gid) ||
!fill_grent_mem(domain, group_rid, name_type, !fill_grent_mem(domain, &group_sid, name_type,
&state->response.data.gr.num_gr_mem, &state->response.data.gr.num_gr_mem,
&gr_mem, &gr_mem_len)) &gr_mem, &gr_mem_len))
return WINBINDD_ERROR; return WINBINDD_ERROR;
@ -544,7 +542,9 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
gid_t group_gid; gid_t group_gid;
int gr_mem_len; int gr_mem_len;
char *gr_mem, *new_gr_mem_list; char *gr_mem, *new_gr_mem_list;
DOM_SID group_sid;
struct winbindd_domain *domain;
/* Do we need to fetch another chunk of groups? */ /* Do we need to fetch another chunk of groups? */
tryagain: tryagain:
@ -578,16 +578,25 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
name_list = ent->sam_entries; name_list = ent->sam_entries;
if (!(domain =
find_domain_from_name(ent->domain_name))) {
DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name));
result = False;
goto done;
}
/* Lookup group info */ /* Lookup group info */
if (!winbindd_idmap_get_gid_from_rid( sid_copy(&group_sid, &domain->sid);
ent->domain_name, sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
name_list[ent->sam_entry_index].rid,
&group_gid)) { if (!winbindd_idmap_get_gid_from_sid(
&group_sid,
&group_gid)) {
DEBUG(1, ("could not look up gid for group %s\n", DEBUG(1, ("could not look up gid for group %s\n",
name_list[ent->sam_entry_index].acct_name)); name_list[ent->sam_entry_index].acct_name));
ent->sam_entry_index++; ent->sam_entry_index++;
goto tryagain; goto tryagain;
} }
@ -608,15 +617,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group membership entry */ /* Fill in group membership entry */
if (result) { if (result) {
struct winbindd_domain *domain; DOM_SID member_sid;
if (!(domain =
find_domain_from_name(ent->domain_name))) {
DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name));
result = False;
goto done;
}
group_list[group_list_ndx].num_gr_mem = 0; group_list[group_list_ndx].num_gr_mem = 0;
gr_mem = NULL; gr_mem = NULL;
gr_mem_len = 0; gr_mem_len = 0;
@ -625,9 +626,11 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
if (state->request.cmd == WINBINDD_GETGRLST) { if (state->request.cmd == WINBINDD_GETGRLST) {
result = True; result = True;
} else { } else {
sid_copy(&member_sid, &domain->sid);
sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid);
result = fill_grent_mem( result = fill_grent_mem(
domain, domain,
name_list[ent->sam_entry_index].rid, &member_sid,
SID_NAME_DOM_GRP, SID_NAME_DOM_GRP,
&group_list[group_list_ndx].num_gr_mem, &group_list[group_list_ndx].num_gr_mem,
&gr_mem, &gr_mem_len); &gr_mem, &gr_mem_len);
@ -730,7 +733,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
struct winbindd_domain *domain; struct winbindd_domain *domain;
char *extra_data = NULL; char *extra_data = NULL;
char *ted = NULL; char *ted = NULL;
int extra_data_len = 0, i; unsigned int extra_data_len = 0, i;
DEBUG(3, ("[%5d]: list groups\n", state->pid)); DEBUG(3, ("[%5d]: list groups\n", state->pid));
@ -805,13 +808,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
fstring name_domain, name_user; fstring name_domain, name_user;
DOM_SID user_sid; DOM_SID user_sid;
enum SID_NAME_USE name_type; enum SID_NAME_USE name_type;
uint32 user_rid, num_groups, num_gids; uint32 num_groups, num_gids;
NTSTATUS status; NTSTATUS status;
uint32 *user_gids; DOM_SID **user_gids;
struct winbindd_domain *domain; struct winbindd_domain *domain;
enum winbindd_result result = WINBINDD_ERROR; enum winbindd_result result = WINBINDD_ERROR;
gid_t *gid_list; gid_t *gid_list;
int i; unsigned int i;
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
/* Ensure null termination */ /* Ensure null termination */
@ -852,9 +855,9 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
goto done; goto done;
} }
sid_split_rid(&user_sid, &user_rid); status = domain->methods->lookup_usergroups(domain, mem_ctx,
&user_sid, &num_groups,
status = domain->methods->lookup_usergroups(domain, mem_ctx, user_rid, &num_groups, &user_gids); &user_gids);
if (!NT_STATUS_IS_OK(status)) goto done; if (!NT_STATUS_IS_OK(status)) goto done;
/* Copy data back to client */ /* Copy data back to client */
@ -866,12 +869,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
goto done; goto done;
for (i = 0; i < num_groups; i++) { for (i = 0; i < num_groups; i++) {
if (!winbindd_idmap_get_gid_from_rid(domain->name, if (!winbindd_idmap_get_gid_from_sid(
user_gids[i], user_gids[i],
&gid_list[num_gids])) { &gid_list[num_gids])) {
fstring sid_string;
DEBUG(1, ("unable to convert group rid %d to gid\n", DEBUG(1, ("unable to convert group sid %s to gid\n",
user_gids[i])); sid_to_string(sid_string, user_gids[i])));
continue; continue;
} }

View File

@ -1,20 +1,19 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/CIFS implementation.
Winbind ID Mapping
Winbind daemon - user related function
Copyright (C) Tim Potter 2000 Copyright (C) Tim Potter 2000
Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@ -22,508 +21,174 @@
#include "winbindd.h" #include "winbindd.h"
#undef DBGC_CLASS static struct {
#define DBGC_CLASS DBGC_WINBIND const char *name;
/* Function to create a member of the idmap_methods list */
BOOL (*reg_meth)(struct winbindd_idmap_methods **methods);
struct winbindd_idmap_methods *methods;
} builtin_winbindd_idmap_functions[] = {
{ "tdb", winbind_idmap_reg_tdb, NULL },
{ NULL, NULL, NULL }
};
/* High water mark keys */ /* singleton pattern: uberlazy evaluation */
static struct winbindd_idmap_methods *impl;
#define HWM_GROUP "GROUP HWM" static struct winbindd_idmap_methods *get_impl(const char *name)
#define HWM_USER "USER HWM"
/* idmap version determines auto-conversion */
#define IDMAP_VERSION 2
/* Globals */
static TDB_CONTEXT *idmap_tdb;
/* Allocate either a user or group id from the pool */
static BOOL allocate_id(uid_t *id, BOOL isgroup)
{ {
int hwm; int i = 0;
struct winbindd_idmap_methods *ret = NULL;
/* Get current high water mark */ while (builtin_winbindd_idmap_functions[i].name &&
strcmp(builtin_winbindd_idmap_functions[i].name, name)) {
i++;
}
if ((hwm = tdb_fetch_int32(idmap_tdb, if (builtin_winbindd_idmap_functions[i].name) {
isgroup ? HWM_GROUP : HWM_USER)) == -1) { if (!builtin_winbindd_idmap_functions[i].methods) {
return False; builtin_winbindd_idmap_functions[i].reg_meth(&builtin_winbindd_idmap_functions[i].methods);
} }
/* Return next available uid in list */ ret = builtin_winbindd_idmap_functions[i].methods;
}
if ((isgroup && (hwm > server_state.gid_high)) || return ret;
(!isgroup && (hwm > server_state.uid_high))) {
DEBUG(0, ("winbind %sid range full!\n", isgroup ? "g" : "u"));
return False;
}
if (id) {
*id = hwm;
}
hwm++;
/* Store new high water mark */
tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm);
return True;
} }
/* Get an id from a rid */ /* Initialize backend */
static BOOL get_id_from_sid(DOM_SID *sid, uid_t *id, BOOL isgroup)
{
TDB_DATA data, key;
fstring keystr;
BOOL result = False;
/* Check if sid is present in database */
sid_to_string(keystr, sid);
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
data = tdb_fetch(idmap_tdb, key);
if (data.dptr) {
fstring scanstr;
int the_id;
/* Parse and return existing uid */
fstrcpy(scanstr, isgroup ? "GID" : "UID");
fstrcat(scanstr, " %d");
if (sscanf(data.dptr, scanstr, &the_id) == 1) {
/* Store uid */
if (id) {
*id = the_id;
}
result = True;
}
SAFE_FREE(data.dptr);
} else {
/* Allocate a new id for this sid */
if (id && allocate_id(id, isgroup)) {
fstring keystr2;
/* Store new id */
slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" : "UID", *id);
data.dptr = keystr2;
data.dsize = strlen(keystr2) + 1;
tdb_store(idmap_tdb, key, data, TDB_REPLACE);
tdb_store(idmap_tdb, data, key, TDB_REPLACE);
result = True;
}
}
return result;
}
/* Get a uid from a user sid */
BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
{
return get_id_from_sid(sid, uid, False);
}
/* Get a gid from a group sid */
BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
{
return get_id_from_sid(sid, gid, True);
}
/* Get a uid from a user rid */
BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, uid_t *uid)
{
struct winbindd_domain *domain;
DOM_SID sid;
if (!(domain = find_domain_from_name(dom_name))) {
return False;
}
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, rid);
return get_id_from_sid(&sid, uid, False);
}
/* Get a gid from a group rid */
BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, gid_t *gid)
{
struct winbindd_domain *domain;
DOM_SID sid;
if (!(domain = find_domain_from_name(dom_name))) {
return False;
}
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, rid);
return get_id_from_sid(&sid, gid, True);
}
BOOL get_sid_from_id(int id, DOM_SID *sid, BOOL isgroup)
{
TDB_DATA key, data;
fstring keystr;
BOOL result = False;
slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID", id);
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
data = tdb_fetch(idmap_tdb, key);
if (data.dptr) {
result = string_to_sid(sid, data.dptr);
SAFE_FREE(data.dptr);
}
return result;
}
/* Get a sid from a uid */
BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
{
return get_sid_from_id((int)uid, sid, False);
}
/* Get a sid from a gid */
BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
{
return get_sid_from_id((int)gid, sid, True);
}
/* Get a user rid from a uid */
BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
struct winbindd_domain **domain)
{
DOM_SID sid;
if (!get_sid_from_id((int)uid, &sid, False)) {
return False;
}
*domain = find_domain_from_sid(&sid);
if (! *domain) return False;
sid_split_rid(&sid, user_rid);
return True;
}
/* Get a group rid from a gid */
BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid,
struct winbindd_domain **domain)
{
DOM_SID sid;
if (!get_sid_from_id((int)gid, &sid, True)) {
return False;
}
*domain = find_domain_from_sid(&sid);
if (! *domain) return False;
sid_split_rid(&sid, group_rid);
return True;
}
/* convert one record to the new format */
static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *ignored)
{
struct winbindd_domain *domain;
char *p;
DOM_SID sid;
uint32 rid;
fstring keystr;
fstring dom_name;
TDB_DATA key2;
p = strchr(key.dptr, '/');
if (!p)
return 0;
*p = 0;
fstrcpy(dom_name, key.dptr);
*p++ = '/';
domain = find_domain_from_name(dom_name);
if (!domain) {
/* We must delete the old record. */
DEBUG(0,("winbindd: convert_fn : Unable to find domain %s\n", dom_name ));
DEBUG(0,("winbindd: convert_fn : deleting record %s\n", key.dptr ));
tdb_delete(idmap_tdb, key);
return 0;
}
rid = atoi(p);
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, rid);
sid_to_string(keystr, &sid);
key2.dptr = keystr;
key2.dsize = strlen(keystr) + 1;
if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) {
/* not good! */
DEBUG(0,("winbindd: convert_fn : Unable to update record %s\n", key2.dptr ));
DEBUG(0,("winbindd: convert_fn : conversion failed - idmap corrupt ?\n"));
return -1;
}
if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) {
/* not good! */
DEBUG(0,("winbindd: convert_fn : Unable to update record %s\n", data.dptr ));
DEBUG(0,("winbindd: convert_fn : conversion failed - idmap corrupt ?\n"));
return -1;
}
tdb_delete(idmap_tdb, key);
return 0;
}
#if 0
/*****************************************************************************
Make a backup copy of the old idmap just to be safe.... JRA.
*****************************************************************************/
static BOOL backup_old_idmap(const char *idmap_name)
{
pstring new_name;
int outfd = -1;
SMB_OFF_T size;
struct stat st;
pstrcpy(new_name, idmap_name);
pstrcat(new_name, ".bak");
DEBUG(10,("backup_old_idmap: backing up %s to %s before upgrade.\n",
idmap_name, new_name ));
if (tdb_lockall(idmap_tdb) == -1) {
DEBUG(10,("backup_old_idmap: failed to lock %s. Error %s\n",
idmap_name, tdb_errorstr(idmap_tdb) ));
return False;
}
if ((outfd = open(new_name, O_CREAT|O_EXCL|O_RDWR, 0600)) == -1) {
DEBUG(10,("backup_old_idmap: failed to open %s. Error %s\n",
new_name, strerror(errno) ));
goto fail;
}
if (fstat(idmap_tdb->fd, &st) == -1) {
DEBUG(10,("backup_old_idmap: failed to fstat %s. Error %s\n",
idmap_name, strerror(errno) ));
goto fail;
}
size = (SMB_OFF_T)st.st_size;
if (transfer_file(idmap_tdb->fd, outfd, size) != size ) {
DEBUG(10,("backup_old_idmap: failed to copy %s. Error %s\n",
idmap_name, strerror(errno) ));
goto fail;
}
if (close(outfd) == -1) {
DEBUG(10,("backup_old_idmap: failed to close %s. Error %s\n",
idmap_name, strerror(errno) ));
outfd = -1;
goto fail;
}
tdb_unlockall(idmap_tdb);
return True;
fail:
if (outfd != -1)
close(outfd);
tdb_unlockall(idmap_tdb);
return False;
}
#endif
/*****************************************************************************
Convert the idmap database from an older version.
*****************************************************************************/
static BOOL idmap_convert(const char *idmap_name)
{
int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
BOOL bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
if (vers == IDMAP_VERSION)
return True;
#if 0
/* Make a backup copy before doing anything else.... */
if (!backup_old_idmap(idmap_name))
return False;
#endif
if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
/* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
/*
* high and low records were created on a
* big endian machine and will need byte-reversing.
*/
int32 wm;
wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
if (wm != -1) {
wm = IREV(wm);
} else
wm = server_state.uid_low;
if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n"));
return False;
}
wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
if (wm != -1) {
wm = IREV(wm);
} else
wm = server_state.gid_low;
if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
return False;
}
}
/* the old format stored as DOMAIN/rid - now we store the SID direct */
tdb_traverse(idmap_tdb, convert_fn, NULL);
if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
return False;
}
return True;
}
/*****************************************************************************
Initialise idmap database.
*****************************************************************************/
BOOL winbindd_idmap_init(void) BOOL winbindd_idmap_init(void)
{ {
/* Open tdb cache */ BOOL ret = False;
if (!(idmap_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0, DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n",
TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) { lp_winbind_backend()));
DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
return False;
}
/* possibly convert from an earlier version */ if (!impl) {
if (!idmap_convert(lock_path("winbindd_idmap.tdb"))) { impl = get_impl(lp_winbind_backend());
DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n")); if (!impl) {
return False; DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
} lp_winbind_backend()));
}
}
/* Create high water marks for group and user id */ if (impl) {
ret = impl->init();
}
if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) { DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false"));
if (tdb_store_int32(idmap_tdb, HWM_USER, server_state.uid_low) == -1) {
DEBUG(0, ("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n"));
return False;
}
}
if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) { return ret;
if (tdb_store_int32(idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) {
DEBUG(0, ("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n"));
return False;
}
}
return True;
} }
/* Get UID from SID */
BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
{
BOOL ret = False;
if (!impl) {
impl = get_impl(lp_winbind_backend());
if (!impl) {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
lp_winbind_backend()));
}
}
if (impl) {
ret = impl->get_uid_from_sid(sid, uid);
}
return ret;
}
/* Get GID from SID */
BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
{
BOOL ret = False;
if (!impl) {
impl = get_impl(lp_winbind_backend());
if (!impl) {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
lp_winbind_backend()));
}
}
if (impl) {
ret = impl->get_gid_from_sid(sid, gid);
}
return ret;
}
/* Get SID from UID */
BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
{
BOOL ret = False;
if (!impl) {
impl = get_impl(lp_winbind_backend());
if (!impl) {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
lp_winbind_backend()));
}
}
if (impl) {
ret = impl->get_sid_from_uid(uid, sid);
}
return ret;
}
/* Get SID from GID */
BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
{
BOOL ret = False;
if (!impl) {
impl = get_impl(lp_winbind_backend());
}
if (impl) {
ret = impl->get_sid_from_gid(gid, sid);
} else {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
lp_winbind_backend()));
}
return ret;
}
/* Close backend */
BOOL winbindd_idmap_close(void) BOOL winbindd_idmap_close(void)
{ {
if (idmap_tdb) BOOL ret = False;
return (tdb_close(idmap_tdb) == 0);
return True; if (!impl) {
impl = get_impl(lp_winbind_backend());
}
if (impl) {
ret = impl->close();
} else {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
lp_winbind_backend()));
}
return ret;
} }
/* Dump status information to log file. Display different stuff based on /* Dump backend status */
the debug level:
Debug Level Information Displayed
=================================================================
0 Percentage of [ug]id range allocated
0 High water marks (next allocated ids)
*/
#define DUMP_INFO 0
void winbindd_idmap_status(void) void winbindd_idmap_status(void)
{ {
int user_hwm, group_hwm; if (!impl) {
impl = get_impl(lp_winbind_backend());
}
DEBUG(0, ("winbindd idmap status:\n")); if (impl) {
impl->status();
/* Get current high water marks */ } else {
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { lp_winbind_backend()));
DEBUG(DUMP_INFO, ("\tCould not get userid high water mark!\n")); }
}
if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
DEBUG(DUMP_INFO, ("\tCould not get groupid high water mark!\n"));
}
/* Display next ids to allocate */
if (user_hwm != -1) {
DEBUG(DUMP_INFO, ("\tNext userid to allocate is %d\n", user_hwm));
}
if (group_hwm != -1) {
DEBUG(DUMP_INFO, ("\tNext groupid to allocate is %d\n", group_hwm));
}
/* Display percentage of id range already allocated. */
if (user_hwm != -1) {
int num_users = user_hwm - server_state.uid_low;
int total_users = server_state.uid_high - server_state.uid_low;
DEBUG(DUMP_INFO, ("\tUser id range is %d%% full (%d of %d)\n",
num_users * 100 / total_users, num_users,
total_users));
}
if (group_hwm != -1) {
int num_groups = group_hwm - server_state.gid_low;
int total_groups = server_state.gid_high - server_state.gid_low;
DEBUG(DUMP_INFO, ("\tGroup id range is %d%% full (%d of %d)\n",
num_groups * 100 / total_groups, num_groups,
total_groups));
}
/* Display complete mapping of users and groups to rids */
} }

View File

@ -3,7 +3,7 @@
Winbind rpc backend functions Winbind rpc backend functions
Copyright (C) Tim Potter 2000-2001 Copyright (C) Tim Potter 2000-2001,2003
Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Tridgell 2001
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -26,6 +26,7 @@
#undef DBGC_CLASS #undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND #define DBGC_CLASS DBGC_WINBIND
/* Query display info for a domain. This returns enough information plus a /* Query display info for a domain. This returns enough information plus a
bit extra to give an overview of domain users for the User Manager bit extra to give an overview of domain users for the User Manager
application. */ application. */
@ -39,18 +40,17 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
POLICY_HND dom_pol; POLICY_HND dom_pol;
BOOL got_dom_pol = False; BOOL got_dom_pol = False;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
int i, loop_count = 0; unsigned int i, start_idx, retry;
int retry;
DEBUG(3,("rpc: query_user_list\n")); DEBUG(3,("rpc: query_user_list\n"));
*num_entries = 0; *num_entries = 0;
*info = NULL; *info = NULL;
/* Get sam handle */
retry = 0; retry = 0;
do { do {
/* Get sam handle */
if (!(hnd = cm_get_sam_handle(domain->name))) if (!(hnd = cm_get_sam_handle(domain->name)))
goto done; goto done;
@ -66,50 +66,39 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
got_dom_pol = True; got_dom_pol = True;
i = 0; i = start_idx = 0;
do { do {
SAM_DISPINFO_CTR ctr;
SAM_DISPINFO_1 info1;
uint32 count = 0, start=i, max_entries, max_size;
int j;
TALLOC_CTX *ctx2; TALLOC_CTX *ctx2;
char **dom_users;
uint32 num_dom_users, *dom_rids, j, size = 0xffff;
uint16 acb_mask = ACB_NORMAL;
ctr.sam.info1 = &info1; if (!(ctx2 = talloc_init("winbindd enum_users"))) {
ctx2 = talloc_init("winbindd dispinfo");
if (!ctx2) {
result = NT_STATUS_NO_MEMORY; result = NT_STATUS_NO_MEMORY;
goto done; goto done;
} }
get_query_dispinfo_params(
loop_count, &max_entries, &max_size);
/* Query display info level 1 */ result = cli_samr_enum_dom_users(
result = cli_samr_query_dispinfo( hnd->cli, ctx2, &dom_pol, &start_idx, acb_mask,
hnd->cli, ctx2, &dom_pol, &start, 1, &count, size, &dom_users, &dom_rids, &num_dom_users);
max_entries, max_size, &ctr);
loop_count++; *num_entries += num_dom_users;
if (!NT_STATUS_IS_OK(result) && *info = talloc_realloc(
!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break; mem_ctx, *info,
(*num_entries) * sizeof(WINBIND_USERINFO));
(*num_entries) += count;
/* now map the result into the WINBIND_USERINFO structure */
(*info) = talloc_realloc(mem_ctx, *info,
(*num_entries)*sizeof(WINBIND_USERINFO));
if (!(*info)) { if (!(*info)) {
result = NT_STATUS_NO_MEMORY; result = NT_STATUS_NO_MEMORY;
talloc_destroy(ctx2); talloc_destroy(ctx2);
goto done; goto done;
} }
for (j=0;j<count;i++, j++) { for (j = 0; j < num_dom_users; i++, j++) {
(*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_acct_name); (*info)[i].acct_name =
(*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_full_name); talloc_strdup(mem_ctx, dom_users[j]);
(*info)[i].user_rid = info1.sam[j].rid_user; (*info)[i].full_name = talloc_strdup(mem_ctx, "");
(*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, dom_rids[j]);
/* For the moment we set the primary group for /* For the moment we set the primary group for
every user to be the Domain Users group. every user to be the Domain Users group.
There are serious problems with determining There are serious problems with determining
@ -117,10 +106,14 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
This should really be made into a 'winbind This should really be made into a 'winbind
force group' smb.conf parameter or force group' smb.conf parameter or
something like that. */ something like that. */
(*info)[i].group_rid = DOMAIN_GROUP_RID_USERS; (*info)[i].group_sid
= rid_to_talloced_sid(domain,
mem_ctx,
DOMAIN_GROUP_RID_USERS);
} }
talloc_destroy(ctx2); talloc_destroy(ctx2);
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
done: done:
@ -263,11 +256,11 @@ 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,
const char *name, const char *name,
DOM_SID *sid, DOM_SID *sid,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
TALLOC_CTX *mem_ctx;
CLI_POLICY_HND *hnd; CLI_POLICY_HND *hnd;
NTSTATUS status; NTSTATUS status;
DOM_SID *sids = NULL; DOM_SID *sids = NULL;
@ -277,23 +270,16 @@ 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));
if (!(mem_ctx = talloc_init("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
DEBUG(0, ("talloc_init failed!\n"));
return NT_STATUS_NO_MEMORY;
}
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"));
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY; return NT_STATUS_NO_MEMORY;
} }
retry = 0; retry = 0;
do { do {
if (!(hnd = cm_get_lsa_handle(domain->name))) { if (!(hnd = cm_get_lsa_handle(domain->name))) {
talloc_destroy(mem_ctx);
return NT_STATUS_UNSUCCESSFUL; return NT_STATUS_UNSUCCESSFUL;
} }
@ -308,7 +294,6 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
*type = types[0]; *type = types[0];
} }
talloc_destroy(mem_ctx);
return status; return status;
} }
@ -356,17 +341,22 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
/* Lookup user information from a rid or username. */ /* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain, static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
WINBIND_USERINFO *user_info) WINBIND_USERINFO *user_info)
{ {
CLI_POLICY_HND *hnd; CLI_POLICY_HND *hnd = NULL;
NTSTATUS result; NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
POLICY_HND dom_pol, user_pol; POLICY_HND dom_pol, user_pol;
BOOL got_dom_pol = False, got_user_pol = False; BOOL got_dom_pol = False, got_user_pol = False;
SAM_USERINFO_CTR *ctr; SAM_USERINFO_CTR *ctr;
int retry; int retry;
fstring sid_string;
uint32 user_rid;
DEBUG(3,("rpc: query_user rid=%u\n", user_rid)); DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
goto done;
}
retry = 0; retry = 0;
do { do {
@ -405,8 +395,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
cli_samr_close(hnd->cli, mem_ctx, &user_pol); cli_samr_close(hnd->cli, mem_ctx, &user_pol);
got_user_pol = False; got_user_pol = False;
user_info->user_rid = user_rid; user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
user_info->group_rid = ctr->info.id21->group_rid; user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
user_info->acct_name = unistr2_tdup(mem_ctx, user_info->acct_name = unistr2_tdup(mem_ctx,
&ctr->info.id21->uni_user_name); &ctr->info.id21->uni_user_name);
user_info->full_name = unistr2_tdup(mem_ctx, user_info->full_name = unistr2_tdup(mem_ctx,
@ -426,8 +416,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
/* Lookup groups a user is a member of. I wish Unix had a call like this! */ /* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 user_rid, DOM_SID *user_sid,
uint32 *num_groups, uint32 **user_gids) uint32 *num_groups, DOM_SID ***user_gids)
{ {
CLI_POLICY_HND *hnd; CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@ -435,15 +425,17 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
BOOL got_dom_pol = False, got_user_pol = False; BOOL got_dom_pol = False, got_user_pol = False;
DOM_GID *user_groups; DOM_GID *user_groups;
int i; unsigned int i;
int retry; unsigned int retry;
fstring sid_string;
uint32 user_rid;
DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid)); DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
*num_groups = 0; *num_groups = 0;
/* First try cached universal groups from logon */ /* First try cached universal groups from logon */
*user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups); *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups);
if((*num_groups > 0) && *user_gids) { if((*num_groups > 0) && *user_gids) {
return NT_STATUS_OK; return NT_STATUS_OK;
} else { } else {
@ -459,7 +451,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
/* Get domain handle */ /* Get domain handle */
result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
des_access, &domain->sid, &dom_pol); des_access, &domain->sid, &dom_pol);
} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
if (!NT_STATUS_IS_OK(result)) if (!NT_STATUS_IS_OK(result))
@ -467,6 +459,11 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
got_dom_pol = True; got_dom_pol = True;
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
goto done;
}
/* Get user handle */ /* Get user handle */
result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
des_access, user_rid, &user_pol); des_access, user_rid, &user_pol);
@ -484,8 +481,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done; goto done;
(*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
if (!(*user_gids)) {
result = NT_STATUS_NO_MEMORY;
goto done;
}
for (i=0;i<(*num_groups);i++) { for (i=0;i<(*num_groups);i++) {
(*user_gids)[i] = user_groups[i].g_rid; (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
} }
done: done:
@ -503,19 +505,27 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
/* Lookup group membership given a rid. */ /* Lookup group membership given a rid. */
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
uint32 group_rid, uint32 *num_names, DOM_SID *group_sid, uint32 *num_names,
uint32 **rid_mem, char ***names, DOM_SID ***sid_mem, char ***names,
uint32 **name_types) uint32 **name_types)
{ {
CLI_POLICY_HND *hnd; CLI_POLICY_HND *hnd = NULL;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
uint32 i, total_names = 0; uint32 i, total_names = 0;
POLICY_HND dom_pol, group_pol; POLICY_HND dom_pol, group_pol;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
BOOL got_dom_pol = False, got_group_pol = False; BOOL got_dom_pol = False, got_group_pol = False;
uint32 *rid_mem = NULL;
uint32 group_rid;
int retry; int retry;
unsigned int j;
fstring sid_string;
DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid)); DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
goto done;
}
*num_names = 0; *num_names = 0;
@ -550,7 +560,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
group. */ group. */
result = cli_samr_query_groupmem(hnd->cli, mem_ctx, result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
&group_pol, num_names, rid_mem, &group_pol, num_names, &rid_mem,
name_types); name_types);
if (!NT_STATUS_IS_OK(result)) if (!NT_STATUS_IS_OK(result))
@ -565,6 +575,16 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
*names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
*name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
*sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *));
for (j=0;j<(*num_names);j++) {
(*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
}
if (!*names || !*name_types) {
result = NT_STATUS_NO_MEMORY;
goto done;
}
for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
@ -577,7 +597,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
result = cli_samr_lookup_rids(hnd->cli, mem_ctx, result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
&dom_pol, 1000, /* flags */ &dom_pol, 1000, /* flags */
num_lookup_rids, num_lookup_rids,
&(*rid_mem)[i], &rid_mem[i],
&tmp_num_names, &tmp_num_names,
&tmp_names, &tmp_types); &tmp_names, &tmp_types);
@ -592,7 +612,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
tmp_num_names); tmp_num_names);
total_names += tmp_num_names; total_names += tmp_num_names;
} }

View File

@ -29,29 +29,30 @@
/* Fill a pwent structure with information we have obtained */ /* Fill a pwent structure with information we have obtained */
static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
uint32 user_rid, uint32 group_rid, DOM_SID *user_sid, DOM_SID *group_sid,
char *full_name, struct winbindd_pw *pw) char *full_name, struct winbindd_pw *pw)
{ {
extern userdom_struct current_user_info; extern userdom_struct current_user_info;
fstring output_username; fstring output_username;
pstring homedir; pstring homedir;
fstring sid_string;
if (!pw || !dom_name || !user_name) if (!pw || !dom_name || !user_name)
return False; return False;
/* Resolve the uid number */ /* Resolve the uid number */
if (!winbindd_idmap_get_uid_from_rid(dom_name, user_rid, if (!winbindd_idmap_get_uid_from_sid(user_sid,
&pw->pw_uid)) { &pw->pw_uid)) {
DEBUG(1, ("error getting user id for rid %d\n", user_rid)); DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid)));
return False; return False;
} }
/* Resolve the gid number */ /* Resolve the gid number */
if (!winbindd_idmap_get_gid_from_rid(dom_name, group_rid, if (!winbindd_idmap_get_gid_from_sid(group_sid,
&pw->pw_gid)) { &pw->pw_gid)) {
DEBUG(1, ("error getting group id for rid %d\n", group_rid)); DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid)));
return False; return False;
} }
@ -95,7 +96,6 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
{ {
uint32 user_rid;
WINBIND_USERINFO user_info; WINBIND_USERINFO user_info;
DOM_SID user_sid; DOM_SID user_sid;
NTSTATUS status; NTSTATUS status;
@ -144,9 +144,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
sid_split_rid(&user_sid, &user_rid); status = domain->methods->query_user(domain, mem_ctx, &user_sid,
status = domain->methods->query_user(domain, mem_ctx, user_rid,
&user_info); &user_info);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -158,7 +156,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* Now take all this information and fill in a passwd structure */ /* Now take all this information and fill in a passwd structure */
if (!winbindd_fill_pwent(name_domain, name_user, if (!winbindd_fill_pwent(name_domain, name_user,
user_rid, user_info.group_rid, user_info.user_sid, user_info.group_sid,
user_info.full_name, user_info.full_name,
&state->response.data.pw)) { &state->response.data.pw)) {
talloc_destroy(mem_ctx); talloc_destroy(mem_ctx);
@ -176,7 +174,6 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
{ {
DOM_SID user_sid; DOM_SID user_sid;
struct winbindd_domain *domain; struct winbindd_domain *domain;
uint32 user_rid;
fstring dom_name; fstring dom_name;
fstring user_name; fstring user_name;
enum SID_NAME_USE name_type; enum SID_NAME_USE name_type;
@ -196,18 +193,15 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
/* Get rid from uid */ /* Get rid from uid */
if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid, if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid,
&user_rid, &domain)) { &user_sid)) {
DEBUG(1, ("could not convert uid %d to rid\n", DEBUG(1, ("could not convert uid %d to SID\n",
state->request.data.uid)); state->request.data.uid));
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
/* Get name and name type from rid */ /* Get name and name type from rid */
sid_copy(&user_sid, &domain->sid);
sid_append_rid(&user_sid, user_rid);
if (!winbindd_lookup_name_by_sid(&user_sid, dom_name, user_name, &name_type)) { if (!winbindd_lookup_name_by_sid(&user_sid, dom_name, user_name, &name_type)) {
fstring temp; fstring temp;
@ -216,6 +210,13 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
domain = find_domain_from_sid(&user_sid);
if (!domain) {
DEBUG(1,("Can't find domain from sid\n"));
return WINBINDD_ERROR;
}
/* Get some user info */ /* Get some user info */
if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)", if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)",
@ -225,7 +226,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
return WINBINDD_ERROR; return WINBINDD_ERROR;
} }
status = domain->methods->query_user(domain, mem_ctx, user_rid, status = domain->methods->query_user(domain, mem_ctx, &user_sid,
&user_info); &user_info);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -237,7 +238,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
/* Resolve gid number */ /* Resolve gid number */
if (!winbindd_idmap_get_gid_from_rid(domain->name, user_info.group_rid, &gid)) { if (!winbindd_idmap_get_gid_from_sid(user_info.group_sid, &gid)) {
DEBUG(1, ("error getting group id for user %s\n", user_name)); DEBUG(1, ("error getting group id for user %s\n", user_name));
talloc_destroy(mem_ctx); talloc_destroy(mem_ctx);
return WINBINDD_ERROR; return WINBINDD_ERROR;
@ -245,7 +246,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
/* Fill in password structure */ /* Fill in password structure */
if (!winbindd_fill_pwent(domain->name, user_name, user_rid, user_info.group_rid, if (!winbindd_fill_pwent(domain->name, user_name, user_info.user_sid,
user_info.group_sid,
user_info.full_name, &state->response.data.pw)) { user_info.full_name, &state->response.data.pw)) {
talloc_destroy(mem_ctx); talloc_destroy(mem_ctx);
return WINBINDD_ERROR; return WINBINDD_ERROR;
@ -332,13 +334,13 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
struct winbindd_domain *domain; struct winbindd_domain *domain;
struct winbindd_methods *methods; struct winbindd_methods *methods;
int i; unsigned int i;
if (ent->num_sam_entries) if (ent->num_sam_entries)
return False; return False;
if (!(mem_ctx = talloc_init("get_sam_user_entries(%s)", if (!(mem_ctx = talloc_init("get_sam_user_entries(%s)",
ent->domain_name))) ent->domain_name)))
return False; return False;
if (!(domain = find_domain_from_name(ent->domain_name))) { if (!(domain = find_domain_from_name(ent->domain_name))) {
@ -393,8 +395,8 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
} }
/* User and group ids */ /* User and group ids */
name_list[ent->num_sam_entries+i].user_rid = info[i].user_rid; sid_copy(&name_list[ent->num_sam_entries+i].user_sid, info[i].user_sid);
name_list[ent->num_sam_entries+i].group_rid = info[i].group_rid; sid_copy(&name_list[ent->num_sam_entries+i].group_sid, info[i].group_sid);
} }
ent->num_sam_entries += num_entries; ent->num_sam_entries += num_entries;
@ -491,8 +493,8 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
result = winbindd_fill_pwent( result = winbindd_fill_pwent(
ent->domain_name, ent->domain_name,
name_list[ent->sam_entry_index].name, name_list[ent->sam_entry_index].name,
name_list[ent->sam_entry_index].user_rid, &name_list[ent->sam_entry_index].user_sid,
name_list[ent->sam_entry_index].group_rid, &name_list[ent->sam_entry_index].group_sid,
name_list[ent->sam_entry_index].gecos, name_list[ent->sam_entry_index].gecos,
&user_list[user_list_ndx]); &user_list[user_list_ndx]);
@ -539,7 +541,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
for (domain = domain_list(); domain; domain = domain->next) { for (domain = domain_list(); domain; domain = domain->next) {
NTSTATUS status; NTSTATUS status;
struct winbindd_methods *methods; struct winbindd_methods *methods;
int i; unsigned int i;
methods = domain->methods; methods = domain->methods;

View File

@ -179,7 +179,7 @@ void rescan_trusted_domains(BOOL force)
int i; int i;
result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains, result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains,
&names, &alt_names, &dom_sids); &names, &alt_names, &dom_sids);
if (!NT_STATUS_IS_OK(result)) { if (!NT_STATUS_IS_OK(result)) {
continue; continue;
} }
@ -188,9 +188,12 @@ void rescan_trusted_domains(BOOL force)
the access methods of its parent */ the access methods of its parent */
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], add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
alt_names?alt_names[i]:NULL, domain->methods, &dom_sids[i]);
domain->methods, &dom_sids[i]);
/* store trusted domain in the cache */
trustdom_cache_store(names[i], alt_names ? alt_names[i] : NULL,
&dom_sids[i], t + WINBINDD_RESCAN_FREQ);
} }
} }
@ -268,14 +271,20 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
enum SID_NAME_USE *type) enum SID_NAME_USE *type)
{ {
NTSTATUS result; NTSTATUS result;
TALLOC_CTX *mem_ctx;
/* Don't bother with machine accounts */ /* Don't bother with machine accounts */
if (name[strlen(name) - 1] == '$') if (name[strlen(name) - 1] == '$')
return False; return False;
mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name);
if (!mem_ctx)
return False;
/* Lookup name */ /* Lookup name */
result = domain->methods->name_to_sid(domain, name, sid, type); result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type);
talloc_destroy(mem_ctx);
/* Return rid and type if lookup successful */ /* Return rid and type if lookup successful */
if (!NT_STATUS_IS_OK(result)) { if (!NT_STATUS_IS_OK(result)) {
@ -549,3 +558,20 @@ int winbindd_num_clients(void)
{ {
return _num_clients; return _num_clients;
} }
/* Help with RID -> SID conversion */
DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 rid)
{
DOM_SID *sid;
sid = talloc(mem_ctx, sizeof(*sid));
if (!sid) {
smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n");
}
sid_copy(sid, &domain->sid);
sid_append_rid(sid, rid);
return sid;
}

View File

@ -163,6 +163,7 @@ typedef struct
BOOL bWinbindEnumUsers; BOOL bWinbindEnumUsers;
BOOL bWinbindEnumGroups; BOOL bWinbindEnumGroups;
BOOL bWinbindUseDefaultDomain; BOOL bWinbindUseDefaultDomain;
char *szWinbindBackend;
char *szAddShareCommand; char *szAddShareCommand;
char *szChangeShareCommand; char *szChangeShareCommand;
char *szDeleteShareCommand; char *szDeleteShareCommand;
@ -1113,6 +1114,7 @@ static struct parm_struct parm_table[] = {
{"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind backend", P_STRING, P_GLOBAL, &Globals.szWinbindBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0} {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
}; };
@ -1459,6 +1461,8 @@ static void init_globals(void)
Globals.bWinbindEnumGroups = True; Globals.bWinbindEnumGroups = True;
Globals.bWinbindUseDefaultDomain = False; Globals.bWinbindUseDefaultDomain = False;
string_set(&Globals.szWinbindBackend, "tdb");
Globals.name_cache_timeout = 660; /* In seconds */ Globals.name_cache_timeout = 660; /* In seconds */
Globals.bUseSpnego = True; Globals.bUseSpnego = True;
@ -1630,6 +1634,7 @@ FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers) FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups) FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain) FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
FN_GLOBAL_STRING(lp_winbind_backend, &Globals.szWinbindBackend)
#ifdef WITH_LDAP_SAMCONFIG #ifdef WITH_LDAP_SAMCONFIG
FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer) FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)

View File

@ -877,6 +877,7 @@ static BOOL init_structs(void )
smbd_process(); smbd_process();
uni_group_cache_shutdown(); uni_group_cache_shutdown();
namecache_shutdown();
exit_server("normal exit"); exit_server("normal exit");
return(0); return(0);
} }