2000-05-09 11:43:00 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
2000-05-09 11:43:00 +00:00
Winbind daemon for ntdom nss module
Copyright ( C ) Tim Potter 2000
2001-11-27 22:39:57 +00:00
Copyright ( C ) Jeremy Allison 2001.
2003-06-30 17:24:59 +00:00
Copyright ( C ) Gerald ( Jerry ) Carter 2003.
2005-01-15 19:00:18 +00:00
Copyright ( C ) Volker Lendecke 2005
2000-05-09 11:43:00 +00:00
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 0213 9 , USA .
*/
2003-11-12 01:51:10 +00:00
# include "includes.h"
2000-05-09 11:43:00 +00:00
# include "winbindd.h"
2004-03-16 18:54:09 +00:00
extern BOOL opt_nocache ;
2002-07-15 10:35:28 +00:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2001-11-27 22:39:57 +00:00
/***************************************************************
Empty static struct for negative caching .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-09 11:43:00 +00:00
/* Fill a grent structure from various other information */
2002-01-20 01:24:59 +00:00
static BOOL fill_grent ( struct winbindd_gr * gr , const char * dom_name ,
const char * gr_name , gid_t unix_gid )
2000-05-09 11:43:00 +00:00
{
2002-01-20 01:24:59 +00:00
fstring full_group_name ;
2001-05-07 04:32:40 +00:00
/* Fill in uid/gid */
2002-01-20 01:24:59 +00:00
fill_domain_username ( full_group_name , dom_name , gr_name ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
gr - > gr_gid = unix_gid ;
/* Group name and password */
2002-01-20 01:24:59 +00:00
safe_strcpy ( gr - > gr_name , full_group_name , sizeof ( gr - > gr_name ) - 1 ) ;
2001-05-07 04:32:40 +00:00
safe_strcpy ( gr - > gr_passwd , " x " , sizeof ( gr - > gr_passwd ) - 1 ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
return True ;
2000-05-09 11:43:00 +00:00
}
2003-04-23 11:54:56 +00:00
/* Fill in the group membership field of a NT group given by group_sid */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
static BOOL fill_grent_mem ( struct winbindd_domain * domain ,
2003-04-23 11:54:56 +00:00
DOM_SID * group_sid ,
2001-05-07 04:32:40 +00:00
enum SID_NAME_USE group_name_type ,
2005-10-18 03:24:00 +00:00
size_t * num_gr_mem , char * * gr_mem , size_t * gr_mem_len )
2000-05-09 11:43:00 +00:00
{
2005-06-08 22:10:34 +00:00
DOM_SID * sid_mem = NULL ;
2003-04-23 11:54:56 +00:00
uint32 num_names = 0 ;
2001-09-05 08:11:17 +00:00
uint32 * name_types = NULL ;
2003-04-23 11:54:56 +00:00
unsigned int buf_len , buf_ndx , i ;
2001-05-07 04:32:40 +00:00
char * * names = NULL , * buf ;
BOOL result = False ;
2001-11-27 22:39:57 +00:00
TALLOC_CTX * mem_ctx ;
2001-12-05 04:48:51 +00:00
NTSTATUS status ;
2003-04-23 11:54:56 +00:00
fstring sid_string ;
2001-10-19 01:46:43 +00:00
2002-12-20 20:21:31 +00:00
if ( ! ( mem_ctx = talloc_init ( " fill_grent_mem(%s) " , domain - > name ) ) )
2001-11-27 22:39:57 +00:00
return False ;
2001-10-19 01:46:43 +00:00
2001-05-07 04:32:40 +00:00
/* Initialise group membership information */
2003-04-23 11:54:56 +00:00
DEBUG ( 10 , ( " group SID %s \n " , sid_to_string ( sid_string , group_sid ) ) ) ;
2001-05-07 04:32:40 +00:00
* num_gr_mem = 0 ;
2004-04-07 12:43:44 +00:00
/* HACK ALERT!! This whole routine does not cope with group members
* from more than one domain , ie aliases . Thus we have to work it out
* ourselves in a special routine . */
if ( domain - > internal )
return fill_passdb_alias_grmem ( domain , group_sid ,
num_gr_mem ,
gr_mem , gr_mem_len ) ;
2001-05-07 04:32:40 +00:00
2003-06-23 05:10:07 +00:00
if ( ! ( ( group_name_type = = SID_NAME_DOM_GRP ) | |
2004-01-08 02:15:46 +00:00
( ( group_name_type = = SID_NAME_ALIAS ) & & domain - > primary ) ) )
2003-06-23 05:10:07 +00:00
{
2003-06-16 01:12:42 +00:00
DEBUG ( 1 , ( " SID %s in domain %s isn't a domain group (%d) \n " ,
sid_to_string ( sid_string , group_sid ) , domain - > name ,
group_name_type ) ) ;
2001-10-19 01:46:43 +00:00
goto done ;
2001-05-07 04:32:40 +00:00
}
/* Lookup group members */
2003-04-23 11:54:56 +00:00
status = domain - > methods - > lookup_groupmem ( domain , mem_ctx , group_sid , & num_names ,
& sid_mem , & names , & name_types ) ;
2001-12-05 04:48:51 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-04-23 11:54:56 +00:00
DEBUG ( 1 , ( " could not lookup membership for group rid %s in domain %s (error: %s) \n " ,
sid_to_string ( sid_string , group_sid ) , domain - > name , nt_errstr ( status ) ) ) ;
2001-05-07 04:32:40 +00:00
2001-10-19 01:46:43 +00:00
goto done ;
2001-05-07 04:32:40 +00:00
}
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " looked up %d names \n " , num_names ) ) ;
2001-05-07 04:32:40 +00:00
if ( DEBUGLEVEL > = 10 ) {
2001-10-19 01:46:43 +00:00
for ( i = 0 ; i < num_names ; i + + )
2005-06-08 22:10:34 +00:00
DEBUG ( 10 , ( " \t %20s %s %d \n " , names [ i ] ,
sid_string_static ( & sid_mem [ i ] ) ,
2001-05-07 04:32:40 +00:00
name_types [ i ] ) ) ;
}
/* Add members to list */
buf = NULL ;
buf_len = buf_ndx = 0 ;
again :
for ( i = 0 ; i < num_names ; i + + ) {
char * the_name ;
fstring name ;
int len ;
the_name = names [ i ] ;
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " processing name %s \n " , the_name ) ) ;
2001-05-07 04:32:40 +00:00
2001-10-31 06:20:58 +00:00
/* FIXME: need to cope with groups within groups. These
occur in Universal groups on a Windows 2000 native mode
server . */
2001-05-07 04:32:40 +00:00
2004-01-07 23:46:47 +00:00
/* make sure to allow machine accounts */
2001-05-07 04:32:40 +00:00
2004-01-07 23:46:47 +00:00
if ( name_types [ i ] ! = SID_NAME_USER & & name_types [ i ] ! = SID_NAME_COMPUTER ) {
2006-02-03 22:19:41 +00:00
DEBUG ( 3 , ( " name %s isn't a domain user (%s) \n " , the_name , sid_type_lookup ( name_types [ i ] ) ) ) ;
2001-05-07 04:32:40 +00:00
continue ;
}
/* Append domain name */
2002-01-18 02:37:55 +00:00
fill_domain_username ( name , domain - > name , the_name ) ;
2001-05-07 04:32:40 +00:00
len = strlen ( name ) ;
/* Add to list or calculate buffer length */
if ( ! buf ) {
buf_len + = len + 1 ; /* List is comma separated */
( * num_gr_mem ) + + ;
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " buf_len + %d = %d \n " , len + 1 , buf_len ) ) ;
2001-05-07 04:32:40 +00:00
} else {
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " appending %s at ndx %d \n " , name , len ) ) ;
2001-05-07 04:32:40 +00:00
safe_strcpy ( & buf [ buf_ndx ] , name , len ) ;
buf_ndx + = len ;
buf [ buf_ndx ] = ' , ' ;
buf_ndx + + ;
}
}
/* Allocate buffer */
2002-03-26 19:45:28 +00:00
if ( ! buf & & buf_len ! = 0 ) {
2004-12-07 18:25:53 +00:00
if ( ! ( buf = SMB_MALLOC ( buf_len ) ) ) {
2002-01-10 06:20:03 +00:00
DEBUG ( 1 , ( " out of memory \n " ) ) ;
2001-05-07 04:32:40 +00:00
result = False ;
2001-10-19 01:46:43 +00:00
goto done ;
2001-05-07 04:32:40 +00:00
}
memset ( buf , 0 , buf_len ) ;
goto again ;
}
if ( buf & & buf_ndx > 0 ) {
buf [ buf_ndx - 1 ] = ' \0 ' ;
}
* gr_mem = buf ;
* gr_mem_len = buf_len ;
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " num_mem = %d, len = %d, mem = %s \n " , * num_gr_mem ,
buf_len , * num_gr_mem ? buf : " NULL " ) ) ;
2001-05-07 04:32:40 +00:00
result = True ;
2001-10-19 01:46:43 +00:00
done :
2001-11-27 22:39:57 +00:00
2001-11-27 06:28:06 +00:00
talloc_destroy ( mem_ctx ) ;
2001-05-07 04:32:40 +00:00
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " fill_grent_mem returning %d \n " , result ) ) ;
2001-05-07 04:32:40 +00:00
return result ;
2000-05-09 11:43:00 +00:00
}
2001-05-07 04:32:40 +00:00
/* Return a group structure from a group name */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getgrnam ( struct winbindd_cli_state * state )
2001-05-07 04:32:40 +00:00
{
DOM_SID group_sid ;
struct winbindd_domain * domain ;
enum SID_NAME_USE name_type ;
2002-01-20 01:24:59 +00:00
fstring name_domain , name_group ;
2001-05-07 04:32:40 +00:00
char * tmp , * gr_mem ;
2005-10-18 03:24:00 +00:00
size_t gr_mem_len ;
2003-05-12 18:12:31 +00:00
gid_t gid ;
2006-02-03 22:19:41 +00:00
union unid_t id ;
NTSTATUS status ;
2001-05-07 04:32:40 +00:00
2002-08-17 17:00:51 +00:00
/* Ensure null termination */
state - > request . data . groupname [ sizeof ( state - > request . data . groupname ) - 1 ] = ' \0 ' ;
2003-07-22 06:52:39 +00:00
DEBUG ( 3 , ( " [%5lu]: getgrnam %s \n " , ( unsigned long ) state - > pid ,
2001-05-07 04:32:40 +00:00
state - > request . data . groupname ) ) ;
/* Parse domain and groupname */
memset ( name_group , 0 , sizeof ( fstring ) ) ;
tmp = state - > request . data . groupname ;
2003-07-09 16:44:47 +00:00
parse_domain_user ( tmp , name_domain , name_group ) ;
2005-06-08 22:10:34 +00:00
/* if no domain or our local domain and no local tdb group, default to
* our local domain for aliases */
2004-04-07 12:43:44 +00:00
if ( ! * name_domain | | strequal ( name_domain , get_global_sam_name ( ) ) ) {
fstrcpy ( name_domain , get_global_sam_name ( ) ) ;
}
2001-05-07 04:32:40 +00:00
/* Get info for the domain */
if ( ( domain = find_domain_from_name ( name_domain ) ) = = NULL ) {
2004-01-08 02:15:46 +00:00
DEBUG ( 3 , ( " could not get domain sid for domain %s \n " ,
2002-01-10 06:20:03 +00:00
name_domain ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2004-01-08 02:15:46 +00:00
/* should we deal with users for our domain? */
if ( lp_winbind_trusted_domains_only ( ) & & domain - > primary ) {
2006-02-03 22:19:41 +00:00
DEBUG ( 7 , ( " winbindd_getgrnam: My domain -- rejecting "
" getgrnam() for %s \\ %s. \n " , name_domain , name_group ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2004-01-08 02:15:46 +00:00
}
2001-05-07 04:32:40 +00:00
/* Get rid and name type from name */
2005-06-08 22:10:34 +00:00
if ( ! winbindd_lookup_sid_by_name ( state - > mem_ctx , domain , domain - > name ,
name_group , & group_sid , & name_type ) ) {
2001-05-07 04:32:40 +00:00
DEBUG ( 1 , ( " group %s in domain %s does not exist \n " ,
name_group , name_domain ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2003-06-23 05:10:07 +00:00
if ( ! ( ( name_type = = SID_NAME_DOM_GRP ) | |
2004-04-07 12:43:44 +00:00
( ( name_type = = SID_NAME_ALIAS ) & & domain - > primary ) | |
2005-09-16 13:01:25 +00:00
( ( name_type = = SID_NAME_ALIAS ) & & domain - > internal ) | |
( ( name_type = = SID_NAME_WKN_GRP ) & & domain - > internal ) ) )
2003-06-23 05:10:07 +00:00
{
2006-02-03 22:19:41 +00:00
DEBUG ( 1 , ( " name '%s' is not a local, domain or builtin "
" group: %d \n " , name_group , name_type ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2006-02-03 22:19:41 +00:00
/* Try to get the GID */
status = idmap_sid_to_gid ( & group_sid , & gid , 0 ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto got_gid ;
}
/* Maybe it's one of our aliases in passdb */
if ( pdb_sid_to_id ( & group_sid , & id , & name_type ) & &
( ( name_type = = SID_NAME_ALIAS ) | |
( name_type = = SID_NAME_WKN_GRP ) ) ) {
gid = id . gid ;
goto got_gid ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2006-02-03 22:19:41 +00:00
DEBUG ( 1 , ( " error converting unix gid to sid \n " ) ) ;
request_error ( state ) ;
return ;
got_gid :
2002-01-20 01:24:59 +00:00
if ( ! fill_grent ( & state - > response . data . gr , name_domain ,
name_group , gid ) | |
2003-04-23 11:54:56 +00:00
! fill_grent_mem ( domain , & group_sid , name_type ,
2001-05-07 04:32:40 +00:00
& state - > response . data . gr . num_gr_mem ,
2001-11-27 22:39:57 +00:00
& gr_mem , & gr_mem_len ) ) {
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-11-27 22:39:57 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Group membership lives at start of extra data */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . data . gr . gr_mem_ofs = 0 ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . length + = gr_mem_len ;
state - > response . extra_data = gr_mem ;
2005-06-20 13:42:29 +00:00
request_ok ( state ) ;
2000-05-09 11:43:00 +00:00
}
2001-05-07 04:32:40 +00:00
/* Return a group structure from a gid number */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getgrgid ( struct winbindd_cli_state * state )
2001-05-07 04:32:40 +00:00
{
struct winbindd_domain * domain ;
DOM_SID group_sid ;
enum SID_NAME_USE name_type ;
2002-01-20 01:24:59 +00:00
fstring dom_name ;
2001-05-07 04:32:40 +00:00
fstring group_name ;
2005-10-18 03:24:00 +00:00
size_t gr_mem_len ;
2001-05-07 04:32:40 +00:00
char * gr_mem ;
2006-02-03 22:19:41 +00:00
NTSTATUS status ;
2000-05-09 11:43:00 +00:00
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: getgrgid %lu \n " , ( unsigned long ) state - > pid ,
( unsigned long ) state - > request . data . gid ) ) ;
2001-10-10 23:08:13 +00:00
2001-05-07 04:32:40 +00:00
/* Bug out if the gid isn't in the winbind range */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
if ( ( state - > request . data . gid < server_state . gid_low ) | |
2005-06-20 13:42:29 +00:00
( state - > request . data . gid > server_state . gid_high ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 11:43:00 +00:00
2006-02-03 22:19:41 +00:00
/* Get sid from gid */
status = idmap_gid_to_sid ( & group_sid , state - > request . data . gid , 0 ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* This is a remote one */
goto got_sid ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2006-02-03 22:19:41 +00:00
/* Ok, this might be "ours", i.e. an alias */
if ( pdb_gid_to_sid ( state - > request . data . gid , & group_sid ) & &
lookup_sid ( state - > mem_ctx , & group_sid , NULL , NULL , & name_type ) & &
( name_type = = SID_NAME_ALIAS ) ) {
/* Hey, got an alias */
goto got_sid ;
}
DEBUG ( 1 , ( " could not convert gid %lu to sid \n " ,
( unsigned long ) state - > request . data . gid ) ) ;
request_error ( state ) ;
return ;
got_sid :
2003-04-23 11:54:56 +00:00
/* Get name from sid */
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
if ( ! winbindd_lookup_name_by_sid ( state - > mem_ctx , & group_sid , dom_name ,
group_name , & name_type ) ) {
2002-01-10 06:20:03 +00:00
DEBUG ( 1 , ( " could not lookup sid \n " ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Fill in group structure */
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
domain = find_domain_from_sid_noinit ( & group_sid ) ;
2003-04-23 11:54:56 +00:00
if ( ! domain ) {
DEBUG ( 1 , ( " Can't find domain from sid \n " ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2003-04-23 11:54:56 +00:00
}
2003-06-23 19:05:23 +00:00
if ( ! ( ( name_type = = SID_NAME_DOM_GRP ) | |
2004-04-07 12:43:44 +00:00
( ( name_type = = SID_NAME_ALIAS ) & & domain - > primary ) | |
( ( name_type = = SID_NAME_ALIAS ) & & domain - > internal ) ) )
2003-06-23 19:05:23 +00:00
{
DEBUG ( 1 , ( " name '%s' is not a local or domain group: %d \n " ,
group_name , name_type ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2003-06-23 19:05:23 +00:00
}
2002-01-20 01:24:59 +00:00
if ( ! fill_grent ( & state - > response . data . gr , dom_name , group_name ,
2001-05-07 04:32:40 +00:00
state - > request . data . gid ) | |
2003-04-23 11:54:56 +00:00
! fill_grent_mem ( domain , & group_sid , name_type ,
2001-05-07 04:32:40 +00:00
& state - > response . data . gr . num_gr_mem ,
2005-06-20 13:42:29 +00:00
& gr_mem , & gr_mem_len ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Group membership lives at start of extra data */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . data . gr . gr_mem_ofs = 0 ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . length + = gr_mem_len ;
state - > response . extra_data = gr_mem ;
2005-06-20 13:42:29 +00:00
request_ok ( state ) ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/*
* set / get / endgrent functions
*/
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* "Rewind" file pointer for group database enumeration */
2000-05-09 11:43:00 +00:00
2005-06-24 14:25:18 +00:00
static BOOL winbindd_setgrent_internal ( struct winbindd_cli_state * state )
2001-05-07 04:32:40 +00:00
{
2002-01-10 06:20:03 +00:00
struct winbindd_domain * domain ;
2001-05-07 04:32:40 +00:00
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: setgrent \n " , ( unsigned long ) state - > pid ) ) ;
2001-05-07 04:32:40 +00:00
/* Check user has enabled this */
2005-06-20 13:42:29 +00:00
if ( ! lp_winbind_enum_groups ( ) ) {
2005-06-24 14:25:18 +00:00
return False ;
2005-06-20 13:42:29 +00:00
}
2001-05-07 04:32:40 +00:00
/* Free old static data if it exists */
if ( state - > getgrent_state ! = NULL ) {
free_getent_state ( state - > getgrent_state ) ;
state - > getgrent_state = NULL ;
}
/* Create sam pipes for each domain we know about */
2002-01-11 05:33:45 +00:00
for ( domain = domain_list ( ) ; domain ! = NULL ; domain = domain - > next ) {
2001-05-07 04:32:40 +00:00
struct getent_state * domain_state ;
2004-04-20 02:37:49 +00:00
/* Create a state record for this domain */
2003-07-07 05:11:10 +00:00
/* don't add our domaina if we are a PDC or if we
are a member of a Samba domain */
2003-06-30 17:24:59 +00:00
2004-04-20 02:37:49 +00:00
if ( lp_winbind_trusted_domains_only ( ) & & domain - > primary )
2003-07-07 05:11:10 +00:00
{
2003-06-30 17:24:59 +00:00
continue ;
2003-07-07 05:11:10 +00:00
}
2003-06-30 17:24:59 +00:00
2001-05-07 04:32:40 +00:00
2004-12-07 18:25:53 +00:00
if ( ( domain_state = SMB_MALLOC_P ( struct getent_state ) ) = = NULL ) {
2002-07-15 10:35:28 +00:00
DEBUG ( 1 , ( " winbindd_setgrent: malloc failed for domain_state! \n " ) ) ;
2005-06-24 14:25:18 +00:00
return False ;
2002-07-15 10:35:28 +00:00
}
2001-05-07 04:32:40 +00:00
ZERO_STRUCTP ( domain_state ) ;
2002-01-11 05:33:45 +00:00
fstrcpy ( domain_state - > domain_name , domain - > name ) ;
2001-10-19 01:46:43 +00:00
2001-05-07 04:32:40 +00:00
/* Add to list of open domains */
DLIST_ADD ( state - > getgrent_state , domain_state ) ;
}
2004-04-28 20:07:51 +00:00
state - > getgrent_initialized = True ;
2005-06-24 14:25:18 +00:00
return True ;
}
void winbindd_setgrent ( struct winbindd_cli_state * state )
{
if ( winbindd_setgrent_internal ( state ) ) {
request_ok ( state ) ;
} else {
request_error ( state ) ;
}
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Close file pointer to ntdom group database */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_endgrent ( struct winbindd_cli_state * state )
2001-05-07 04:32:40 +00:00
{
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: endgrent \n " , ( unsigned long ) state - > pid ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
free_getent_state ( state - > getgrent_state ) ;
2004-04-28 20:07:51 +00:00
state - > getgrent_initialized = False ;
2001-05-07 04:32:40 +00:00
state - > getgrent_state = NULL ;
2005-06-20 13:42:29 +00:00
request_ok ( state ) ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Get the list of domain groups and domain aliases for a domain. We fill in
the sam_entries and num_sam_entries fields with domain group information .
The dispinfo_ndx field is incremented to the index of the next group to
fetch . Return True if some groups were returned , False otherwise . */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
static BOOL get_sam_group_entries ( struct getent_state * ent )
{
2001-09-04 07:13:01 +00:00
NTSTATUS status ;
uint32 num_entries ;
2002-10-08 18:32:42 +00:00
struct acct_info * name_list = NULL , * tmp_name_list = NULL ;
2001-11-27 22:39:57 +00:00
TALLOC_CTX * mem_ctx ;
BOOL result = False ;
2001-12-11 01:04:13 +00:00
struct acct_info * sam_grp_entries = NULL ;
2002-01-11 05:33:45 +00:00
struct winbindd_domain * domain ;
2001-05-07 04:32:40 +00:00
2001-12-11 01:04:13 +00:00
if ( ent - > got_sam_entries )
2001-05-07 04:32:40 +00:00
return False ;
2002-12-20 20:21:31 +00:00
if ( ! ( mem_ctx = talloc_init ( " get_sam_group_entries(%s) " ,
2002-07-15 10:35:28 +00:00
ent - > domain_name ) ) ) {
DEBUG ( 1 , ( " get_sam_group_entries: could not create talloc context! \n " ) ) ;
2001-11-27 22:39:57 +00:00
return False ;
2002-07-15 10:35:28 +00:00
}
2001-05-07 04:32:40 +00:00
/* Free any existing group info */
2001-09-17 04:52:45 +00:00
SAFE_FREE ( ent - > sam_entries ) ;
ent - > num_sam_entries = 0 ;
2001-12-11 01:04:13 +00:00
ent - > got_sam_entries = True ;
2001-05-07 04:32:40 +00:00
2001-12-11 01:04:13 +00:00
/* Enumerate domain groups */
2002-01-11 05:33:45 +00:00
2001-12-11 01:04:13 +00:00
num_entries = 0 ;
2001-05-07 04:32:40 +00:00
2002-01-11 05:33:45 +00:00
if ( ! ( domain = find_domain_from_name ( ent - > domain_name ) ) ) {
DEBUG ( 3 , ( " no such domain %s in get_sam_group_entries \n " , ent - > domain_name ) ) ;
goto done ;
}
2002-10-08 18:32:42 +00:00
/* always get the domain global groups */
status = domain - > methods - > enum_dom_groups ( domain , mem_ctx , & num_entries , & sam_grp_entries ) ;
2001-12-11 01:04:13 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-02-25 23:54:40 +00:00
DEBUG ( 3 , ( " get_sam_group_entries: could not enumerate domain groups! Error: %s \n " , nt_errstr ( status ) ) ) ;
2001-12-11 01:04:13 +00:00
result = False ;
goto done ;
}
2001-05-07 04:32:40 +00:00
2001-12-11 01:04:13 +00:00
/* Copy entries into return buffer */
2002-01-11 05:33:45 +00:00
2001-12-11 01:04:13 +00:00
if ( num_entries ) {
2004-12-07 18:25:53 +00:00
if ( ! ( name_list = SMB_MALLOC_ARRAY ( struct acct_info , num_entries ) ) ) {
2002-10-08 18:32:42 +00:00
DEBUG ( 0 , ( " get_sam_group_entries: Failed to malloc memory for %d domain groups! \n " ,
num_entries ) ) ;
result = False ;
goto done ;
}
memcpy ( name_list , sam_grp_entries , num_entries * sizeof ( struct acct_info ) ) ;
2001-12-11 01:04:13 +00:00
}
ent - > num_sam_entries = num_entries ;
2002-10-08 18:32:42 +00:00
2003-06-23 05:10:07 +00:00
/* get the domain local groups if we are a member of a native win2k domain
and are not using LDAP to get the groups */
2002-10-08 18:32:42 +00:00
2004-04-07 12:43:44 +00:00
if ( ( lp_security ( ) ! = SEC_ADS & & domain - > native_mode
& & domain - > primary ) | | domain - > internal )
2002-10-08 18:32:42 +00:00
{
2005-09-16 13:01:25 +00:00
DEBUG ( 4 , ( " get_sam_group_entries: %s domain; enumerating local groups as well \n " ,
2005-09-16 13:12:08 +00:00
domain - > native_mode ? " Native Mode 2k " : " BUILTIN or local " ) ) ;
2002-10-08 18:32:42 +00:00
status = domain - > methods - > enum_local_groups ( domain , mem_ctx , & num_entries , & sam_grp_entries ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " get_sam_group_entries: Failed to enumerate domain local groups! \n " ) ) ;
num_entries = 0 ;
}
else
DEBUG ( 4 , ( " get_sam_group_entries: Returned %d local groups \n " , num_entries ) ) ;
/* Copy entries into return buffer */
if ( num_entries ) {
2004-12-07 18:25:53 +00:00
if ( ! ( tmp_name_list = SMB_REALLOC_ARRAY ( name_list , struct acct_info , ent - > num_sam_entries + num_entries ) ) )
2002-10-08 18:32:42 +00:00
{
DEBUG ( 0 , ( " get_sam_group_entries: Failed to realloc more memory for %d local groups! \n " ,
num_entries ) ) ;
result = False ;
SAFE_FREE ( name_list ) ;
goto done ;
}
name_list = tmp_name_list ;
memcpy ( & name_list [ ent - > num_sam_entries ] , sam_grp_entries ,
num_entries * sizeof ( struct acct_info ) ) ;
}
ent - > num_sam_entries + = num_entries ;
}
2001-05-07 04:32:40 +00:00
/* Fill in remaining fields */
2002-01-11 05:33:45 +00:00
2001-05-07 04:32:40 +00:00
ent - > sam_entries = name_list ;
ent - > sam_entry_index = 0 ;
2001-10-19 08:22:52 +00:00
result = ( ent - > num_sam_entries > 0 ) ;
done :
2001-11-27 22:39:57 +00:00
talloc_destroy ( mem_ctx ) ;
return result ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Fetch next group entry from ntdom database */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
# define MAX_GETGRENT_GROUPS 500
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getgrent ( struct winbindd_cli_state * state )
2001-05-07 04:32:40 +00:00
{
struct getent_state * ent ;
struct winbindd_gr * group_list = NULL ;
int num_groups , group_list_ndx = 0 , i , gr_mem_list_len = 0 ;
2002-01-20 01:24:59 +00:00
char * new_extra_data , * gr_mem_list = NULL ;
2000-05-09 11:43:00 +00:00
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: getgrent \n " , ( unsigned long ) state - > pid ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Check user has enabled this */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
if ( ! lp_winbind_enum_groups ( ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
num_groups = MIN ( MAX_GETGRENT_GROUPS , state - > request . data . num_entries ) ;
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
if ( ( state - > response . extra_data = SMB_MALLOC_ARRAY ( struct winbindd_gr , num_groups ) ) = = NULL ) {
request_error ( state ) ;
return ;
}
2000-05-09 11:43:00 +00:00
2004-05-07 18:14:38 +00:00
memset ( state - > response . extra_data , ' \0 ' ,
num_groups * sizeof ( struct winbindd_gr ) ) ;
2001-05-07 04:32:40 +00:00
state - > response . data . num_entries = 0 ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
group_list = ( struct winbindd_gr * ) state - > response . extra_data ;
2000-05-09 11:43:00 +00:00
2004-04-28 20:07:51 +00:00
if ( ! state - > getgrent_initialized )
2005-06-24 14:25:18 +00:00
winbindd_setgrent_internal ( state ) ;
2004-04-28 20:07:51 +00:00
2005-06-20 13:42:29 +00:00
if ( ! ( ent = state - > getgrent_state ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Start sending back groups */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
for ( i = 0 ; i < num_groups ; i + + ) {
struct acct_info * name_list = NULL ;
fstring domain_group_name ;
uint32 result ;
gid_t group_gid ;
2005-10-18 03:24:00 +00:00
size_t gr_mem_len ;
2001-12-04 06:17:39 +00:00
char * gr_mem , * new_gr_mem_list ;
2003-04-23 11:54:56 +00:00
DOM_SID group_sid ;
struct winbindd_domain * domain ;
2001-05-07 04:32:40 +00:00
/* Do we need to fetch another chunk of groups? */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
tryagain :
2000-05-09 11:43:00 +00:00
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " entry_index = %d, num_entries = %d \n " ,
2001-05-07 04:32:40 +00:00
ent - > sam_entry_index , ent - > num_sam_entries ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
if ( ent - > num_sam_entries = = ent - > sam_entry_index ) {
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
while ( ent & & ! get_sam_group_entries ( ent ) ) {
struct getent_state * next_ent ;
2000-05-09 11:43:00 +00:00
2002-01-11 05:33:45 +00:00
DEBUG ( 10 , ( " freeing state info for domain %s \n " , ent - > domain_name ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Free state information for this domain */
2000-05-09 11:43:00 +00:00
2001-09-17 04:52:45 +00:00
SAFE_FREE ( ent - > sam_entries ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
next_ent = ent - > next ;
DLIST_REMOVE ( state - > getgrent_state , ent ) ;
2001-09-17 04:52:45 +00:00
SAFE_FREE ( ent ) ;
2001-05-07 04:32:40 +00:00
ent = next_ent ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* No more domains */
2000-05-09 11:43:00 +00:00
2001-10-09 22:55:00 +00:00
if ( ! ent )
break ;
2001-05-07 04:32:40 +00:00
}
name_list = ent - > sam_entries ;
2003-04-23 11:54:56 +00:00
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 ;
}
2001-05-07 04:32:40 +00:00
/* Lookup group info */
2003-04-23 11:54:56 +00:00
sid_copy ( & group_sid , & domain - > sid ) ;
sid_append_rid ( & group_sid , name_list [ ent - > sam_entry_index ] . rid ) ;
2006-02-03 22:19:41 +00:00
if ( ! NT_STATUS_IS_OK ( idmap_sid_to_gid ( & group_sid ,
& group_gid , 0 ) ) ) {
union unid_t id ;
enum SID_NAME_USE type ;
DEBUG ( 10 , ( " SID %s not in idmap \n " ,
sid_string_static ( & group_sid ) ) ) ;
if ( ! pdb_sid_to_id ( & group_sid , & id , & type ) ) {
DEBUG ( 1 , ( " could not look up gid for group "
" %s \n " ,
name_list [ ent - > sam_entry_index ] . acct_name ) ) ;
ent - > sam_entry_index + + ;
goto tryagain ;
}
if ( ( type ! = SID_NAME_DOM_GRP ) & &
( type ! = SID_NAME_ALIAS ) & &
( type ! = SID_NAME_WKN_GRP ) ) {
DEBUG ( 1 , ( " Group %s is a %s, not a group \n " ,
sid_type_lookup ( type ) ,
name_list [ ent - > sam_entry_index ] . acct_name ) ) ;
ent - > sam_entry_index + + ;
goto tryagain ;
}
group_gid = id . gid ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2003-12-04 19:22:44 +00:00
DEBUG ( 10 , ( " got gid %lu for group %lu \n " , ( unsigned long ) group_gid ,
( unsigned long ) name_list [ ent - > sam_entry_index ] . rid ) ) ;
2001-05-07 04:32:40 +00:00
/* Fill in group entry */
2000-05-09 11:43:00 +00:00
2002-01-18 02:37:55 +00:00
fill_domain_username ( domain_group_name , ent - > domain_name ,
2001-05-07 04:32:40 +00:00
name_list [ ent - > sam_entry_index ] . acct_name ) ;
2002-01-18 02:37:55 +00:00
2001-05-07 04:32:40 +00:00
result = fill_grent ( & group_list [ group_list_ndx ] ,
2002-01-20 01:24:59 +00:00
ent - > domain_name ,
name_list [ ent - > sam_entry_index ] . acct_name ,
group_gid ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Fill in group membership entry */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
if ( result ) {
2003-04-23 11:54:56 +00:00
DOM_SID member_sid ;
2002-07-15 10:35:28 +00:00
group_list [ group_list_ndx ] . num_gr_mem = 0 ;
gr_mem = NULL ;
gr_mem_len = 0 ;
2002-01-11 05:33:45 +00:00
2002-07-15 10:35:28 +00:00
/* Get group membership */
if ( state - > request . cmd = = WINBINDD_GETGRLST ) {
result = True ;
} else {
2003-04-23 11:54:56 +00:00
sid_copy ( & member_sid , & domain - > sid ) ;
sid_append_rid ( & member_sid , name_list [ ent - > sam_entry_index ] . rid ) ;
2002-07-15 10:35:28 +00:00
result = fill_grent_mem (
domain ,
2003-04-23 11:54:56 +00:00
& member_sid ,
2002-07-15 10:35:28 +00:00
SID_NAME_DOM_GRP ,
& group_list [ group_list_ndx ] . num_gr_mem ,
& gr_mem , & gr_mem_len ) ;
}
2001-12-04 06:17:39 +00:00
}
2000-05-09 11:43:00 +00:00
2001-12-04 06:17:39 +00:00
if ( result ) {
2001-05-07 04:32:40 +00:00
/* Append to group membership list */
2004-12-07 18:25:53 +00:00
new_gr_mem_list = SMB_REALLOC ( gr_mem_list , gr_mem_list_len + gr_mem_len ) ;
2000-05-09 11:43:00 +00:00
2001-08-30 00:13:55 +00:00
if ( ! new_gr_mem_list & & ( group_list [ group_list_ndx ] . num_gr_mem ! = 0 ) ) {
2002-01-10 06:20:03 +00:00
DEBUG ( 0 , ( " out of memory \n " ) ) ;
2001-09-17 04:52:45 +00:00
SAFE_FREE ( gr_mem_list ) ;
2001-05-07 04:32:40 +00:00
gr_mem_list_len = 0 ;
break ;
}
2000-05-09 11:43:00 +00:00
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " list_len = %d, mem_len = %d \n " ,
2001-05-07 04:32:40 +00:00
gr_mem_list_len , gr_mem_len ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
gr_mem_list = new_gr_mem_list ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
memcpy ( & gr_mem_list [ gr_mem_list_len ] , gr_mem ,
gr_mem_len ) ;
2000-05-09 11:43:00 +00:00
2001-09-17 04:52:45 +00:00
SAFE_FREE ( gr_mem ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
group_list [ group_list_ndx ] . gr_mem_ofs =
gr_mem_list_len ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
gr_mem_list_len + = gr_mem_len ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
ent - > sam_entry_index + + ;
/* Add group to return list */
if ( result ) {
2000-05-09 11:43:00 +00:00
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " adding group num_entries = %d \n " ,
2001-05-07 04:32:40 +00:00
state - > response . data . num_entries ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
group_list_ndx + + ;
state - > response . data . num_entries + + ;
state - > response . length + =
sizeof ( struct winbindd_gr ) ;
} else {
DEBUG ( 0 , ( " could not lookup domain group %s \n " ,
domain_group_name ) ) ;
}
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Copy the list of group memberships to the end of the extra data */
2000-05-09 11:43:00 +00:00
2001-10-09 22:55:00 +00:00
if ( group_list_ndx = = 0 )
2001-05-07 04:32:40 +00:00
goto done ;
2000-05-09 11:43:00 +00:00
2004-12-07 18:25:53 +00:00
new_extra_data = SMB_REALLOC (
2001-05-07 04:32:40 +00:00
state - > response . extra_data ,
group_list_ndx * sizeof ( struct winbindd_gr ) + gr_mem_list_len ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
if ( ! new_extra_data ) {
DEBUG ( 0 , ( " out of memory \n " ) ) ;
group_list_ndx = 0 ;
2001-09-17 04:52:45 +00:00
SAFE_FREE ( state - > response . extra_data ) ;
SAFE_FREE ( gr_mem_list ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . extra_data = new_extra_data ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
memcpy ( & ( ( char * ) state - > response . extra_data )
[ group_list_ndx * sizeof ( struct winbindd_gr ) ] ,
gr_mem_list , gr_mem_list_len ) ;
2000-05-09 11:43:00 +00:00
2001-09-17 04:52:45 +00:00
SAFE_FREE ( gr_mem_list ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
state - > response . length + = gr_mem_list_len ;
2000-05-09 11:43:00 +00:00
2002-01-10 06:20:03 +00:00
DEBUG ( 10 , ( " returning %d groups, length = %d \n " ,
2001-05-07 04:32:40 +00:00
group_list_ndx , gr_mem_list_len ) ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Out of domains */
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
done :
2001-11-27 22:39:57 +00:00
2005-06-20 13:42:29 +00:00
if ( group_list_ndx > 0 )
request_ok ( state ) ;
else
request_error ( state ) ;
2000-05-09 11:43:00 +00:00
}
2001-05-07 04:32:40 +00:00
/* List domain groups without mapping to unix ids */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_list_groups ( struct winbindd_cli_state * state )
2000-05-09 11:43:00 +00:00
{
2001-11-27 22:39:57 +00:00
uint32 total_entries = 0 ;
struct winbindd_domain * domain ;
2003-08-10 22:01:11 +00:00
const char * which_domain ;
2001-08-30 00:13:55 +00:00
char * extra_data = NULL ;
char * ted = NULL ;
2003-04-23 11:54:56 +00:00
unsigned int extra_data_len = 0 , i ;
2000-05-09 11:43:00 +00:00
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: list groups \n " , ( unsigned long ) state - > pid ) ) ;
2000-05-09 11:43:00 +00:00
2003-08-10 22:01:11 +00:00
/* Ensure null termination */
state - > request . domain_name [ sizeof ( state - > request . domain_name ) - 1 ] = ' \0 ' ;
which_domain = state - > request . domain_name ;
2001-11-27 22:39:57 +00:00
/* Enumerate over trusted domains */
2001-10-09 22:55:00 +00:00
2002-01-11 05:33:45 +00:00
for ( domain = domain_list ( ) ; domain ; domain = domain - > next ) {
2001-12-18 06:22:15 +00:00
struct getent_state groups ;
2003-08-10 22:01:11 +00:00
/* if we have a domain name restricting the request and this
one in the list doesn ' t match , then just bypass the remainder
of the loop */
if ( * which_domain & & ! strequal ( which_domain , domain - > name ) )
continue ;
2001-12-18 06:22:15 +00:00
ZERO_STRUCT ( groups ) ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Get list of sam groups */
2003-06-21 04:05:01 +00:00
2002-01-11 05:33:45 +00:00
fstrcpy ( groups . domain_name , domain - > name ) ;
2000-05-09 11:43:00 +00:00
2001-12-11 01:04:13 +00:00
get_sam_group_entries ( & groups ) ;
2001-08-30 00:13:55 +00:00
2001-12-18 06:22:15 +00:00
if ( groups . num_sam_entries = = 0 ) {
/* this domain is empty or in an error state */
2001-10-21 07:01:01 +00:00
continue ;
2001-12-18 06:22:15 +00:00
}
2000-05-09 11:43:00 +00:00
2001-08-30 00:13:55 +00:00
/* keep track the of the total number of groups seen so
far over all domains */
total_entries + = groups . num_sam_entries ;
/* Allocate some memory for extra data. Note that we limit
2001-12-18 06:22:15 +00:00
account names to sizeof ( fstring ) = 128 characters . */
2004-12-07 18:25:53 +00:00
ted = SMB_REALLOC ( extra_data , sizeof ( fstring ) * total_entries ) ;
2001-08-30 00:13:55 +00:00
2001-08-12 17:30:01 +00:00
if ( ! ted ) {
2002-01-10 06:20:03 +00:00
DEBUG ( 0 , ( " failed to enlarge buffer! \n " ) ) ;
2001-09-17 04:52:45 +00:00
SAFE_FREE ( extra_data ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-08-30 00:13:55 +00:00
} else
extra_data = ted ;
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* Pack group list into extra data fields */
for ( i = 0 ; i < groups . num_sam_entries ; i + + ) {
char * group_name = ( ( struct acct_info * )
groups . sam_entries ) [ i ] . acct_name ;
fstring name ;
2000-05-09 11:43:00 +00:00
2002-01-18 02:37:55 +00:00
fill_domain_username ( name , domain - > name , group_name ) ;
2001-12-18 06:22:15 +00:00
/* Append to extra data */
2001-10-09 22:55:00 +00:00
memcpy ( & extra_data [ extra_data_len ] , name ,
strlen ( name ) ) ;
2001-05-07 04:32:40 +00:00
extra_data_len + = strlen ( name ) ;
extra_data [ extra_data_len + + ] = ' , ' ;
}
2000-05-09 11:43:00 +00:00
2004-01-08 08:41:26 +00:00
SAFE_FREE ( groups . sam_entries ) ;
2001-12-18 06:22:15 +00:00
}
2001-12-10 06:21:18 +00:00
2001-05-07 04:32:40 +00:00
/* Assign extra_data fields in response structure */
if ( extra_data ) {
extra_data [ extra_data_len - 1 ] = ' \0 ' ;
state - > response . extra_data = extra_data ;
state - > response . length + = extra_data_len ;
}
2000-05-09 11:43:00 +00:00
2001-05-07 04:32:40 +00:00
/* No domains may have responded but that's still OK so don't
return an error . */
2000-05-09 11:43:00 +00:00
2005-06-20 13:42:29 +00:00
request_ok ( state ) ;
2000-05-09 11:43:00 +00:00
}
2001-05-07 04:32:40 +00:00
/* Get user supplementary groups. This is much quicker than trying to
2003-06-21 04:05:01 +00:00
invert the groups database . We merge the groups from the gids and
other_sids info3 fields as trusted domain , universal group
memberships , and nested groups ( win2k native mode only ) are not
returned by the getgroups RPC call but are present in the info3 . */
2000-05-09 11:43:00 +00:00
2005-06-08 22:10:34 +00:00
struct getgroups_state {
struct winbindd_cli_state * state ;
struct winbindd_domain * domain ;
char * domname ;
char * username ;
DOM_SID user_sid ;
const DOM_SID * token_sids ;
2005-10-18 03:24:00 +00:00
size_t i , num_token_sids ;
2005-06-08 22:10:34 +00:00
gid_t * token_gids ;
2005-10-18 03:24:00 +00:00
size_t num_token_gids ;
2005-06-08 22:10:34 +00:00
} ;
2005-06-24 20:25:18 +00:00
static void getgroups_usersid_recv ( void * private_data , BOOL success ,
2005-06-08 22:10:34 +00:00
const DOM_SID * sid , enum SID_NAME_USE type ) ;
2005-06-24 20:25:18 +00:00
static void getgroups_tokensids_recv ( void * private_data , BOOL success ,
2005-10-18 03:24:00 +00:00
DOM_SID * token_sids , size_t num_token_sids ) ;
2005-06-24 20:25:18 +00:00
static void getgroups_sid2gid_recv ( void * private_data , BOOL success , gid_t gid ) ;
2005-06-08 22:10:34 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getgroups ( struct winbindd_cli_state * state )
2000-05-09 11:43:00 +00:00
{
2005-06-08 22:10:34 +00:00
struct getgroups_state * s ;
2002-08-17 17:00:51 +00:00
/* Ensure null termination */
2005-06-08 22:10:34 +00:00
state - > request . data . username
[ sizeof ( state - > request . data . username ) - 1 ] = ' \0 ' ;
2002-08-17 17:00:51 +00:00
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: getgroups %s \n " , ( unsigned long ) state - > pid ,
2001-05-07 04:32:40 +00:00
state - > request . data . username ) ) ;
/* Parse domain and username */
2005-06-08 22:10:34 +00:00
s = TALLOC_P ( state - > mem_ctx , struct getgroups_state ) ;
if ( s = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2005-06-08 22:10:34 +00:00
s - > state = state ;
if ( ! parse_domain_user_talloc ( state - > mem_ctx ,
state - > request . data . username ,
& s - > domname , & s - > username ) ) {
2006-02-13 15:12:22 +00:00
DEBUG ( 5 , ( " Could not parse domain user: %s \n " ,
2005-06-08 22:10:34 +00:00
state - > request . data . username ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2005-06-08 22:10:34 +00:00
}
2004-01-08 02:15:46 +00:00
2005-06-08 22:10:34 +00:00
/* Get info for the domain */
2001-05-07 04:32:40 +00:00
2005-06-08 22:10:34 +00:00
s - > domain = find_domain_from_name_noinit ( s - > domname ) ;
2001-05-07 04:32:40 +00:00
2005-06-08 22:10:34 +00:00
if ( s - > domain = = NULL ) {
DEBUG ( 7 , ( " could not find domain entry for domain %s \n " ,
s - > domname ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2001-05-07 04:32:40 +00:00
}
2005-06-08 22:10:34 +00:00
if ( s - > domain - > primary & & lp_winbind_trusted_domains_only ( ) ) {
DEBUG ( 7 , ( " winbindd_getpwnam: My domain -- rejecting "
" getgroups() for %s \\ %s. \n " , s - > domname ,
s - > username ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2005-06-08 22:10:34 +00:00
}
2003-06-21 04:05:01 +00:00
2005-06-08 22:10:34 +00:00
/* Get rid and name type from name. The following costs 1 packet */
2003-06-21 04:05:01 +00:00
2005-06-08 22:10:34 +00:00
winbindd_lookupname_async ( state - > mem_ctx , s - > domname , s - > username ,
getgroups_usersid_recv , s ) ;
}
2003-06-21 04:05:01 +00:00
2005-06-24 20:25:18 +00:00
static void getgroups_usersid_recv ( void * private_data , BOOL success ,
2005-06-08 22:10:34 +00:00
const DOM_SID * sid , enum SID_NAME_USE type )
{
2005-06-24 20:25:18 +00:00
struct getgroups_state * s = private_data ;
2003-06-21 04:05:01 +00:00
2005-06-08 22:10:34 +00:00
if ( ( ! success ) | |
( ( type ! = SID_NAME_USER ) & & ( type ! = SID_NAME_COMPUTER ) ) ) {
2005-06-20 13:42:29 +00:00
request_error ( s - > state ) ;
2005-06-08 22:10:34 +00:00
return ;
2001-05-07 04:32:40 +00:00
}
2005-06-08 22:10:34 +00:00
sid_copy ( & s - > user_sid , sid ) ;
2003-06-21 04:05:01 +00:00
2005-06-08 22:10:34 +00:00
winbindd_gettoken_async ( s - > state - > mem_ctx , & s - > user_sid ,
getgroups_tokensids_recv , s ) ;
2000-05-09 11:43:00 +00:00
}
2003-11-19 08:11:14 +00:00
2005-06-24 20:25:18 +00:00
static void getgroups_tokensids_recv ( void * private_data , BOOL success ,
2005-10-18 03:24:00 +00:00
DOM_SID * token_sids , size_t num_token_sids )
2004-08-05 07:57:37 +00:00
{
2005-06-24 20:25:18 +00:00
struct getgroups_state * s = private_data ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
/* We need at least the user sid and the primary group in the token,
* otherwise it ' s an error */
if ( ( ! success ) | | ( num_token_sids < 2 ) ) {
2005-06-20 13:42:29 +00:00
request_error ( s - > state ) ;
2005-06-08 22:10:34 +00:00
return ;
2004-08-05 07:57:37 +00:00
}
2005-06-08 22:10:34 +00:00
s - > token_sids = token_sids ;
s - > num_token_sids = num_token_sids ;
s - > i = 0 ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
s - > token_gids = NULL ;
s - > num_token_gids = 0 ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
getgroups_sid2gid_recv ( s , False , 0 ) ;
2004-08-05 07:57:37 +00:00
}
2005-06-24 20:25:18 +00:00
static void getgroups_sid2gid_recv ( void * private_data , BOOL success , gid_t gid )
2004-08-05 07:57:37 +00:00
{
2005-06-24 20:25:18 +00:00
struct getgroups_state * s = private_data ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
if ( success )
add_gid_to_array_unique ( NULL , gid ,
& s - > token_gids ,
& s - > num_token_gids ) ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
if ( s - > i < s - > num_token_sids ) {
const DOM_SID * sid = & s - > token_sids [ s - > i ] ;
s - > i + = 1 ;
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
if ( sid_equal ( sid , & s - > user_sid ) ) {
getgroups_sid2gid_recv ( s , False , 0 ) ;
return ;
}
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
winbindd_sid2gid_async ( s - > state - > mem_ctx , sid ,
getgroups_sid2gid_recv , s ) ;
return ;
}
2004-08-05 07:57:37 +00:00
2005-06-08 22:10:34 +00:00
s - > state - > response . data . num_entries = s - > num_token_gids ;
s - > state - > response . extra_data = s - > token_gids ;
s - > state - > response . length + = s - > num_token_gids * sizeof ( gid_t ) ;
2005-06-20 13:42:29 +00:00
request_ok ( s - > state ) ;
2004-08-05 07:57:37 +00:00
}
2003-11-19 08:11:14 +00:00
/* Get user supplementary sids. This is equivalent to the
winbindd_getgroups ( ) function but it involves a SID - > SIDs mapping
rather than a NAME - > SID - > SIDS - > GIDS mapping , which means we avoid
idmap . This call is designed to be used with applications that need
to do ACL evaluation themselves . Note that the cached info3 data is
not used
this function assumes that the SID that comes in is a user SID . If
you pass in another type of SID then you may get unpredictable
results .
*/
2005-06-08 22:10:34 +00:00
2005-06-24 20:25:18 +00:00
static void getusersids_recv ( void * private_data , BOOL success , DOM_SID * sids ,
2005-10-18 03:24:00 +00:00
size_t num_sids ) ;
2005-06-08 22:10:34 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getusersids ( struct winbindd_cli_state * state )
2003-11-19 08:11:14 +00:00
{
2005-06-08 22:10:34 +00:00
DOM_SID * user_sid ;
2003-11-19 08:11:14 +00:00
/* Ensure null termination */
state - > request . data . sid [ sizeof ( state - > request . data . sid ) - 1 ] = ' \0 ' ;
2005-06-08 22:10:34 +00:00
user_sid = TALLOC_P ( state - > mem_ctx , DOM_SID ) ;
if ( user_sid = = NULL ) {
DEBUG ( 1 , ( " talloc failed \n " ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2003-11-19 08:11:14 +00:00
}
2005-06-08 22:10:34 +00:00
if ( ! string_to_sid ( user_sid , state - > request . data . sid ) ) {
DEBUG ( 1 , ( " Could not get convert sid %s from string \n " ,
state - > request . data . sid ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2003-11-19 08:11:14 +00:00
}
2005-06-08 22:10:34 +00:00
winbindd_gettoken_async ( state - > mem_ctx , user_sid , getusersids_recv ,
state ) ;
}
2003-11-19 08:11:14 +00:00
2005-06-24 20:25:18 +00:00
static void getusersids_recv ( void * private_data , BOOL success , DOM_SID * sids ,
2005-10-18 03:24:00 +00:00
size_t num_sids )
2005-06-08 22:10:34 +00:00
{
2005-06-24 20:25:18 +00:00
struct winbindd_cli_state * state = private_data ;
2005-06-08 22:10:34 +00:00
char * ret = NULL ;
unsigned ofs , ret_size = 0 ;
2005-10-18 03:24:00 +00:00
size_t i ;
2003-11-19 08:11:14 +00:00
2005-06-20 13:42:29 +00:00
if ( ! success ) {
request_error ( state ) ;
return ;
}
2004-08-05 07:57:37 +00:00
2003-11-19 08:11:14 +00:00
/* work out the response size */
2005-06-08 22:10:34 +00:00
for ( i = 0 ; i < num_sids ; i + + ) {
const char * s = sid_string_static ( & sids [ i ] ) ;
2003-11-19 08:11:14 +00:00
ret_size + = strlen ( s ) + 1 ;
}
/* build the reply */
2004-12-07 18:25:53 +00:00
ret = SMB_MALLOC ( ret_size ) ;
2005-06-20 13:42:29 +00:00
if ( ! ret ) {
DEBUG ( 0 , ( " malloc failed \n " ) ) ;
request_error ( state ) ;
return ;
}
2003-11-19 08:11:14 +00:00
ofs = 0 ;
2005-06-08 22:10:34 +00:00
for ( i = 0 ; i < num_sids ; i + + ) {
const char * s = sid_string_static ( & sids [ i ] ) ;
2004-01-15 15:36:01 +00:00
safe_strcpy ( ret + ofs , s , ret_size - ofs - 1 ) ;
2003-11-19 08:11:14 +00:00
ofs + = strlen ( ret + ofs ) + 1 ;
}
/* Send data back to client */
2005-06-08 22:10:34 +00:00
state - > response . data . num_entries = num_sids ;
2003-11-19 08:11:14 +00:00
state - > response . extra_data = ret ;
state - > response . length + = ret_size ;
2005-06-20 13:42:29 +00:00
request_ok ( state ) ;
2005-06-08 22:10:34 +00:00
}
2003-11-19 08:11:14 +00:00
2005-06-20 13:42:29 +00:00
void winbindd_getuserdomgroups ( struct winbindd_cli_state * state )
2005-06-08 22:10:34 +00:00
{
DOM_SID user_sid ;
struct winbindd_domain * domain ;
/* Ensure null termination */
state - > request . data . sid [ sizeof ( state - > request . data . sid ) - 1 ] = ' \0 ' ;
if ( ! string_to_sid ( & user_sid , state - > request . data . sid ) ) {
DEBUG ( 1 , ( " Could not get convert sid %s from string \n " ,
state - > request . data . sid ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2005-06-08 22:10:34 +00:00
}
/* Get info for the domain */
if ( ( domain = find_domain_from_sid_noinit ( & user_sid ) ) = = NULL ) {
DEBUG ( 0 , ( " could not find domain entry for sid %s \n " ,
sid_string_static ( & user_sid ) ) ) ;
2005-06-20 13:42:29 +00:00
request_error ( state ) ;
return ;
2005-06-08 22:10:34 +00:00
}
2005-06-20 13:42:29 +00:00
sendto_domain ( state , domain ) ;
2003-11-19 08:11:14 +00:00
}
2005-06-08 22:10:34 +00:00
enum winbindd_result winbindd_dual_getuserdomgroups ( struct winbindd_domain * domain ,
struct winbindd_cli_state * state )
{
DOM_SID user_sid ;
NTSTATUS status ;
2005-09-30 17:13:37 +00:00
char * sidstring ;
2005-10-18 03:24:00 +00:00
ssize_t len ;
2005-06-08 22:10:34 +00:00
DOM_SID * groups ;
2005-10-18 03:24:00 +00:00
uint32 num_groups ;
2005-06-08 22:10:34 +00:00
/* Ensure null termination */
state - > request . data . sid [ sizeof ( state - > request . data . sid ) - 1 ] = ' \0 ' ;
if ( ! string_to_sid ( & user_sid , state - > request . data . sid ) ) {
DEBUG ( 1 , ( " Could not get convert sid %s from string \n " ,
state - > request . data . sid ) ) ;
return WINBINDD_ERROR ;
}
status = domain - > methods - > lookup_usergroups ( domain , state - > mem_ctx ,
& user_sid , & num_groups ,
& groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
return WINBINDD_ERROR ;
if ( num_groups = = 0 ) {
state - > response . data . num_entries = 0 ;
state - > response . extra_data = NULL ;
return WINBINDD_OK ;
}
2005-09-30 17:13:37 +00:00
if ( ! print_sidlist ( NULL , groups , num_groups , & sidstring , & len ) ) {
DEBUG ( 0 , ( " malloc failed \n " ) ) ;
2005-06-08 22:10:34 +00:00
return WINBINDD_ERROR ;
}
2005-09-30 17:13:37 +00:00
state - > response . extra_data = sidstring ;
2005-06-08 22:10:34 +00:00
state - > response . length + = len + 1 ;
2005-09-30 17:13:37 +00:00
state - > response . data . num_entries = num_groups ;
2005-06-08 22:10:34 +00:00
return WINBINDD_OK ;
}