2001-12-03 04:23:42 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-12-03 04:23:42 +03:00
Winbind rpc backend functions
2003-04-23 15:54:56 +04:00
Copyright ( C ) Tim Potter 2000 - 2001 , 2003
2001-12-03 04:23:42 +03:00
Copyright ( C ) Andrew Tridgell 2001
2005-01-15 22:00:18 +03:00
Copyright ( C ) Volker Lendecke 2005
2008-02-27 21:38:48 +03:00
Copyright ( C ) Guenther Deschner 2008 ( pidl conversion )
2009-08-03 00:28:49 +04:00
2001-12-03 04:23:42 +03: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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-12-03 04:23:42 +03:00
( at your option ) any later version .
2009-08-03 00:28:49 +04:00
2001-12-03 04:23:42 +03:00
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 .
2009-08-03 00:28:49 +04:00
2001-12-03 04:23:42 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-12-03 04:23:42 +03:00
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2001-12-03 04:23:42 +03:00
# include "winbindd.h"
2009-11-26 20:21:28 +03:00
# include "../librpc/gen_ndr/cli_samr.h"
2010-05-18 20:25:50 +04:00
# include "rpc_client/cli_samr.h"
2009-11-26 20:21:28 +03:00
# include "../librpc/gen_ndr/cli_lsa.h"
2010-05-18 20:26:16 +04:00
# include "rpc_client/cli_lsarpc.h"
2001-12-03 04:23:42 +03:00
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2003-04-23 15:54:56 +04:00
2001-12-03 04:23:42 +03:00
/* 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
application . */
2001-12-03 14:32:55 +03:00
static NTSTATUS query_user_list ( struct winbindd_domain * domain ,
2001-12-03 09:04:18 +03:00
TALLOC_CTX * mem_ctx ,
2001-12-11 03:03:58 +03:00
uint32 * num_entries ,
2009-08-09 15:31:31 +04:00
struct wbint_userinfo * * info )
2001-12-03 04:23:42 +03:00
{
2005-06-09 02:10:34 +04:00
NTSTATUS result ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2005-06-09 02:10:34 +04:00
unsigned int i , start_idx ;
2003-11-27 07:39:53 +03:00
uint32 loop_count ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2001-12-03 04:23:42 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " rpc: query_user_list \n " ) ) ;
2001-12-11 01:10:16 +03:00
* num_entries = 0 ;
2001-12-11 03:03:58 +03:00
* info = NULL ;
2001-12-11 01:10:16 +03:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " query_user_list: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
2001-12-03 04:23:42 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-03 04:23:42 +03:00
2003-04-23 15:54:56 +04:00
i = start_idx = 0 ;
2003-11-27 07:39:53 +03:00
loop_count = 0 ;
2001-12-11 03:03:58 +03:00
do {
2003-11-27 07:39:53 +03:00
uint32 num_dom_users , j ;
uint32 max_entries , max_size ;
2008-02-07 22:46:02 +03:00
uint32_t total_size , returned_size ;
2003-11-27 07:39:53 +03:00
2008-02-07 22:46:02 +03:00
union samr_DispInfo disp_info ;
2003-01-29 23:15:35 +03:00
2003-11-27 07:39:53 +03:00
/* this next bit is copied from net_user_list_internal() */
2005-06-09 02:10:34 +04:00
get_query_dispinfo_params ( loop_count , & max_entries ,
& max_size ) ;
2003-11-27 07:39:53 +03:00
2008-02-07 22:46:02 +03:00
result = rpccli_samr_QueryDisplayInfo ( cli , mem_ctx ,
& dom_pol ,
1 ,
start_idx ,
max_entries ,
max_size ,
& total_size ,
& returned_size ,
& disp_info ) ;
num_dom_users = disp_info . info1 . count ;
start_idx + = disp_info . info1 . count ;
2003-11-27 07:39:53 +03:00
loop_count + + ;
2003-01-29 23:15:35 +03:00
2003-04-23 15:54:56 +04:00
* num_entries + = num_dom_users ;
2001-12-11 03:03:58 +03:00
2009-08-09 15:31:31 +04:00
* info = TALLOC_REALLOC_ARRAY ( mem_ctx , * info ,
struct wbint_userinfo ,
2005-06-09 02:10:34 +04:00
* num_entries ) ;
2001-12-11 03:03:58 +03:00
if ( ! ( * info ) ) {
2005-06-09 02:10:34 +04:00
return NT_STATUS_NO_MEMORY ;
2001-12-11 03:03:58 +03:00
}
2003-04-23 15:54:56 +04:00
for ( j = 0 ; j < num_dom_users ; i + + , j + + ) {
2008-02-07 22:46:02 +03:00
uint32_t rid = disp_info . info1 . entries [ j ] . rid ;
2009-10-06 23:31:02 +04:00
struct samr_DispEntryGeneral * src ;
struct wbint_userinfo * dst ;
2008-02-07 22:46:02 +03:00
2009-10-06 23:31:02 +04:00
src = & ( disp_info . info1 . entries [ j ] ) ;
dst = & ( ( * info ) [ i ] ) ;
dst - > acct_name = talloc_strdup (
mem_ctx , src - > account_name . string ) ;
dst - > full_name = talloc_strdup (
mem_ctx , src - > full_name . string ) ;
dst - > homedir = NULL ;
dst - > shell = NULL ;
sid_compose ( & dst - > user_sid , & domain - > sid , rid ) ;
2009-08-03 00:28:49 +04:00
2001-12-11 03:03:58 +03:00
/* For the moment we set the primary group for
every user to be the Domain Users group .
There are serious problems with determining
the actual primary group for large domains .
This should really be made into a ' winbind
force group ' smb . conf parameter or
something like that . */
2009-08-03 00:28:49 +04:00
2009-10-06 23:31:02 +04:00
sid_compose ( & dst - > group_sid , & domain - > sid ,
2010-05-18 00:04:24 +04:00
DOMAIN_RID_USERS ) ;
2001-12-11 03:03:58 +03:00
}
2002-01-31 15:47:42 +03:00
2001-12-11 03:03:58 +03:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2001-12-03 04:23:42 +03:00
return result ;
}
/* list all domain groups */
2001-12-03 09:04:18 +03:00
static NTSTATUS enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2001-12-11 04:04:13 +03:00
uint32 * num_entries ,
2001-12-03 09:04:18 +03:00
struct acct_info * * info )
2001-12-03 04:23:42 +03:00
{
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2001-12-03 04:23:42 +03:00
NTSTATUS status ;
2003-01-06 10:29:38 +03:00
uint32 start = 0 ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2001-12-03 04:23:42 +03:00
* num_entries = 0 ;
2001-12-11 04:04:13 +03:00
* info = NULL ;
2001-12-03 04:23:42 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " rpc: enum_dom_groups \n " ) ) ;
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " enum_domain_groups: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-06-09 02:10:34 +04:00
status = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
2003-02-15 04:34:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) )
2001-12-03 04:23:42 +03:00
return status ;
2001-12-11 04:04:13 +03:00
do {
2008-02-13 13:08:49 +03:00
struct samr_SamArray * sam_array = NULL ;
2003-01-06 10:29:38 +03:00
uint32 count = 0 ;
2001-12-11 04:04:13 +03:00
TALLOC_CTX * mem_ctx2 ;
2008-02-13 13:08:49 +03:00
int g ;
2001-12-11 04:04:13 +03:00
2002-12-20 23:21:31 +03:00
mem_ctx2 = talloc_init ( " enum_dom_groups[rpc] " ) ;
2001-12-11 04:04:13 +03:00
2003-01-06 10:29:38 +03:00
/* start is updated by this call. */
2008-02-13 13:08:49 +03:00
status = rpccli_samr_EnumDomainGroups ( cli , mem_ctx2 ,
& dom_pol ,
& start ,
& sam_array ,
0xFFFF , /* buffer size? */
& count ) ;
2001-12-11 04:04:13 +03:00
2008-02-13 13:08:49 +03:00
if ( ! NT_STATUS_IS_OK ( status ) & &
2001-12-11 04:04:13 +03:00
! NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
talloc_destroy ( mem_ctx2 ) ;
break ;
}
2005-06-09 02:10:34 +04:00
( * info ) = TALLOC_REALLOC_ARRAY ( mem_ctx , * info ,
struct acct_info ,
( * num_entries ) + count ) ;
2001-12-11 04:04:13 +03:00
if ( ! * info ) {
talloc_destroy ( mem_ctx2 ) ;
2007-08-27 22:12:29 +04:00
return NT_STATUS_NO_MEMORY ;
2001-12-11 04:04:13 +03:00
}
2008-02-13 13:08:49 +03:00
for ( g = 0 ; g < count ; g + + ) {
fstrcpy ( ( * info ) [ * num_entries + g ] . acct_name ,
sam_array - > entries [ g ] . name . string ) ;
( * info ) [ * num_entries + g ] . rid = sam_array - > entries [ g ] . idx ;
}
2001-12-11 04:04:13 +03:00
( * num_entries ) + = count ;
talloc_destroy ( mem_ctx2 ) ;
} while ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) ;
2001-12-03 04:23:42 +03:00
2010-01-06 10:05:20 +03:00
return status ;
2001-12-03 04:23:42 +03:00
}
2002-10-08 22:32:42 +04:00
/* List all domain groups */
static NTSTATUS enum_local_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_entries ,
struct acct_info * * info )
{
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2002-10-08 22:32:42 +04:00
NTSTATUS result ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2002-10-08 22:32:42 +04:00
* num_entries = 0 ;
* info = NULL ;
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " rpc: enum_local_groups \n " ) ) ;
2002-10-08 22:32:42 +04:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " enum_local_groups: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
2002-10-08 22:32:42 +04:00
return result ;
do {
2008-02-13 13:15:40 +03:00
struct samr_SamArray * sam_array = NULL ;
2002-10-08 22:32:42 +04:00
uint32 count = 0 , start = * num_entries ;
TALLOC_CTX * mem_ctx2 ;
2008-02-13 13:15:40 +03:00
int g ;
2002-10-08 22:32:42 +04:00
2002-12-20 23:21:31 +03:00
mem_ctx2 = talloc_init ( " enum_dom_local_groups[rpc] " ) ;
2002-10-08 22:32:42 +04:00
2008-02-13 13:15:40 +03:00
result = rpccli_samr_EnumDomainAliases ( cli , mem_ctx2 ,
& dom_pol ,
& start ,
& sam_array ,
0xFFFF , /* buffer size? */
& count ) ;
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) & &
2008-02-13 13:15:40 +03:00
! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) )
2002-10-08 22:32:42 +04:00
{
talloc_destroy ( mem_ctx2 ) ;
2005-06-09 02:10:34 +04:00
return result ;
2002-10-08 22:32:42 +04:00
}
2005-06-09 02:10:34 +04:00
( * info ) = TALLOC_REALLOC_ARRAY ( mem_ctx , * info ,
struct acct_info ,
( * num_entries ) + count ) ;
2002-10-08 22:32:42 +04:00
if ( ! * info ) {
talloc_destroy ( mem_ctx2 ) ;
return NT_STATUS_NO_MEMORY ;
}
2008-02-13 13:15:40 +03:00
for ( g = 0 ; g < count ; g + + ) {
fstrcpy ( ( * info ) [ * num_entries + g ] . acct_name ,
sam_array - > entries [ g ] . name . string ) ;
( * info ) [ * num_entries + g ] . rid = sam_array - > entries [ g ] . idx ;
}
2002-10-08 22:32:42 +04:00
( * num_entries ) + = count ;
talloc_destroy ( mem_ctx2 ) ;
2005-06-09 02:10:34 +04:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2002-10-08 22:32:42 +04:00
2010-01-06 10:05:20 +03:00
return result ;
2002-10-08 22:32:42 +04:00
}
2001-12-03 11:17:46 +03:00
/* convert a single name to a sid in a domain */
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_name_to_sid ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const char * domain_name ,
const char * name ,
2009-08-02 12:43:05 +04:00
uint32_t flags ,
2010-05-21 05:25:01 +04:00
struct dom_sid * sid ,
2008-11-22 01:17:05 +03:00
enum lsa_SidType * type )
2001-12-03 11:17:46 +03:00
{
2003-06-21 08:05:01 +04:00
NTSTATUS result ;
2010-05-21 05:25:01 +04:00
struct dom_sid * sids = NULL ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType * types = NULL ;
2007-02-01 18:22:08 +03:00
char * full_name = NULL ;
2008-09-16 00:50:15 +04:00
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL ;
char * mapped_name = NULL ;
2001-12-03 11:17:46 +03:00
2007-07-02 13:46:18 +04:00
if ( name = = NULL | | * name = = ' \0 ' ) {
full_name = talloc_asprintf ( mem_ctx , " %s " , domain_name ) ;
} else if ( domain_name = = NULL | | * domain_name = = ' \0 ' ) {
full_name = talloc_asprintf ( mem_ctx , " %s " , name ) ;
} else {
full_name = talloc_asprintf ( mem_ctx , " %s \\ %s " , domain_name , name ) ;
}
2002-01-26 14:48:42 +03:00
if ( ! full_name ) {
DEBUG ( 0 , ( " talloc_asprintf failed! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2007-07-02 13:46:18 +04:00
DEBUG ( 3 , ( " rpc: name_to_sid name=%s \n " , full_name ) ) ;
2008-09-16 00:50:15 +04:00
name_map_status = normalize_name_unmap ( mem_ctx , full_name ,
& mapped_name ) ;
2007-01-31 08:38:36 +03:00
2008-09-16 00:50:15 +04:00
/* Reset the full_name pointer if we mapped anytthing */
if ( NT_STATUS_IS_OK ( name_map_status ) | |
NT_STATUS_EQUAL ( name_map_status , NT_STATUS_FILE_RENAMED ) )
{
full_name = mapped_name ;
}
DEBUG ( 3 , ( " name_to_sid [rpc] %s for domain %s \n " ,
full_name ? full_name : " " , domain_name ) ) ;
2003-06-21 08:05:01 +04:00
2009-09-17 10:06:34 +04:00
result = winbindd_lookup_names ( mem_ctx , domain , 1 ,
( const char * * ) & full_name , NULL ,
& sids , & types ) ;
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) )
return result ;
2002-07-15 14:35:28 +04:00
/* Return rid and type if lookup successful */
2005-06-09 02:10:34 +04:00
sid_copy ( sid , & sids [ 0 ] ) ;
2006-06-29 01:30:21 +04:00
* type = types [ 0 ] ;
2001-12-03 11:17:46 +03:00
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2001-12-03 11:17:46 +03:00
}
2001-12-03 14:11:14 +03:00
/*
convert a domain SID to a user or group name
*/
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-11-22 01:17:05 +03:00
char * * domain_name ,
char * * name ,
enum lsa_SidType * type )
2001-12-03 14:11:14 +03:00
{
2002-01-20 04:24:59 +03:00
char * * domains ;
2001-12-03 14:11:14 +03:00
char * * names ;
2008-01-12 09:44:33 +03:00
enum lsa_SidType * types = NULL ;
2003-06-21 08:05:01 +04:00
NTSTATUS result ;
2008-09-16 00:50:15 +04:00
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL ;
char * mapped_name = NULL ;
2001-12-03 14:11:14 +03:00
2007-12-15 23:11:36 +03:00
DEBUG ( 3 , ( " sid_to_name [rpc] %s for domain %s \n " , sid_string_dbg ( sid ) ,
domain - > name ) ) ;
2002-07-15 14:35:28 +04:00
2009-09-17 09:59:25 +04:00
result = winbindd_lookup_sids ( mem_ctx ,
domain ,
1 ,
sid ,
& domains ,
& names ,
& types ) ;
2007-05-07 00:16:12 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2009-09-17 09:59:25 +04:00
DEBUG ( 2 , ( " msrpc_sid_to_name: failed to lookup sids: %s \n " ,
nt_errstr ( result ) ) ) ;
2005-06-09 02:10:34 +04:00
return result ;
2007-05-07 00:16:12 +04:00
}
2009-08-03 00:28:49 +04:00
2001-12-03 14:11:14 +03:00
2006-09-08 18:28:06 +04:00
* type = ( enum lsa_SidType ) types [ 0 ] ;
2005-06-09 02:10:34 +04:00
* domain_name = domains [ 0 ] ;
* name = names [ 0 ] ;
2007-01-31 08:38:36 +03:00
2005-06-09 02:10:34 +04:00
DEBUG ( 5 , ( " Mapped sid to [%s] \\ [%s] \n " , domains [ 0 ] , * name ) ) ;
2008-09-16 00:50:15 +04:00
name_map_status = normalize_name_map ( mem_ctx , domain , * name ,
& mapped_name ) ;
if ( NT_STATUS_IS_OK ( name_map_status ) | |
NT_STATUS_EQUAL ( name_map_status , NT_STATUS_FILE_RENAMED ) )
{
* name = mapped_name ;
DEBUG ( 5 , ( " returning mapped name -- %s \n " , * name ) ) ;
}
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2001-12-03 14:11:14 +03:00
}
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_rids_to_names ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-11-22 01:17:05 +03:00
uint32 * rids ,
size_t num_rids ,
char * * domain_name ,
char * * * names ,
enum lsa_SidType * * types )
2006-07-11 22:01:26 +04:00
{
char * * domains ;
NTSTATUS result ;
2010-05-21 05:25:01 +04:00
struct dom_sid * sids ;
2006-07-11 22:01:26 +04:00
size_t i ;
2007-01-31 08:38:36 +03:00
char * * ret_names ;
2006-07-11 22:01:26 +04:00
DEBUG ( 3 , ( " rids_to_names [rpc] for domain %s \n " , domain - > name ) ) ;
2007-04-30 06:39:34 +04:00
if ( num_rids ) {
2010-05-21 05:25:01 +04:00
sids = TALLOC_ARRAY ( mem_ctx , struct dom_sid , num_rids ) ;
2007-04-30 06:39:34 +04:00
if ( sids = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
} else {
sids = NULL ;
2006-07-11 22:01:26 +04:00
}
for ( i = 0 ; i < num_rids ; i + + ) {
if ( ! sid_compose ( & sids [ i ] , sid , rids [ i ] ) ) {
return NT_STATUS_INTERNAL_ERROR ;
}
}
2009-09-17 09:59:25 +04:00
result = winbindd_lookup_sids ( mem_ctx ,
domain ,
num_rids ,
sids ,
& domains ,
names ,
types ) ;
2009-08-11 15:50:16 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_EQUAL ( result , STATUS_SOME_UNMAPPED ) ) {
return result ;
}
2007-01-31 08:38:36 +03:00
ret_names = * names ;
2006-07-11 22:01:26 +04:00
for ( i = 0 ; i < num_rids ; i + + ) {
2008-09-16 00:50:15 +04:00
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL ;
char * mapped_name = NULL ;
2006-07-11 22:01:26 +04:00
if ( ( * types ) [ i ] ! = SID_NAME_UNKNOWN ) {
2008-09-16 00:50:15 +04:00
name_map_status = normalize_name_map ( mem_ctx ,
domain ,
ret_names [ i ] ,
& mapped_name ) ;
if ( NT_STATUS_IS_OK ( name_map_status ) | |
NT_STATUS_EQUAL ( name_map_status , NT_STATUS_FILE_RENAMED ) )
{
ret_names [ i ] = mapped_name ;
}
2006-07-11 22:01:26 +04:00
* domain_name = domains [ i ] ;
}
}
return result ;
}
2001-12-04 09:17:39 +03:00
/* Lookup user information from a rid or username. */
static NTSTATUS query_user ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * user_sid ,
2009-08-09 15:31:31 +04:00
struct wbint_userinfo * user_info )
2001-12-04 09:17:39 +03:00
{
2003-04-23 15:54:56 +04:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol , user_pol ;
2008-02-12 20:13:30 +03:00
union samr_UserInfo * info = NULL ;
2003-04-23 15:54:56 +04:00
uint32 user_rid ;
2008-02-17 04:08:12 +03:00
struct netr_SamInfo3 * user ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2001-12-04 09:17:39 +03:00
2007-12-15 23:11:36 +03:00
DEBUG ( 3 , ( " rpc: query_user sid=%s \n " , sid_string_dbg ( user_sid ) ) ) ;
2005-06-09 02:10:34 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , user_sid , & user_rid ) )
return NT_STATUS_UNSUCCESSFUL ;
2009-08-03 00:28:49 +04:00
2007-05-07 00:16:12 +04:00
user_info - > homedir = NULL ;
user_info - > shell = NULL ;
user_info - > primary_gid = ( gid_t ) - 1 ;
2009-08-03 00:28:49 +04:00
2005-11-10 23:28:23 +03:00
/* try netsamlogon cache first */
2009-08-03 00:28:49 +04:00
2005-11-10 23:28:23 +03:00
if ( ( user = netsamlogon_cache_get ( mem_ctx , user_sid ) ) ! = NULL )
{
2009-08-03 00:28:49 +04:00
2005-11-10 23:28:23 +03:00
DEBUG ( 5 , ( " query_user: Cache lookup succeeded for %s \n " ,
2007-12-15 23:11:36 +03:00
sid_string_dbg ( user_sid ) ) ) ;
2005-11-10 23:28:23 +03:00
2008-02-17 04:08:12 +03:00
sid_compose ( & user_info - > user_sid , & domain - > sid , user - > base . rid ) ;
2005-11-10 23:28:23 +03:00
sid_compose ( & user_info - > group_sid , & domain - > sid ,
2008-02-17 04:08:12 +03:00
user - > base . primary_gid ) ;
2009-08-03 00:28:49 +04:00
2008-02-17 04:08:12 +03:00
user_info - > acct_name = talloc_strdup ( mem_ctx ,
user - > base . account_name . string ) ;
user_info - > full_name = talloc_strdup ( mem_ctx ,
user - > base . full_name . string ) ;
2009-08-03 00:28:49 +04:00
2007-05-03 16:29:32 +04:00
TALLOC_FREE ( user ) ;
2009-08-03 00:28:49 +04:00
2007-05-07 00:16:12 +04:00
return NT_STATUS_OK ;
}
2009-08-03 00:28:49 +04:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " query_user: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
2005-11-10 23:28:23 +03:00
return NT_STATUS_OK ;
}
2009-08-03 00:28:49 +04:00
2005-11-10 23:28:23 +03:00
/* no cache; hit the wire */
2009-08-03 00:28:49 +04:00
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
2001-12-04 09:17:39 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-04 09:17:39 +03:00
/* Get user handle */
2008-02-01 13:57:53 +03:00
result = rpccli_samr_OpenUser ( cli , mem_ctx ,
& dom_pol ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED ,
2008-02-01 13:57:53 +03:00
user_rid ,
& user_pol ) ;
2001-12-04 09:17:39 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2002-04-04 06:39:57 +04:00
2001-12-04 09:17:39 +03:00
/* Get user info */
2008-02-12 20:13:30 +03:00
result = rpccli_samr_QueryUserInfo ( cli , mem_ctx ,
& user_pol ,
0x15 ,
& info ) ;
2001-12-04 09:17:39 +03:00
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( cli , mem_ctx , & user_pol ) ;
2002-07-15 14:35:28 +04:00
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) )
return result ;
2001-12-04 09:17:39 +03:00
2005-06-09 02:10:34 +04:00
sid_compose ( & user_info - > user_sid , & domain - > sid , user_rid ) ;
sid_compose ( & user_info - > group_sid , & domain - > sid ,
2008-02-12 20:13:30 +03:00
info - > info21 . primary_gid ) ;
user_info - > acct_name = talloc_strdup ( mem_ctx ,
info - > info21 . account_name . string ) ;
user_info - > full_name = talloc_strdup ( mem_ctx ,
info - > info21 . full_name . string ) ;
2005-06-29 18:03:53 +04:00
user_info - > homedir = NULL ;
user_info - > shell = NULL ;
2007-02-16 18:13:57 +03:00
user_info - > primary_gid = ( gid_t ) - 1 ;
2001-12-04 09:17:39 +03:00
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2001-12-04 09:17:39 +03:00
}
2001-12-04 09:46:53 +03:00
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * user_sid ,
uint32 * num_groups , struct dom_sid * * user_grpsids )
2001-12-04 09:46:53 +03:00
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol , user_pol ;
2009-04-15 03:12:13 +04:00
uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED ;
2008-02-06 18:19:20 +03:00
struct samr_RidWithAttributeArray * rid_array = NULL ;
2003-04-23 15:54:56 +04:00
unsigned int i ;
uint32 user_rid ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2007-12-15 23:11:36 +03:00
DEBUG ( 3 , ( " rpc: lookup_usergroups sid=%s \n " , sid_string_dbg ( user_sid ) ) ) ;
2001-12-04 09:46:53 +03:00
2005-06-09 02:10:34 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , user_sid , & user_rid ) )
return NT_STATUS_UNSUCCESSFUL ;
2002-07-15 14:35:28 +04:00
2001-12-11 01:10:16 +03:00
* num_groups = 0 ;
2003-06-21 08:05:01 +04:00
* user_grpsids = NULL ;
2005-11-10 23:28:23 +03:00
/* so lets see if we have a cached user_info_3 */
2006-04-28 18:48:22 +04:00
result = lookup_usergroups_cached ( domain , mem_ctx , user_sid ,
num_groups , user_grpsids ) ;
if ( NT_STATUS_IS_OK ( result ) ) {
2005-11-10 23:28:23 +03:00
return NT_STATUS_OK ;
}
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_usergroups: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
/* Tell the cache manager not to remember this one */
return NT_STATUS_SYNCHRONIZATION_REQUIRED ;
}
2005-11-10 23:28:23 +03:00
/* no cache; hit the wire */
2009-08-03 00:28:49 +04:00
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
2001-12-04 09:46:53 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2003-04-23 15:54:56 +04:00
2001-12-04 09:46:53 +03:00
/* Get user handle */
2008-02-01 13:57:53 +03:00
result = rpccli_samr_OpenUser ( cli , mem_ctx ,
& dom_pol ,
des_access ,
user_rid ,
& user_pol ) ;
2001-12-04 09:46:53 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-04 09:46:53 +03:00
/* Query user rids */
2008-02-06 18:19:20 +03:00
result = rpccli_samr_GetGroupsForUser ( cli , mem_ctx ,
& user_pol ,
& rid_array ) ;
* num_groups = rid_array - > count ;
2001-12-04 09:46:53 +03:00
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( cli , mem_ctx , & user_pol ) ;
2005-06-09 02:10:34 +04:00
2001-12-04 09:46:53 +03:00
if ( ! NT_STATUS_IS_OK ( result ) | | ( * num_groups ) = = 0 )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-04 09:46:53 +03:00
2010-05-21 05:25:01 +04:00
( * user_grpsids ) = TALLOC_ARRAY ( mem_ctx , struct dom_sid , * num_groups ) ;
2005-06-09 02:10:34 +04:00
if ( ! ( * user_grpsids ) )
return NT_STATUS_NO_MEMORY ;
2003-04-23 15:54:56 +04:00
2001-12-04 09:46:53 +03:00
for ( i = 0 ; i < ( * num_groups ) ; i + + ) {
2010-01-10 19:39:27 +03:00
sid_compose ( & ( ( * user_grpsids ) [ i ] ) , & domain - > sid ,
rid_array - > rids [ i ] . rid ) ;
2001-12-04 09:46:53 +03:00
}
2008-02-06 18:19:20 +03:00
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2001-12-04 09:46:53 +03:00
}
2008-11-05 15:39:25 +03:00
# define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_lookup_useraliases ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
uint32 num_sids , const struct dom_sid * sids ,
2008-11-22 01:17:05 +03:00
uint32 * num_aliases ,
uint32 * * alias_rids )
2005-01-15 22:00:18 +03:00
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2006-06-19 20:00:32 +04:00
uint32 num_query_sids = 0 ;
2005-06-09 02:10:34 +04:00
int i ;
struct rpc_pipe_client * cli ;
2008-02-05 04:45:51 +03:00
struct samr_Ids alias_rids_query ;
2006-06-19 20:00:32 +04:00
int rangesize = MAX_SAM_ENTRIES_W2K ;
uint32 total_sids = 0 ;
int num_queries = 1 ;
2005-01-15 22:00:18 +03:00
* num_aliases = 0 ;
* alias_rids = NULL ;
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " rpc: lookup_useraliases \n " ) ) ;
2005-01-15 22:00:18 +03:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " msrpc_lookup_useraliases: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
2005-01-15 22:00:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2005-01-15 22:00:18 +03:00
2006-06-19 20:00:32 +04:00
do {
/* prepare query */
2008-02-05 04:45:51 +03:00
struct lsa_SidArray sid_array ;
ZERO_STRUCT ( sid_array ) ;
2005-01-15 22:00:18 +03:00
2006-06-19 20:00:32 +04:00
num_query_sids = MIN ( num_sids - total_sids , rangesize ) ;
2005-01-15 22:00:18 +03:00
2006-06-19 20:00:32 +04:00
DEBUG ( 10 , ( " rpc: lookup_useraliases: entering query %d for %d sids \n " ,
num_queries , num_query_sids ) ) ;
2007-04-30 06:39:34 +04:00
if ( num_query_sids ) {
2008-02-05 04:45:51 +03:00
sid_array . sids = TALLOC_ZERO_ARRAY ( mem_ctx , struct lsa_SidPtr , num_query_sids ) ;
if ( sid_array . sids = = NULL ) {
2007-04-30 06:39:34 +04:00
return NT_STATUS_NO_MEMORY ;
}
} else {
2008-02-05 04:45:51 +03:00
sid_array . sids = NULL ;
2006-06-19 20:00:32 +04:00
}
for ( i = 0 ; i < num_query_sids ; i + + ) {
2008-02-05 04:45:51 +03:00
sid_array . sids [ i ] . sid = sid_dup_talloc ( mem_ctx , & sids [ total_sids + + ] ) ;
2008-02-08 12:59:31 +03:00
if ( ! sid_array . sids [ i ] . sid ) {
2008-02-05 04:45:51 +03:00
TALLOC_FREE ( sid_array . sids ) ;
return NT_STATUS_NO_MEMORY ;
}
2006-06-19 20:00:32 +04:00
}
2008-02-05 04:45:51 +03:00
sid_array . num_sids = num_query_sids ;
2006-06-19 20:00:32 +04:00
/* do request */
2008-02-05 04:45:51 +03:00
result = rpccli_samr_GetAliasMembership ( cli , mem_ctx ,
& dom_pol ,
& sid_array ,
& alias_rids_query ) ;
2006-06-19 20:00:32 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
* num_aliases = 0 ;
* alias_rids = NULL ;
2008-02-05 04:45:51 +03:00
TALLOC_FREE ( sid_array . sids ) ;
2006-06-19 20:00:32 +04:00
goto done ;
}
/* process output */
2008-02-05 04:45:51 +03:00
for ( i = 0 ; i < alias_rids_query . count ; i + + ) {
2006-06-19 22:49:51 +04:00
size_t na = * num_aliases ;
2008-02-05 04:45:51 +03:00
if ( ! add_rid_to_array_unique ( mem_ctx , alias_rids_query . ids [ i ] ,
2006-12-09 05:58:18 +03:00
alias_rids , & na ) ) {
return NT_STATUS_NO_MEMORY ;
}
2006-06-19 22:49:51 +04:00
* num_aliases = na ;
2006-06-19 20:00:32 +04:00
}
2008-02-05 04:45:51 +03:00
TALLOC_FREE ( sid_array . sids ) ;
2006-06-19 20:00:32 +04:00
num_queries + + ;
} while ( total_sids < num_sids ) ;
2005-01-15 22:00:18 +03:00
2006-06-19 20:00:32 +04:00
done :
DEBUG ( 10 , ( " rpc: lookup_useraliases: got %d aliases in %d queries "
" (rangesize: %d) \n " , * num_aliases , num_queries , rangesize ) ) ;
2005-01-15 22:00:18 +03:00
return result ;
}
2001-12-03 04:23:42 +03:00
2001-12-05 07:48:51 +03:00
/* Lookup group membership given a rid. */
static NTSTATUS lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * group_sid ,
2009-08-28 16:25:11 +04:00
enum lsa_SidType type ,
uint32 * num_names ,
2010-05-21 05:25:01 +04:00
struct dom_sid * * sid_mem , char * * * names ,
2001-12-05 07:48:51 +03:00
uint32 * * name_types )
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
uint32 i , total_names = 0 ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol , group_pol ;
2009-04-15 03:12:13 +04:00
uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED ;
2003-04-23 15:54:56 +04:00
uint32 * rid_mem = NULL ;
uint32 group_rid ;
2008-02-13 12:49:55 +03:00
unsigned int j , r ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2006-10-16 18:29:14 +04:00
unsigned int orig_timeout ;
2008-02-05 12:58:37 +03:00
struct samr_RidTypeArray * rids = NULL ;
2001-12-05 07:48:51 +03:00
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " rpc: lookup_groupmem %s sid=%s \n " , domain - > name ,
2007-12-15 23:11:36 +03:00
sid_string_dbg ( group_sid ) ) ) ;
2003-04-23 15:54:56 +04:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_groupmem: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-06-09 02:10:34 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , group_sid , & group_rid ) )
return NT_STATUS_UNSUCCESSFUL ;
2002-07-15 14:35:28 +04:00
2001-12-11 01:10:16 +03:00
* num_names = 0 ;
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
return result ;
2001-12-05 07:48:51 +03:00
2008-02-01 13:24:01 +03:00
result = rpccli_samr_OpenGroup ( cli , mem_ctx ,
& dom_pol ,
des_access ,
group_rid ,
& group_pol ) ;
2001-12-05 07:48:51 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-05 07:48:51 +03:00
/* Step #1: Get a list of user rids that are the members of the
group . */
2006-10-16 18:29:14 +04:00
/* This call can take a long time - allow the server to time out.
35 seconds should do it . */
2008-04-20 01:27:35 +04:00
orig_timeout = rpccli_set_timeout ( cli , 35000 ) ;
2006-10-16 18:29:14 +04:00
2008-02-05 12:58:37 +03:00
result = rpccli_samr_QueryGroupMember ( cli , mem_ctx ,
& group_pol ,
& rids ) ;
2005-06-09 02:10:34 +04:00
2006-10-16 18:29:14 +04:00
/* And restore our original timeout. */
2008-04-20 01:27:35 +04:00
rpccli_set_timeout ( cli , orig_timeout ) ;
2006-10-16 18:29:14 +04:00
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( cli , mem_ctx , & group_pol ) ;
2001-12-05 07:48:51 +03:00
if ( ! NT_STATUS_IS_OK ( result ) )
2005-06-09 02:10:34 +04:00
return result ;
2001-12-05 07:48:51 +03:00
2009-12-30 23:04:55 +03:00
if ( ! rids | | ! rids - > count ) {
2004-01-02 08:33:14 +03:00
names = NULL ;
name_types = NULL ;
sid_mem = NULL ;
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2004-01-02 08:33:14 +03:00
}
2009-12-30 23:04:55 +03:00
* num_names = rids - > count ;
rid_mem = rids - > rids ;
2001-12-05 07:48:51 +03:00
/* Step #2: Convert list of rids into list of usernames. Do this
in bunches of ~ 1000 to avoid crashing NT4 . It looks like there
is a buffer overflow or something like that lurking around
somewhere . */
# define MAX_LOOKUP_RIDS 900
2004-12-07 21:25:53 +03:00
* names = TALLOC_ZERO_ARRAY ( mem_ctx , char * , * num_names ) ;
* name_types = TALLOC_ZERO_ARRAY ( mem_ctx , uint32 , * num_names ) ;
2010-05-21 05:25:01 +04:00
* sid_mem = TALLOC_ZERO_ARRAY ( mem_ctx , struct dom_sid , * num_names ) ;
2003-04-23 15:54:56 +04:00
2005-06-09 02:10:34 +04:00
for ( j = 0 ; j < ( * num_names ) ; j + + )
sid_compose ( & ( * sid_mem ) [ j ] , & domain - > sid , rid_mem [ j ] ) ;
2009-08-03 00:28:49 +04:00
2005-06-09 02:10:34 +04:00
if ( * num_names > 0 & & ( ! * names | | ! * name_types ) )
return NT_STATUS_NO_MEMORY ;
2001-12-05 07:48:51 +03:00
2008-02-13 12:49:55 +03:00
for ( i = 0 ; i < * num_names ; i + = MAX_LOOKUP_RIDS ) {
int num_lookup_rids = MIN ( * num_names - i , MAX_LOOKUP_RIDS ) ;
struct lsa_Strings tmp_names ;
struct samr_Ids tmp_types ;
2001-12-05 07:48:51 +03:00
2008-02-13 12:49:55 +03:00
/* Lookup a chunk of rids */
2001-12-05 07:48:51 +03:00
2008-02-13 12:49:55 +03:00
result = rpccli_samr_LookupRids ( cli , mem_ctx ,
& dom_pol ,
num_lookup_rids ,
& rid_mem [ i ] ,
& tmp_names ,
& tmp_types ) ;
2001-12-05 07:48:51 +03:00
2005-06-09 02:10:34 +04:00
/* see if we have a real error (and yes the
STATUS_SOME_UNMAPPED is the one returned from 2 k ) */
2008-02-13 12:49:55 +03:00
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_EQUAL ( result , STATUS_SOME_UNMAPPED ) )
return result ;
2001-12-05 07:48:51 +03:00
2008-02-13 12:49:55 +03:00
/* Copy result into array. The talloc system will take
care of freeing the temporary arrays later on . */
2001-12-05 07:48:51 +03:00
2008-02-13 12:49:55 +03:00
if ( tmp_names . count ! = tmp_types . count ) {
return NT_STATUS_UNSUCCESSFUL ;
}
for ( r = 0 ; r < tmp_names . count ; r + + ) {
2009-03-16 15:17:04 +03:00
if ( tmp_types . ids [ r ] = = SID_NAME_UNKNOWN ) {
continue ;
}
( * names ) [ total_names ] = fill_domain_username_talloc (
mem_ctx , domain - > name ,
tmp_names . names [ r ] . string , true ) ;
( * name_types ) [ total_names ] = tmp_types . ids [ r ] ;
total_names + = 1 ;
2008-02-13 12:49:55 +03:00
}
2001-12-05 07:48:51 +03:00
}
* num_names = total_names ;
2005-06-09 02:10:34 +04:00
return NT_STATUS_OK ;
2001-12-05 07:48:51 +03:00
}
2003-06-23 09:10:07 +04:00
# ifdef HAVE_LDAP
# include <ldap.h>
2003-06-25 21:41:05 +04:00
static int get_ldap_seq ( const char * server , int port , uint32 * seq )
2003-06-23 09:10:07 +04:00
{
int ret = - 1 ;
struct timeval to ;
2005-02-17 17:27:34 +03:00
const char * attrs [ ] = { " highestCommittedUSN " , NULL } ;
2003-06-23 09:10:07 +04:00
LDAPMessage * res = NULL ;
char * * values = NULL ;
LDAP * ldp = NULL ;
* seq = DOM_SEQUENCE_NONE ;
/*
2005-06-09 02:10:34 +04:00
* Parameterised ( 5 ) second timeout on open . This is needed as the
* search timeout doesn ' t seem to apply to doing an open as well . JRA .
2003-06-23 09:10:07 +04:00
*/
2005-06-09 02:10:34 +04:00
ldp = ldap_open_with_timeout ( server , port , lp_ldap_timeout ( ) ) ;
if ( ldp = = NULL )
2003-06-23 09:10:07 +04:00
return - 1 ;
/* Timeout if no response within 20 seconds. */
to . tv_sec = 10 ;
to . tv_usec = 0 ;
2005-03-30 08:40:24 +04:00
if ( ldap_search_st ( ldp , " " , LDAP_SCOPE_BASE , " (objectclass=*) " ,
2005-06-09 02:10:34 +04:00
CONST_DISCARD ( char * * , attrs ) , 0 , & to , & res ) )
2003-06-23 09:10:07 +04:00
goto done ;
if ( ldap_count_entries ( ldp , res ) ! = 1 )
goto done ;
values = ldap_get_values ( ldp , res , " highestCommittedUSN " ) ;
if ( ! values | | ! values [ 0 ] )
goto done ;
* seq = atoi ( values [ 0 ] ) ;
ret = 0 ;
done :
if ( values )
ldap_value_free ( values ) ;
if ( res )
ldap_msgfree ( res ) ;
if ( ldp )
ldap_unbind ( ldp ) ;
return ret ;
}
/**********************************************************************
Get the sequence number for a Windows AD native mode domain using
2007-10-25 01:16:54 +04:00
LDAP queries .
2003-06-23 09:10:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-07 01:43:31 +04:00
static int get_ldap_sequence_number ( struct winbindd_domain * domain , uint32 * seq )
2003-06-23 09:10:07 +04:00
{
int ret = - 1 ;
2007-10-25 01:16:54 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2003-06-23 09:10:07 +04:00
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , & domain - > dcaddr ) ;
if ( ( ret = get_ldap_seq ( addr , LDAP_PORT , seq ) ) = = 0 ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " get_ldap_sequence_number: Retrieved sequence "
2007-10-25 01:16:54 +04:00
" number for Domain (%s) from DC (%s) \n " ,
domain - > name , addr ) ) ;
}
2003-06-23 09:10:07 +04:00
return ret ;
}
# endif /* HAVE_LDAP */
2001-12-05 10:52:44 +03:00
/* find the sequence number for a domain */
2001-12-10 02:59:42 +03:00
static NTSTATUS sequence_number ( struct winbindd_domain * domain , uint32 * seq )
2001-12-05 10:52:44 +03:00
{
TALLOC_CTX * mem_ctx ;
2008-02-05 19:25:07 +03:00
union samr_DomainInfo * info = NULL ;
2001-12-05 10:52:44 +03:00
NTSTATUS result ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2007-10-19 04:40:25 +04:00
bool got_seq_num = False ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2001-12-05 10:52:44 +03:00
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " rpc: fetch sequence_number for %s \n " , domain - > name ) ) ;
2002-07-15 14:35:28 +04:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " sequence_number: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
2007-10-25 01:16:54 +04:00
* seq = time ( NULL ) ;
2007-05-07 00:16:12 +04:00
return NT_STATUS_OK ;
}
2001-12-10 02:59:42 +03:00
* seq = DOM_SEQUENCE_NONE ;
2002-12-20 23:21:31 +03:00
if ( ! ( mem_ctx = talloc_init ( " sequence_number[rpc] " ) ) )
2001-12-10 02:59:42 +03:00
return NT_STATUS_NO_MEMORY ;
2001-12-05 10:52:44 +03:00
2005-06-09 02:10:34 +04:00
# ifdef HAVE_LDAP
2007-05-06 23:37:13 +04:00
if ( domain - > active_directory )
2005-06-09 02:10:34 +04:00
{
int res ;
DEBUG ( 8 , ( " using get_ldap_seq() to retrieve the "
" sequence number \n " ) ) ;
2006-09-07 01:52:06 +04:00
res = get_ldap_sequence_number ( domain , seq ) ;
2005-06-09 02:10:34 +04:00
if ( res = = 0 )
{
result = NT_STATUS_OK ;
DEBUG ( 10 , ( " domain_sequence_number: LDAP for "
" domain %s is %u \n " ,
domain - > name , * seq ) ) ;
2003-02-15 04:34:37 +03:00
goto done ;
2005-06-09 02:10:34 +04:00
}
2001-12-05 10:52:44 +03:00
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " domain_sequence_number: failed to get LDAP "
" sequence number for domain %s \n " ,
domain - > name ) ) ;
}
# endif /* HAVE_LDAP */
2001-12-05 10:52:44 +03:00
2005-06-09 02:10:34 +04:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
2001-12-05 10:52:44 +03:00
goto done ;
2005-06-09 02:10:34 +04:00
}
2001-12-05 10:52:44 +03:00
/* Query domain info */
2008-02-05 19:25:07 +03:00
result = rpccli_samr_QueryDomainInfo ( cli , mem_ctx ,
& dom_pol ,
8 ,
& info ) ;
2001-12-05 10:52:44 +03:00
if ( NT_STATUS_IS_OK ( result ) ) {
2008-02-05 19:25:07 +03:00
* seq = info - > info8 . sequence_num ;
2004-12-22 19:58:43 +03:00
got_seq_num = True ;
goto seq_num ;
}
/* retry with info-level 2 in case the dc does not support info-level 8
2008-02-05 19:25:07 +03:00
* ( like all older samba2 and samba3 dc ' s ) - Guenther */
result = rpccli_samr_QueryDomainInfo ( cli , mem_ctx ,
& dom_pol ,
2 ,
& info ) ;
2004-12-22 19:58:43 +03:00
if ( NT_STATUS_IS_OK ( result ) ) {
2008-10-15 19:10:53 +04:00
* seq = info - > general . sequence_num ;
2004-12-22 19:58:43 +03:00
got_seq_num = True ;
}
seq_num :
if ( got_seq_num ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " domain_sequence_number: for domain %s is %u \n " ,
domain - > name , ( unsigned ) * seq ) ) ;
2001-12-05 10:52:44 +03:00
} else {
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " domain_sequence_number: failed to get sequence "
" number (%u) for domain %s \n " ,
( unsigned ) * seq , domain - > name ) ) ;
2001-12-05 10:52:44 +03:00
}
done :
talloc_destroy ( mem_ctx ) ;
2001-12-10 02:59:42 +03:00
return result ;
2001-12-05 10:52:44 +03:00
}
2001-12-10 05:25:19 +03:00
/* get a list of trusted domains */
static NTSTATUS trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2009-12-28 17:51:36 +03:00
struct netr_DomainTrustList * trusts )
2001-12-10 05:25:19 +03:00
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
uint32 enum_ctx = 0 ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2009-03-19 00:49:41 +03:00
struct policy_handle lsa_policy ;
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " rpc: trusted_domains \n " ) ) ;
2001-12-10 05:25:19 +03:00
2009-12-28 17:51:36 +03:00
ZERO_STRUCTP ( trusts ) ;
2001-12-11 01:10:16 +03:00
2005-06-09 02:10:34 +04:00
result = cm_connect_lsa ( domain , mem_ctx , & cli , & lsa_policy ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
return result ;
2003-02-15 04:34:37 +03:00
2005-06-09 02:10:34 +04:00
result = STATUS_MORE_ENTRIES ;
2001-12-10 05:25:19 +03:00
2005-06-09 02:10:34 +04:00
while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
2008-02-13 02:25:40 +03:00
uint32 start_idx ;
2005-06-09 02:10:34 +04:00
int i ;
2008-02-13 02:25:40 +03:00
struct lsa_DomainList dom_list ;
2005-06-09 02:10:34 +04:00
2008-02-13 02:25:40 +03:00
result = rpccli_lsa_EnumTrustDom ( cli , mem_ctx ,
& lsa_policy ,
& enum_ctx ,
& dom_list ,
( uint32_t ) - 1 ) ;
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) )
break ;
2009-12-28 17:51:36 +03:00
start_idx = trusts - > count ;
trusts - > count + = dom_list . count ;
trusts - > array = talloc_realloc (
mem_ctx , trusts - > array , struct netr_DomainTrust ,
trusts - > count ) ;
if ( trusts - > array = = NULL ) {
2005-06-09 02:10:34 +04:00
return NT_STATUS_NO_MEMORY ;
2009-12-28 17:51:36 +03:00
}
2005-06-09 02:10:34 +04:00
2008-02-13 03:29:52 +03:00
for ( i = 0 ; i < dom_list . count ; i + + ) {
2009-12-28 17:51:36 +03:00
struct netr_DomainTrust * trust = & trusts - > array [ i ] ;
struct dom_sid * sid ;
ZERO_STRUCTP ( trust ) ;
trust - > netbios_name = talloc_move (
trusts - > array ,
& dom_list . domains [ i ] . name . string ) ;
trust - > dns_name = NULL ;
sid = talloc ( trusts - > array , struct dom_sid ) ;
if ( sid = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
sid_copy ( sid , dom_list . domains [ i ] . sid ) ;
trust - > sid = sid ;
2005-06-09 02:10:34 +04:00
}
}
2001-12-10 05:25:19 +03:00
return result ;
}
2006-02-04 01:19:41 +03:00
/* find the lockout policy for a domain */
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_lockout_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo12 * lockout_policy )
2006-02-04 01:19:41 +03:00
{
NTSTATUS result ;
struct rpc_pipe_client * cli ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2008-02-05 19:25:07 +03:00
union samr_DomainInfo * info = NULL ;
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " rpc: fetch lockout policy for %s \n " , domain - > name ) ) ;
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " msrpc_lockout_policy: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_NOT_SUPPORTED ;
}
2006-02-04 01:19:41 +03:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
2008-02-05 19:25:07 +03:00
result = rpccli_samr_QueryDomainInfo ( cli , mem_ctx ,
& dom_pol ,
12 ,
& info ) ;
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
2008-02-05 19:25:07 +03:00
* lockout_policy = info - > info12 ;
2006-02-04 01:19:41 +03:00
2008-02-05 19:25:07 +03:00
DEBUG ( 10 , ( " msrpc_lockout_policy: lockout_threshold %d \n " ,
info - > info12 . lockout_threshold ) ) ;
2006-02-04 01:19:41 +03:00
done :
return result ;
}
/* find the password policy for a domain */
2008-11-22 01:17:05 +03:00
static NTSTATUS msrpc_password_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo1 * password_policy )
2006-02-04 01:19:41 +03:00
{
NTSTATUS result ;
struct rpc_pipe_client * cli ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2008-02-05 19:25:07 +03:00
union samr_DomainInfo * info = NULL ;
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " rpc: fetch password policy for %s \n " , domain - > name ) ) ;
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " msrpc_password_policy: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_NOT_SUPPORTED ;
}
2006-02-04 01:19:41 +03:00
result = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
2008-02-05 19:25:07 +03:00
result = rpccli_samr_QueryDomainInfo ( cli , mem_ctx ,
& dom_pol ,
1 ,
& info ) ;
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
2008-02-05 19:25:07 +03:00
* password_policy = info - > info1 ;
2006-02-04 01:19:41 +03:00
2008-02-05 19:25:07 +03:00
DEBUG ( 10 , ( " msrpc_password_policy: min_length_password %d \n " ,
info - > info1 . min_password_length ) ) ;
2006-02-04 01:19:41 +03:00
done :
return result ;
}
2009-09-17 11:43:36 +04:00
typedef NTSTATUS ( * lookup_sids_fn_t ) ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
struct policy_handle * pol ,
int num_sids ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sids ,
2009-09-17 11:43:36 +04:00
char * * * pdomains ,
char * * * pnames ,
enum lsa_SidType * * ptypes ) ;
2009-09-17 09:59:25 +04:00
NTSTATUS winbindd_lookup_sids ( TALLOC_CTX * mem_ctx ,
struct winbindd_domain * domain ,
uint32_t num_sids ,
const struct dom_sid * sids ,
char * * * domains ,
char * * * names ,
enum lsa_SidType * * types )
{
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle lsa_policy ;
unsigned int orig_timeout ;
2009-09-17 11:43:36 +04:00
lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids ;
2009-09-17 09:59:25 +04:00
2009-09-17 11:43:36 +04:00
if ( domain - > can_do_ncacn_ip_tcp ) {
status = cm_connect_lsa_tcp ( domain , mem_ctx , & cli ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
lookup_sids_fn = rpccli_lsa_lookup_sids3 ;
goto lookup ;
}
domain - > can_do_ncacn_ip_tcp = false ;
}
2009-09-17 09:59:25 +04:00
status = cm_connect_lsa ( domain , mem_ctx , & cli , & lsa_policy ) ;
2009-09-17 11:43:36 +04:00
2009-09-17 09:59:25 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-09-17 11:43:36 +04:00
lookup :
2009-09-17 09:59:25 +04:00
/*
* This call can take a long time
* allow the server to time out .
* 35 seconds should do it .
*/
orig_timeout = rpccli_set_timeout ( cli , 35000 ) ;
2009-09-17 11:43:36 +04:00
status = lookup_sids_fn ( cli ,
mem_ctx ,
& lsa_policy ,
num_sids ,
sids ,
domains ,
names ,
types ) ;
2009-09-17 09:59:25 +04:00
/* And restore our original timeout. */
rpccli_set_timeout ( cli , orig_timeout ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return status ;
}
2009-09-17 11:43:36 +04:00
typedef NTSTATUS ( * lookup_names_fn_t ) ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
struct policy_handle * pol ,
int num_names ,
const char * * names ,
const char * * * dom_names ,
int level ,
struct dom_sid * * sids ,
enum lsa_SidType * * types ) ;
2009-09-17 10:06:34 +04:00
NTSTATUS winbindd_lookup_names ( TALLOC_CTX * mem_ctx ,
struct winbindd_domain * domain ,
uint32_t num_names ,
const char * * names ,
const char * * * domains ,
struct dom_sid * * sids ,
enum lsa_SidType * * types )
{
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle lsa_policy ;
2009-12-24 14:56:09 +03:00
unsigned int orig_timeout = 0 ;
2009-09-17 11:43:36 +04:00
lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names ;
2009-09-17 10:06:34 +04:00
2009-09-17 11:43:36 +04:00
if ( domain - > can_do_ncacn_ip_tcp ) {
status = cm_connect_lsa_tcp ( domain , mem_ctx , & cli ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
lookup_names_fn = rpccli_lsa_lookup_names4 ;
goto lookup ;
}
domain - > can_do_ncacn_ip_tcp = false ;
}
2009-09-17 10:06:34 +04:00
status = cm_connect_lsa ( domain , mem_ctx , & cli , & lsa_policy ) ;
2009-09-17 11:43:36 +04:00
2009-09-17 10:06:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-09-17 11:43:36 +04:00
lookup :
2009-09-17 10:06:34 +04:00
/*
* This call can take a long time
* allow the server to time out .
* 35 seconds should do it .
*/
2010-01-06 07:13:35 +03:00
orig_timeout = rpccli_set_timeout ( cli , 35000 ) ;
2009-09-17 10:06:34 +04:00
2009-09-17 11:43:36 +04:00
status = lookup_names_fn ( cli ,
mem_ctx ,
& lsa_policy ,
num_names ,
( const char * * ) names ,
domains ,
1 ,
sids ,
types ) ;
2009-09-17 10:06:34 +04:00
/* And restore our original timeout. */
2010-01-06 07:13:35 +03:00
rpccli_set_timeout ( cli , orig_timeout ) ;
2009-09-17 10:06:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return status ;
}
2006-02-04 01:19:41 +03:00
2001-12-03 04:23:42 +03:00
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
2001-12-10 09:05:21 +03:00
False ,
2001-12-03 14:32:55 +03:00
query_user_list ,
2001-12-03 11:17:46 +03:00
enum_dom_groups ,
2002-10-08 22:32:42 +04:00
enum_local_groups ,
2004-04-20 06:37:49 +04:00
msrpc_name_to_sid ,
msrpc_sid_to_name ,
2006-07-11 22:01:26 +04:00
msrpc_rids_to_names ,
2001-12-04 09:46:53 +03:00
query_user ,
2001-12-05 07:48:51 +03:00
lookup_usergroups ,
2005-01-15 22:00:18 +03:00
msrpc_lookup_useraliases ,
2001-12-05 10:52:44 +03:00
lookup_groupmem ,
2001-12-10 05:25:19 +03:00
sequence_number ,
2006-02-04 01:19:41 +03:00
msrpc_lockout_policy ,
msrpc_password_policy ,
2001-12-10 05:25:19 +03:00
trusted_domains ,
2001-12-03 04:23:42 +03:00
} ;