2000-05-09 15:43:00 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
Winbind daemon - user related functions
2000-05-09 15:43:00 +04:00
Copyright ( C ) Tim Potter 2000
2001-11-28 01:39:57 +03:00
Copyright ( C ) Jeremy Allison 2001.
2003-06-30 21:24:59 +04:00
Copyright ( C ) Gerald ( Jerry ) Carter 2003.
2000-05-09 15:43:00 +04: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 04:51:10 +03:00
# include "includes.h"
2000-05-09 15:43:00 +04:00
# include "winbindd.h"
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2003-06-16 22:37:54 +04:00
extern userdom_struct current_user_info ;
2005-06-29 18:03:53 +04:00
static BOOL fillup_pw_field ( const char * lp_template ,
const char * username ,
const char * domname ,
uid_t uid ,
gid_t gid ,
const char * in ,
fstring out )
{
char * templ ;
if ( out = = NULL )
return False ;
2005-07-04 17:57:54 +04:00
if ( in & & ! strequal ( in , " " ) & & lp_security ( ) = = SEC_ADS & & use_nss_info ( " sfu " ) ) {
2005-06-29 18:03:53 +04:00
safe_strcpy ( out , in , sizeof ( fstring ) - 1 ) ;
return True ;
}
/* Home directory and shell - use template config parameters. The
defaults are / tmp for the home directory and / bin / false for
shell . */
/* The substitution of %U and %D in the 'template homedir' is done
by alloc_sub_specified ( ) below . */
templ = alloc_sub_specified ( lp_template , username , domname , uid , gid ) ;
if ( ! templ )
return False ;
safe_strcpy ( out , templ , sizeof ( fstring ) - 1 ) ;
SAFE_FREE ( templ ) ;
return True ;
}
2000-05-09 15:43:00 +04:00
/* Fill a pwent structure with information we have obtained */
2002-01-20 04:24:59 +03:00
static BOOL winbindd_fill_pwent ( char * dom_name , char * user_name ,
2003-04-23 15:54:56 +04:00
DOM_SID * user_sid , DOM_SID * group_sid ,
2005-06-29 18:03:53 +04:00
char * full_name , char * homedir , char * shell ,
struct winbindd_pw * pw )
2000-05-09 15:43:00 +04:00
{
2002-01-20 04:24:59 +03:00
fstring output_username ;
2003-04-23 15:54:56 +04:00
fstring sid_string ;
2001-05-07 08:32:40 +04:00
2002-01-20 04:24:59 +03:00
if ( ! pw | | ! dom_name | | ! user_name )
2001-05-07 08:32:40 +04:00
return False ;
/* Resolve the uid number */
2003-05-12 22:12:31 +04:00
2004-07-31 05:50:35 +04:00
if ( ! NT_STATUS_IS_OK ( idmap_sid_to_uid ( user_sid , & pw - > pw_uid , 0 ) ) ) {
2003-04-23 15:54:56 +04:00
DEBUG ( 1 , ( " error getting user id for sid %s \n " , sid_to_string ( sid_string , user_sid ) ) ) ;
2001-05-07 08:32:40 +04:00
return False ;
}
/* Resolve the gid number */
2003-05-12 22:12:31 +04:00
2004-07-31 05:50:35 +04:00
if ( ! NT_STATUS_IS_OK ( idmap_sid_to_gid ( group_sid , & pw - > pw_gid , 0 ) ) ) {
2003-04-23 15:54:56 +04:00
DEBUG ( 1 , ( " error getting group id for sid %s \n " , sid_to_string ( sid_string , group_sid ) ) ) ;
2001-05-07 08:32:40 +04:00
return False ;
}
2004-09-24 10:42:04 +04:00
strlower_m ( user_name ) ;
2001-05-07 08:32:40 +04:00
/* Username */
2002-01-20 04:24:59 +03:00
fill_domain_username ( output_username , dom_name , user_name ) ;
safe_strcpy ( pw - > pw_name , output_username , sizeof ( pw - > pw_name ) - 1 ) ;
2001-05-07 08:32:40 +04:00
/* Full name (gecos) */
safe_strcpy ( pw - > pw_gecos , full_name , sizeof ( pw - > pw_gecos ) - 1 ) ;
2001-10-29 07:50:17 +03:00
2001-05-07 08:32:40 +04:00
/* Home directory and shell - use template config parameters. The
defaults are / tmp for the home directory and / bin / false for
shell . */
2001-05-08 09:58:03 +04:00
/* The substitution of %U and %D in the 'template homedir' is done
2004-01-08 02:46:47 +03:00
by alloc_sub_specified ( ) below . */
2001-05-07 08:32:40 +04:00
2002-01-20 04:24:59 +03:00
fstrcpy ( current_user_info . domain , dom_name ) ;
2001-05-07 08:32:40 +04:00
2005-06-29 18:03:53 +04:00
if ( ! fillup_pw_field ( lp_template_homedir ( ) , user_name , dom_name ,
pw - > pw_uid , pw - > pw_gid , homedir , pw - > pw_dir ) )
2004-01-08 02:46:47 +03:00
return False ;
2005-06-29 18:03:53 +04:00
if ( ! fillup_pw_field ( lp_template_shell ( ) , user_name , dom_name ,
pw - > pw_uid , pw - > pw_gid , shell , pw - > pw_shell ) )
2004-01-08 02:46:47 +03:00
return False ;
2001-05-07 08:32:40 +04:00
/* Password - set to "x" as we can't generate anything useful here.
2002-01-20 04:24:59 +03:00
Authentication can be done using the pam_winbind module . */
2001-05-07 08:32:40 +04:00
safe_strcpy ( pw - > pw_passwd , " x " , sizeof ( pw - > pw_passwd ) - 1 ) ;
2004-01-08 02:46:47 +03:00
2001-05-07 08:32:40 +04:00
return True ;
2000-05-09 15:43:00 +04:00
}
2005-06-09 02:10:34 +04:00
/* Wrapper for domain->methods->query_user, only on the parent->child pipe */
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
enum winbindd_result winbindd_dual_userinfo ( struct winbindd_domain * domain ,
struct winbindd_cli_state * state )
2000-05-09 15:43:00 +04:00
{
2005-06-09 02:10:34 +04:00
DOM_SID sid ;
2001-12-04 09:17:39 +03:00
WINBIND_USERINFO user_info ;
NTSTATUS status ;
2005-06-09 02:10:34 +04:00
2002-08-17 21:00:51 +04:00
/* Ensure null termination */
2005-06-09 02:10:34 +04:00
state - > request . data . sid [ sizeof ( state - > request . data . sid ) - 1 ] = ' \0 ' ;
2002-08-17 21:00:51 +04:00
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " [%5lu]: lookupsid %s \n " , ( unsigned long ) state - > pid ,
state - > request . data . sid ) ) ;
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
if ( ! string_to_sid ( & sid , state - > request . data . sid ) ) {
DEBUG ( 5 , ( " %s not a SID \n " , state - > request . data . sid ) ) ;
2001-11-21 12:59:15 +03:00
return WINBINDD_ERROR ;
}
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
status = domain - > methods - > query_user ( domain , state - > mem_ctx ,
& sid , & user_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " error getting user info for sid %s \n " ,
sid_string_static ( & sid ) ) ) ;
2001-05-07 08:32:40 +04:00
return WINBINDD_ERROR ;
}
2005-06-09 02:10:34 +04:00
fstrcpy ( state - > response . data . user_info . acct_name , user_info . acct_name ) ;
fstrcpy ( state - > response . data . user_info . full_name , user_info . full_name ) ;
2005-06-29 18:03:53 +04:00
fstrcpy ( state - > response . data . user_info . homedir , user_info . homedir ) ;
fstrcpy ( state - > response . data . user_info . shell , user_info . shell ) ;
2005-06-09 02:10:34 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & user_info . group_sid ,
& state - > response . data . user_info . group_rid ) ) {
DEBUG ( 1 , ( " Could not extract group rid out of %s \n " ,
sid_string_static ( & sid ) ) ) ;
2001-11-27 09:28:06 +03:00
return WINBINDD_ERROR ;
}
2001-10-29 07:50:17 +03:00
2005-06-09 02:10:34 +04:00
return WINBINDD_OK ;
}
2002-01-10 09:20:03 +03:00
2005-06-09 02:10:34 +04:00
struct getpwsid_state {
struct winbindd_cli_state * state ;
struct winbindd_domain * domain ;
char * username ;
char * fullname ;
2005-06-29 18:03:53 +04:00
char * homedir ;
char * shell ;
2005-06-09 02:10:34 +04:00
DOM_SID user_sid ;
uid_t uid ;
DOM_SID group_sid ;
gid_t gid ;
} ;
2005-06-25 00:25:18 +04:00
static void getpwsid_queryuser_recv ( void * private_data , BOOL success ,
2005-06-09 02:10:34 +04:00
const char * acct_name ,
2005-06-29 18:03:53 +04:00
const char * full_name ,
const char * homedir ,
const char * shell ,
uint32 group_rid ) ;
2005-06-25 00:25:18 +04:00
static void getpwsid_sid2uid_recv ( void * private_data , BOOL success , uid_t uid ) ;
static void getpwsid_sid2gid_recv ( void * private_data , BOOL success , gid_t gid ) ;
2005-06-09 02:10:34 +04:00
static void winbindd_getpwsid ( struct winbindd_cli_state * state ,
const DOM_SID * sid )
{
struct getpwsid_state * s ;
s = TALLOC_P ( state - > mem_ctx , struct getpwsid_state ) ;
if ( s = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
goto error ;
2001-05-07 08:32:40 +04:00
}
2005-06-09 02:10:34 +04:00
s - > state = state ;
s - > domain = find_domain_from_sid_noinit ( sid ) ;
if ( s - > domain = = NULL ) {
DEBUG ( 3 , ( " Could not find domain for sid %s \n " ,
sid_string_static ( sid ) ) ) ;
goto error ;
2001-05-07 08:32:40 +04:00
}
2001-12-04 09:17:39 +03:00
2005-06-09 02:10:34 +04:00
sid_copy ( & s - > user_sid , sid ) ;
query_user_async ( s - > state - > mem_ctx , s - > domain , sid ,
getpwsid_queryuser_recv , s ) ;
return ;
error :
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
2005-06-09 02:10:34 +04:00
}
2001-05-07 08:32:40 +04:00
2005-06-25 00:25:18 +04:00
static void getpwsid_queryuser_recv ( void * private_data , BOOL success ,
2005-06-09 02:10:34 +04:00
const char * acct_name ,
2005-06-29 18:03:53 +04:00
const char * full_name ,
const char * homedir ,
const char * shell ,
uint32 group_rid )
2005-06-09 02:10:34 +04:00
{
struct getpwsid_state * s =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct getpwsid_state ) ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
DEBUG ( 5 , ( " Could not query user %s \\ %s \n " , s - > domain - > name ,
s - > username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( s - > state ) ;
2005-06-09 02:10:34 +04:00
return ;
}
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
s - > username = talloc_strdup ( s - > state - > mem_ctx , acct_name ) ;
s - > fullname = talloc_strdup ( s - > state - > mem_ctx , full_name ) ;
2005-06-29 18:03:53 +04:00
s - > homedir = talloc_strdup ( s - > state - > mem_ctx , homedir ) ;
s - > shell = talloc_strdup ( s - > state - > mem_ctx , shell ) ;
2005-06-09 02:10:34 +04:00
sid_copy ( & s - > group_sid , & s - > domain - > sid ) ;
sid_append_rid ( & s - > group_sid , group_rid ) ;
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
winbindd_sid2uid_async ( s - > state - > mem_ctx , & s - > user_sid ,
getpwsid_sid2uid_recv , s ) ;
}
2005-06-25 00:25:18 +04:00
static void getpwsid_sid2uid_recv ( void * private_data , BOOL success , uid_t uid )
2000-05-09 15:43:00 +04:00
{
2005-06-09 02:10:34 +04:00
struct getpwsid_state * s =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct getpwsid_state ) ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
DEBUG ( 5 , ( " Could not query user's %s \\ %s uid \n " ,
s - > domain - > name , s - > username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( s - > state ) ;
2005-06-09 02:10:34 +04:00
return ;
}
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
s - > uid = uid ;
winbindd_sid2gid_async ( s - > state - > mem_ctx , & s - > group_sid ,
getpwsid_sid2gid_recv , s ) ;
}
2001-05-07 08:32:40 +04:00
2005-06-25 00:25:18 +04:00
static void getpwsid_sid2gid_recv ( void * private_data , BOOL success , gid_t gid )
2005-06-09 02:10:34 +04:00
{
struct getpwsid_state * s =
2005-06-25 00:25:18 +04:00
talloc_get_type_abort ( private_data , struct getpwsid_state ) ;
2005-06-09 02:10:34 +04:00
struct winbindd_pw * pw ;
fstring output_username ;
2003-07-09 20:44:47 +04:00
2005-06-09 02:10:34 +04:00
if ( ! success ) {
DEBUG ( 5 , ( " Could not query user's %s \\ %s \n gid " ,
s - > domain - > name , s - > username ) ) ;
2005-06-20 17:42:29 +04:00
goto failed ;
2001-05-07 08:32:40 +04:00
}
2005-06-09 02:10:34 +04:00
s - > gid = gid ;
pw = & s - > state - > response . data . pw ;
pw - > pw_uid = s - > uid ;
pw - > pw_gid = s - > gid ;
fill_domain_username ( output_username , s - > domain - > name , s - > username ) ;
safe_strcpy ( pw - > pw_name , output_username , sizeof ( pw - > pw_name ) - 1 ) ;
safe_strcpy ( pw - > pw_gecos , s - > fullname , sizeof ( pw - > pw_gecos ) - 1 ) ;
fstrcpy ( current_user_info . domain , s - > domain - > name ) ;
2005-06-29 18:03:53 +04:00
if ( ! fillup_pw_field ( lp_template_homedir ( ) , s - > username , s - > domain - > name ,
pw - > pw_uid , pw - > pw_gid , s - > homedir , pw - > pw_dir ) ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 5 , ( " Could not compose homedir \n " ) ) ;
2005-06-20 17:42:29 +04:00
goto failed ;
2001-05-07 08:32:40 +04:00
}
2005-06-29 18:03:53 +04:00
if ( ! fillup_pw_field ( lp_template_shell ( ) , s - > username , s - > domain - > name ,
pw - > pw_uid , pw - > pw_gid , s - > shell , pw - > pw_shell ) ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 5 , ( " Could not compose shell \n " ) ) ;
2005-06-20 17:42:29 +04:00
goto failed ;
2005-06-09 02:10:34 +04:00
}
/* Password - set to "x" as we can't generate anything useful here.
Authentication can be done using the pam_winbind module . */
safe_strcpy ( pw - > pw_passwd , " x " , sizeof ( pw - > pw_passwd ) - 1 ) ;
2005-06-20 17:42:29 +04:00
request_ok ( s - > state ) ;
return ;
2005-06-09 02:10:34 +04:00
2005-06-20 17:42:29 +04:00
failed :
request_error ( s - > state ) ;
2005-06-09 02:10:34 +04:00
}
2003-04-23 15:54:56 +04:00
2005-06-09 02:10:34 +04:00
/* Return a password structure from a username. */
2005-06-25 00:25:18 +04:00
static void getpwnam_name2sid_recv ( void * private_data , BOOL success ,
2005-06-09 02:10:34 +04:00
const DOM_SID * sid , enum SID_NAME_USE type ) ;
2005-06-20 17:42:29 +04:00
void winbindd_getpwnam ( struct winbindd_cli_state * state )
2005-06-09 02:10:34 +04:00
{
struct winbindd_domain * domain ;
fstring domname , username ;
/* Ensure null termination */
state - > request . data . username [ sizeof ( state - > request . data . username ) - 1 ] = ' \0 ' ;
DEBUG ( 3 , ( " [%5lu]: getpwnam %s \n " , ( unsigned long ) state - > pid ,
state - > request . data . username ) ) ;
if ( ! parse_domain_user ( state - > request . data . username , domname ,
username ) ) {
DEBUG ( 0 , ( " Could not parse domain user: %s \n " ,
state - > request . data . username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2003-04-23 15:54:56 +04:00
}
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
/* Get info for the domain */
2002-01-10 09:20:03 +03:00
2005-06-10 07:26:39 +04:00
domain = find_domain_from_name ( domname ) ;
2005-06-09 02:10:34 +04:00
if ( domain = = NULL ) {
DEBUG ( 7 , ( " could not find domain entry for domain %s \n " ,
domname ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2001-11-27 09:28:06 +03:00
}
2001-10-29 07:50:17 +03:00
2005-06-10 07:26:39 +04:00
if ( strequal ( domname , lp_workgroup ( ) ) & & lp_winbind_trusted_domains_only ( ) ) {
DEBUG ( 7 , ( " winbindd_getpwnam: My domain -- rejecting getpwnam() for %s \\ %s. \n " ,
domname , username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2005-06-09 02:10:34 +04:00
}
/* Get rid and name type from name. The following costs 1 packet */
winbindd_lookupname_async ( state - > mem_ctx , domname , username ,
getpwnam_name2sid_recv , state ) ;
}
2005-06-25 00:25:18 +04:00
static void getpwnam_name2sid_recv ( void * private_data , BOOL success ,
2005-06-09 02:10:34 +04:00
const DOM_SID * sid , enum SID_NAME_USE type )
{
2005-06-25 00:25:18 +04:00
struct winbindd_cli_state * state = private_data ;
2005-06-09 02:10:34 +04:00
if ( ! success ) {
DEBUG ( 5 , ( " Could not lookup name for user %s \n " ,
state - > request . data . username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
2005-06-09 02:10:34 +04:00
return ;
}
if ( ( type ! = SID_NAME_USER ) & & ( type ! = SID_NAME_COMPUTER ) ) {
DEBUG ( 5 , ( " %s is not a user \n " , state - > request . data . username ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
2005-06-09 02:10:34 +04:00
return ;
2001-05-07 08:32:40 +04:00
}
2005-06-09 02:10:34 +04:00
winbindd_getpwsid ( state , sid ) ;
}
/* Return a password structure given a uid number */
2005-06-20 17:42:29 +04:00
void winbindd_getpwuid ( struct winbindd_cli_state * state )
2005-06-09 02:10:34 +04:00
{
DOM_SID user_sid ;
NTSTATUS status ;
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
/* Bug out if the uid isn't in the winbind range */
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
if ( ( state - > request . data . uid < server_state . uid_low ) | |
2005-06-20 17:42:29 +04:00
( state - > request . data . uid > server_state . uid_high ) ) {
request_error ( state ) ;
return ;
}
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " [%5lu]: getpwuid %lu \n " , ( unsigned long ) state - > pid ,
( unsigned long ) state - > request . data . uid ) ) ;
2001-05-07 08:32:40 +04:00
2005-06-09 02:10:34 +04:00
status = idmap_uid_to_sid ( & user_sid , state - > request . data . uid ,
ID_QUERY_ONLY | ID_CACHE_ONLY ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " Could not find SID for uid %lu \n " ,
( unsigned long ) state - > request . data . uid ) ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2001-11-27 23:57:14 +03:00
}
2001-12-04 09:17:39 +03:00
2005-06-09 02:10:34 +04:00
winbindd_getpwsid ( state , & user_sid ) ;
2000-05-09 15:43:00 +04:00
}
/*
* set / get / endpwent functions
*/
/* Rewind file pointer for ntdom passwd database */
2005-06-24 18:25:18 +04:00
static BOOL winbindd_setpwent_internal ( struct winbindd_cli_state * state )
2000-05-09 15:43:00 +04:00
{
2002-01-10 09:20:03 +03:00
struct winbindd_domain * domain ;
2001-10-08 04:34:14 +04:00
2003-07-22 08:31:20 +04:00
DEBUG ( 3 , ( " [%5lu]: setpwent \n " , ( unsigned long ) state - > pid ) ) ;
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
/* Check user has enabled this */
2001-10-08 04:34:14 +04:00
2005-06-20 17:42:29 +04:00
if ( ! lp_winbind_enum_users ( ) ) {
2005-06-24 18:25:18 +04:00
return False ;
2005-06-20 17:42:29 +04:00
}
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
/* Free old static data if it exists */
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
if ( state - > getpwent_state ! = NULL ) {
free_getent_state ( state - > getpwent_state ) ;
state - > getpwent_state = NULL ;
}
2003-07-11 09:33:40 +04:00
#if 0 /* JERRY */
/* add any local users we have */
if ( ( domain_state = ( struct getent_state * ) malloc ( sizeof ( struct getent_state ) ) ) = = NULL )
2005-06-24 18:25:18 +04:00
return False ;
2003-07-11 09:33:40 +04:00
ZERO_STRUCTP ( domain_state ) ;
/* Add to list of open domains */
DLIST_ADD ( state - > getpwent_state , domain_state ) ;
# endif
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
/* Create sam pipes for each domain we know about */
2001-10-08 04:34:14 +04:00
2002-01-11 08:33:45 +03:00
for ( domain = domain_list ( ) ; domain ! = NULL ; domain = domain - > next ) {
2001-11-27 23:57:14 +03:00
struct getent_state * domain_state ;
2001-10-08 04:34:14 +04:00
2003-06-30 21:24:59 +04:00
2003-07-07 09:11:10 +04:00
/* don't add our domaina if we are a PDC or if we
are a member of a Samba domain */
2003-06-30 21:24:59 +04:00
2003-07-07 09:11:10 +04:00
if ( ( IS_DC | | lp_winbind_trusted_domains_only ( ) )
& & strequal ( domain - > name , lp_workgroup ( ) ) )
{
continue ;
}
2003-06-30 21:24:59 +04:00
2001-11-27 23:57:14 +03:00
/* Create a state record for this domain */
2001-10-08 04:34:14 +04:00
2005-06-20 17:42:29 +04:00
if ( ( domain_state = SMB_MALLOC_P ( struct getent_state ) ) = = NULL ) {
DEBUG ( 0 , ( " malloc failed \n " ) ) ;
2005-06-24 18:25:18 +04:00
return False ;
2005-06-20 17:42:29 +04:00
}
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
ZERO_STRUCTP ( domain_state ) ;
2001-10-19 05:46:43 +04:00
2002-01-11 08:33:45 +03:00
fstrcpy ( domain_state - > domain_name , domain - > name ) ;
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
/* Add to list of open domains */
2001-10-08 04:34:14 +04:00
2001-11-27 23:57:14 +03:00
DLIST_ADD ( state - > getpwent_state , domain_state ) ;
}
2001-10-08 04:34:14 +04:00
2004-04-29 00:07:51 +04:00
state - > getpwent_initialized = True ;
2005-06-24 18:25:18 +04:00
return True ;
}
void winbindd_setpwent ( struct winbindd_cli_state * state )
{
if ( winbindd_setpwent_internal ( state ) ) {
request_ok ( state ) ;
} else {
request_error ( state ) ;
}
2000-05-09 15:43:00 +04:00
}
/* Close file pointer to ntdom passwd database */
2005-06-20 17:42:29 +04:00
void winbindd_endpwent ( struct winbindd_cli_state * state )
2000-05-09 15:43:00 +04:00
{
2003-07-22 08:31:20 +04:00
DEBUG ( 3 , ( " [%5lu]: endpwent \n " , ( unsigned long ) state - > pid ) ) ;
2000-05-09 15:43:00 +04:00
2001-11-27 23:57:14 +03:00
free_getent_state ( state - > getpwent_state ) ;
2004-04-29 00:07:51 +04:00
state - > getpwent_initialized = False ;
2001-11-27 23:57:14 +03:00
state - > getpwent_state = NULL ;
2005-06-20 17:42:29 +04:00
request_ok ( state ) ;
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04:00
/* Get partial list of domain users for a domain. We fill in the sam_entries,
and num_sam_entries fields with domain user information . The dispinfo_ndx
field is incremented to the index of the next user to fetch . Return True if
some users were returned , False otherwise . */
2005-06-09 02:10:34 +04:00
static BOOL get_sam_user_entries ( struct getent_state * ent , TALLOC_CTX * mem_ctx )
2001-05-07 08:32:40 +04:00
{
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
uint32 num_entries ;
2001-12-03 14:32:55 +03:00
WINBIND_USERINFO * info ;
2001-05-07 08:32:40 +04:00
struct getpwent_user * name_list = NULL ;
2001-11-27 23:57:14 +03:00
BOOL result = False ;
2002-01-11 08:33:45 +03:00
struct winbindd_domain * domain ;
2001-12-01 15:31:43 +03:00
struct winbindd_methods * methods ;
2003-04-23 15:54:56 +04:00
unsigned int i ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
if ( ent - > num_sam_entries )
2001-05-07 08:32:40 +04:00
return False ;
2002-01-11 08:33:45 +03:00
if ( ! ( domain = find_domain_from_name ( ent - > domain_name ) ) ) {
DEBUG ( 3 , ( " no such domain %s in get_sam_user_entries \n " ,
ent - > domain_name ) ) ;
return False ;
}
methods = domain - > methods ;
2001-05-07 08:32:40 +04:00
/* Free any existing user info */
2001-09-17 08:52:45 +04:00
SAFE_FREE ( ent - > sam_entries ) ;
ent - > num_sam_entries = 0 ;
2001-12-03 14:32:55 +03:00
/* Call query_user_list to get a list of usernames and user rids */
2002-01-11 08:33:45 +03:00
2001-12-11 03:03:58 +03:00
num_entries = 0 ;
2001-05-07 08:32:40 +04:00
2002-01-11 08:33:45 +03:00
status = methods - > query_user_list ( domain , mem_ctx , & num_entries ,
& info ) ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
if ( num_entries ) {
struct getpwent_user * tnl ;
2004-12-07 21:25:53 +03:00
tnl = SMB_REALLOC_ARRAY ( name_list , struct getpwent_user , ent - > num_sam_entries + num_entries ) ;
2001-12-11 03:03:58 +03:00
if ( ! tnl ) {
2002-01-10 09:20:03 +03:00
DEBUG ( 0 , ( " get_sam_user_entries realloc failed. \n " ) ) ;
2001-12-11 03:03:58 +03:00
SAFE_FREE ( name_list ) ;
goto done ;
} else
name_list = tnl ;
}
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
for ( i = 0 ; i < num_entries ; i + + ) {
/* Store account name and gecos */
if ( ! info [ i ] . acct_name ) {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . name , " " ) ;
} else {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . name ,
info [ i ] . acct_name ) ;
}
if ( ! info [ i ] . full_name ) {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . gecos , " " ) ;
} else {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . gecos ,
info [ i ] . full_name ) ;
2001-05-07 08:32:40 +04:00
}
2005-06-29 18:03:53 +04:00
if ( ! info [ i ] . homedir ) {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . homedir , " " ) ;
} else {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . homedir ,
info [ i ] . homedir ) ;
}
if ( ! info [ i ] . shell ) {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . shell , " " ) ;
} else {
fstrcpy ( name_list [ ent - > num_sam_entries + i ] . shell ,
info [ i ] . shell ) ;
}
2001-12-11 03:03:58 +03:00
/* User and group ids */
2005-06-09 02:10:34 +04:00
sid_copy ( & name_list [ ent - > num_sam_entries + i ] . user_sid ,
& info [ i ] . user_sid ) ;
sid_copy ( & name_list [ ent - > num_sam_entries + i ] . group_sid ,
& info [ i ] . group_sid ) ;
2001-12-11 03:03:58 +03:00
}
ent - > num_sam_entries + = num_entries ;
2001-05-07 08:32:40 +04:00
/* Fill in remaining fields */
ent - > sam_entries = name_list ;
ent - > sam_entry_index = 0 ;
2001-10-19 12:22:52 +04:00
result = ent - > num_sam_entries > 0 ;
done :
2001-05-07 08:32:40 +04:00
2001-11-27 23:57:14 +03:00
return result ;
2001-05-07 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
/* Fetch next passwd entry from ntdom database */
2001-05-07 08:32:40 +04:00
# define MAX_GETPWENT_USERS 500
2005-06-20 17:42:29 +04:00
void winbindd_getpwent ( struct winbindd_cli_state * state )
2000-05-09 15:43:00 +04:00
{
2001-05-07 08:32:40 +04:00
struct getent_state * ent ;
struct winbindd_pw * user_list ;
int num_users , user_list_ndx = 0 , i ;
2000-05-09 15:43:00 +04:00
2003-07-22 08:31:20 +04:00
DEBUG ( 3 , ( " [%5lu]: getpwent \n " , ( unsigned long ) state - > pid ) ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Check user has enabled this */
2000-05-09 15:43:00 +04:00
2005-06-20 17:42:29 +04:00
if ( ! lp_winbind_enum_users ( ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Allocate space for returning a chunk of users */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
num_users = MIN ( MAX_GETPWENT_USERS , state - > request . data . num_entries ) ;
2005-06-20 17:42:29 +04:00
if ( ( state - > response . extra_data = SMB_MALLOC_ARRAY ( struct winbindd_pw , num_users ) ) = = NULL ) {
request_error ( state ) ;
return ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
memset ( state - > response . extra_data , 0 , num_users *
sizeof ( struct winbindd_pw ) ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
user_list = ( struct winbindd_pw * ) state - > response . extra_data ;
2004-04-29 00:07:51 +04:00
if ( ! state - > getpwent_initialized )
2005-06-24 18:25:18 +04:00
winbindd_setpwent_internal ( state ) ;
2001-05-07 08:32:40 +04:00
2005-06-20 17:42:29 +04:00
if ( ! ( ent = state - > getpwent_state ) ) {
request_error ( state ) ;
return ;
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Start sending back users */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
for ( i = 0 ; i < num_users ; i + + ) {
struct getpwent_user * name_list = NULL ;
uint32 result ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Do we need to fetch another chunk of users? */
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
if ( ent - > num_sam_entries = = ent - > sam_entry_index ) {
2000-05-09 15:43:00 +04:00
2005-06-09 02:10:34 +04:00
while ( ent & &
! get_sam_user_entries ( ent , state - > mem_ctx ) ) {
2001-05-07 08:32:40 +04:00
struct getent_state * next_ent ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* Free state information for this domain */
2000-05-09 15:43:00 +04:00
2001-09-17 08:52:45 +04:00
SAFE_FREE ( ent - > sam_entries ) ;
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
next_ent = ent - > next ;
DLIST_REMOVE ( state - > getpwent_state , ent ) ;
2001-09-17 08:52:45 +04:00
SAFE_FREE ( ent ) ;
2001-05-07 08:32:40 +04:00
ent = next_ent ;
}
/* No more domains */
2001-10-08 04:34:14 +04:00
if ( ! ent )
2001-11-27 09:28:06 +03:00
break ;
2001-05-07 08:32:40 +04:00
}
name_list = ent - > sam_entries ;
/* Lookup user info */
result = winbindd_fill_pwent (
2002-01-11 08:33:45 +03:00
ent - > domain_name ,
2002-01-20 04:24:59 +03:00
name_list [ ent - > sam_entry_index ] . name ,
2003-04-23 15:54:56 +04:00
& name_list [ ent - > sam_entry_index ] . user_sid ,
& name_list [ ent - > sam_entry_index ] . group_sid ,
2001-05-07 08:32:40 +04:00
name_list [ ent - > sam_entry_index ] . gecos ,
2005-06-29 18:03:53 +04:00
name_list [ ent - > sam_entry_index ] . homedir ,
name_list [ ent - > sam_entry_index ] . shell ,
2001-05-07 08:32:40 +04:00
& user_list [ user_list_ndx ] ) ;
ent - > sam_entry_index + + ;
/* Add user to return list */
if ( result ) {
user_list_ndx + + ;
state - > response . data . num_entries + + ;
state - > response . length + =
sizeof ( struct winbindd_pw ) ;
2001-10-08 04:34:14 +04:00
} else
2001-05-07 08:32:40 +04:00
DEBUG ( 1 , ( " could not lookup domain user %s \n " ,
2003-03-19 11:23:29 +03:00
name_list [ ent - > sam_entry_index ] . name ) ) ;
2001-05-07 08:32:40 +04:00
}
/* Out of domains */
2005-06-20 17:42:29 +04:00
if ( user_list_ndx > 0 )
request_ok ( state ) ;
else
request_error ( state ) ;
2001-05-07 08:32:40 +04:00
}
2000-05-09 15:43:00 +04:00
2001-05-07 08:32:40 +04:00
/* List domain users without mapping to unix ids */
2005-06-20 17:42:29 +04:00
void winbindd_list_users ( struct winbindd_cli_state * state )
2001-05-07 08:32:40 +04:00
{
2001-08-18 23:43:28 +04:00
struct winbindd_domain * domain ;
2001-12-03 14:32:55 +03:00
WINBIND_USERINFO * info ;
2003-08-11 02:01:11 +04:00
const char * which_domain ;
2001-08-18 23:43:28 +04:00
uint32 num_entries = 0 , total_entries = 0 ;
2001-08-12 21:30:01 +04:00
char * ted , * extra_data = NULL ;
2001-05-07 08:32:40 +04:00
int extra_data_len = 0 ;
2001-11-27 09:28:06 +03:00
enum winbindd_result rv = WINBINDD_ERROR ;
2001-05-07 08:32:40 +04:00
2003-07-22 08:31:20 +04:00
DEBUG ( 3 , ( " [%5lu]: list users \n " , ( unsigned long ) state - > pid ) ) ;
2001-05-07 08:32:40 +04:00
2003-08-11 02:01:11 +04:00
/* Ensure null termination */
state - > request . domain_name [ sizeof ( state - > request . domain_name ) - 1 ] = ' \0 ' ;
which_domain = state - > request . domain_name ;
2001-08-18 23:43:28 +04:00
/* Enumerate over trusted domains */
2001-05-07 08:32:40 +04:00
2002-01-11 08:33:45 +03:00
for ( domain = domain_list ( ) ; domain ; domain = domain - > next ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2001-12-01 15:31:43 +03:00
struct winbindd_methods * methods ;
2003-04-23 15:54:56 +04:00
unsigned int i ;
2003-08-11 02:01:11 +04: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-01 15:31:43 +03:00
methods = domain - > methods ;
2001-08-18 23:43:28 +04:00
/* Query display info */
2005-06-09 02:10:34 +04:00
status = methods - > query_user_list ( domain , state - > mem_ctx ,
2001-12-11 03:03:58 +03:00
& num_entries , & info ) ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
if ( num_entries = = 0 )
continue ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
/* Allocate some memory for extra data */
total_entries + = num_entries ;
2001-05-07 08:32:40 +04:00
2004-12-07 21:25:53 +03:00
ted = SMB_REALLOC ( extra_data , sizeof ( fstring ) * total_entries ) ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
if ( ! ted ) {
2002-01-10 09:20:03 +03:00
DEBUG ( 0 , ( " failed to enlarge buffer! \n " ) ) ;
2001-12-11 03:03:58 +03:00
SAFE_FREE ( extra_data ) ;
goto done ;
} else
extra_data = ted ;
2001-05-07 08:32:40 +04:00
2001-12-11 03:03:58 +03:00
/* Pack user list into extra data fields */
for ( i = 0 ; i < num_entries ; i + + ) {
fstring acct_name , name ;
if ( ! info [ i ] . acct_name ) {
fstrcpy ( acct_name , " " ) ;
} else {
fstrcpy ( acct_name , info [ i ] . acct_name ) ;
}
2002-01-18 05:37:55 +03:00
fill_domain_username ( name , domain - > name , acct_name ) ;
2001-05-07 08:32:40 +04:00
/* Append to extra data */
2001-12-11 03:03:58 +03:00
memcpy ( & extra_data [ extra_data_len ] , name ,
strlen ( name ) ) ;
extra_data_len + = strlen ( name ) ;
extra_data [ extra_data_len + + ] = ' , ' ;
}
2000-05-09 15:43:00 +04:00
}
2001-05-07 08:32:40 +04: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 ;
}
/* No domains responded but that's still OK so don't return an
error . */
2000-05-09 15:43:00 +04:00
2001-10-19 05:46:43 +04:00
rv = WINBINDD_OK ;
done :
2005-06-20 17:42:29 +04:00
if ( rv = = WINBINDD_OK )
request_ok ( state ) ;
else
request_error ( state ) ;
2000-05-09 15:43:00 +04:00
}