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"
2010-06-17 15:56:54 +04:00
# include "winbindd_rpc.h"
2011-01-18 16:06:48 +03:00
# include "../librpc/gen_ndr/ndr_samr_c.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2010-05-18 20:25:50 +04:00
# include "rpc_client/cli_samr.h"
2010-05-18 20:26:16 +04:00
# include "rpc_client/cli_lsarpc.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.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 . */
2010-06-17 16:54:55 +04:00
static NTSTATUS msrpc_query_user_list ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32_t * pnum_info ,
struct wbint_userinfo * * pinfo )
2001-12-03 04:23:42 +03:00
{
2010-06-17 16:54:55 +04:00
struct rpc_pipe_client * samr_pipe = NULL ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2010-06-17 16:54:55 +04:00
struct wbint_userinfo * info = NULL ;
uint32_t num_info = 0 ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2001-12-03 04:23:42 +03:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_query_user_list \n " ) ) ;
2002-07-15 14:35:28 +04:00
2010-06-17 16:54:55 +04:00
if ( pnum_info ) {
* pnum_info = 0 ;
}
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
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 ) ) ;
2010-06-17 16:54:55 +04:00
status = NT_STATUS_OK ;
goto done ;
2007-05-07 00:16:12 +04:00
}
2010-06-17 16:54:55 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2001-12-11 03:03:58 +03:00
2010-06-17 16:54:55 +04:00
status = rpc_query_user_list ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
& num_info ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2001-12-11 03:03:58 +03:00
2010-06-17 16:54:55 +04:00
if ( pnum_info ) {
* pnum_info = num_info ;
}
2002-01-31 15:47:42 +03:00
2010-06-17 16:54:55 +04:00
if ( pinfo ) {
* pinfo = talloc_move ( mem_ctx , & info ) ;
}
2001-12-03 04:23:42 +03:00
2010-06-17 16:54:55 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2001-12-03 04:23:42 +03:00
}
/* list all domain groups */
2010-06-17 15:56:54 +04:00
static NTSTATUS msrpc_enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32_t * pnum_info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * pinfo )
2001-12-03 04:23:42 +03:00
{
2010-06-17 15:56:54 +04:00
struct rpc_pipe_client * samr_pipe ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-17 15:56:54 +04:00
uint32_t num_info = 0 ;
TALLOC_CTX * tmp_ctx ;
2001-12-03 04:23:42 +03:00
NTSTATUS status ;
2010-06-17 15:56:54 +04:00
DEBUG ( 3 , ( " msrpc_enum_dom_groups \n " ) ) ;
if ( pnum_info ) {
* pnum_info = 0 ;
}
2001-12-03 04:23:42 +03:00
2010-06-17 15:56:54 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2002-07-15 14:35:28 +04:00
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 ) ) ;
2010-06-17 15:56:54 +04:00
status = NT_STATUS_OK ;
goto done ;
2007-05-07 00:16:12 +04:00
}
2010-06-17 15:56:54 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2001-12-11 04:04:13 +03:00
2010-06-17 15:56:54 +04:00
status = rpc_enum_dom_groups ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& num_info ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-13 13:08:49 +03:00
2010-06-17 15:56:54 +04:00
if ( pnum_info ) {
* pnum_info = num_info ;
}
2008-02-13 13:08:49 +03:00
2010-06-17 15:56:54 +04:00
if ( pinfo ) {
* pinfo = talloc_move ( mem_ctx , & info ) ;
}
2001-12-03 04:23:42 +03:00
2010-06-17 15:56:54 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
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 */
2010-06-17 17:52:44 +04:00
static NTSTATUS msrpc_enum_local_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32_t * pnum_info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * pinfo )
2002-10-08 22:32:42 +04:00
{
2010-06-17 17:52:44 +04:00
struct rpc_pipe_client * samr_pipe ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-17 17:52:44 +04:00
uint32_t num_info = 0 ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2002-10-08 22:32:42 +04:00
2010-06-17 17:52:44 +04:00
DEBUG ( 3 , ( " msrpc_enum_local_groups \n " ) ) ;
2002-10-08 22:32:42 +04:00
2010-06-17 17:52:44 +04:00
if ( pnum_info ) {
* pnum_info = 0 ;
}
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
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 ) ) ;
2010-06-17 17:52:44 +04:00
status = NT_STATUS_OK ;
goto done ;
2007-05-07 00:16:12 +04:00
}
2010-06-17 17:52:44 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-13 13:15:40 +03:00
2010-06-17 17:52:44 +04:00
status = rpc_enum_local_groups ( mem_ctx ,
samr_pipe ,
& dom_pol ,
& num_info ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-13 13:15:40 +03:00
2010-06-17 17:52:44 +04:00
if ( pnum_info ) {
* pnum_info = num_info ;
}
2002-10-08 22:32:42 +04:00
2010-06-17 17:52:44 +04:00
if ( pinfo ) {
* pinfo = talloc_move ( mem_ctx , & info ) ;
}
2002-10-08 22:32:42 +04:00
2010-06-17 17:52:44 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
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 ;
}
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_name_to_sid: name=%s \n " , full_name ) ) ;
2007-07-02 13:46:18 +04:00
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
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_sid_to_name: %s for domain %s \n " , sid_string_dbg ( sid ) ,
2007-12-15 23:11:36 +03:00
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
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_rids_to_names: domain %s \n " , domain - > name ) ) ;
2006-07-11 22:01:26 +04:00
2007-04-30 06:39:34 +04:00
if ( num_rids ) {
2011-06-07 05:30:12 +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. */
2010-06-18 19:47:47 +04:00
static NTSTATUS msrpc_query_user ( struct winbindd_domain * domain ,
2001-12-04 09:17:39 +03:00
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
{
2010-06-18 19:47:47 +04:00
struct rpc_pipe_client * samr_pipe ;
struct policy_handle dom_pol ;
2011-06-08 14:56:10 +04:00
struct netr_SamInfo3 * user = NULL ;
2010-06-18 19:47:47 +04:00
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2001-12-04 09:17:39 +03:00
2010-06-18 19:47:47 +04:00
DEBUG ( 3 , ( " msrpc_query_user sid=%s \n " , sid_string_dbg ( user_sid ) ) ) ;
2005-06-09 02:10:34 +04:00
2010-06-18 19:47:47 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2009-08-03 00:28:49 +04:00
2010-06-18 19:47:47 +04:00
if ( user_info ) {
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 */
2011-06-08 14:56:10 +04:00
if ( winbindd_use_cache ( ) ) {
user = netsamlogon_cache_get ( tmp_ctx , user_sid ) ;
}
2010-06-18 19:47:47 +04:00
if ( user ! = NULL ) {
DEBUG ( 5 , ( " msrpc_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
2010-06-18 19:47:47 +04:00
user_info - > acct_name = talloc_strdup ( user_info ,
2008-02-17 04:08:12 +03:00
user - > base . account_name . string ) ;
2010-06-18 19:47:47 +04:00
user_info - > full_name = talloc_strdup ( user_info ,
2008-02-17 04:08:12 +03:00
user - > base . full_name . string ) ;
2009-08-03 00:28:49 +04:00
2010-06-18 19:47:47 +04:00
status = NT_STATUS_OK ;
goto done ;
2007-05-07 00:16:12 +04:00
}
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 ) ) ;
2010-07-07 16:27:04 +04:00
/* Tell the cache manager not to remember this one */
status = NT_STATUS_SYNCHRONIZATION_REQUIRED ;
2010-06-18 19:47:47 +04:00
goto done ;
2005-11-10 23:28:23 +03:00
}
2009-08-03 00:28:49 +04:00
2005-11-10 23:28:23 +03:00
/* no cache; hit the wire */
2010-06-18 19:47:47 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2009-08-03 00:28:49 +04:00
2010-06-18 19:47:47 +04:00
status = rpc_query_user ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
user_sid ,
user_info ) ;
2001-12-04 09:17:39 +03:00
2010-06-18 19:47:47 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
}
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! */
2010-06-18 20:20:12 +04:00
static NTSTATUS msrpc_lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * user_sid ,
uint32_t * pnum_groups ,
struct dom_sid * * puser_grpsids )
2001-12-04 09:46:53 +03:00
{
2010-06-18 20:20:12 +04:00
struct rpc_pipe_client * samr_pipe ;
struct policy_handle dom_pol ;
struct dom_sid * user_grpsids = NULL ;
uint32_t num_groups = 0 ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2001-12-04 09:46:53 +03:00
2010-06-18 20:20:12 +04:00
DEBUG ( 3 , ( " msrpc_lookup_usergroups sid=%s \n " , sid_string_dbg ( user_sid ) ) ) ;
2002-07-15 14:35:28 +04:00
2010-06-18 20:20:12 +04:00
* pnum_groups = 0 ;
2005-11-10 23:28:23 +03:00
2010-06-18 20:20:12 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2006-04-28 18:48:22 +04:00
2010-06-18 20:20:12 +04:00
/* Check if we have a cached user_info_3 */
status = lookup_usergroups_cached ( domain ,
tmp_ctx ,
user_sid ,
& num_groups ,
& user_grpsids ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto cached ;
2005-11-10 23:28:23 +03:00
}
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 */
2010-06-18 20:20:12 +04:00
status = NT_STATUS_SYNCHRONIZATION_REQUIRED ;
goto done ;
2007-05-07 00:16:12 +04:00
}
2005-11-10 23:28:23 +03:00
/* no cache; hit the wire */
2010-06-18 20:20:12 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2009-08-03 00:28:49 +04:00
2010-06-18 20:20:12 +04:00
status = rpc_lookup_usergroups ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
user_sid ,
& num_groups ,
& user_grpsids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2001-12-04 09:46:53 +03:00
2010-06-18 20:20:12 +04:00
cached :
2011-03-30 08:53:15 +04:00
* pnum_groups = num_groups ;
2003-04-23 15:54:56 +04:00
2010-06-18 20:20:12 +04:00
if ( puser_grpsids ) {
* puser_grpsids = talloc_move ( mem_ctx , & user_grpsids ) ;
2001-12-04 09:46:53 +03:00
}
2008-02-06 18:19:20 +03:00
2010-06-18 20:20:12 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
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 ,
2010-06-18 21:08:41 +04:00
uint32 * pnum_aliases ,
uint32 * * palias_rids )
2005-01-15 22:00:18 +03:00
{
2010-06-18 21:08:41 +04:00
struct rpc_pipe_client * samr_pipe ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2010-06-18 21:08:41 +04:00
uint32_t num_aliases = 0 ;
uint32_t * alias_rids = NULL ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2005-01-15 22:00:18 +03:00
2010-06-18 21:08:41 +04:00
DEBUG ( 3 , ( " msrpc_lookup_useraliases \n " ) ) ;
2005-01-15 22:00:18 +03:00
2010-06-18 21:08:41 +04:00
if ( pnum_aliases ) {
* pnum_aliases = 0 ;
}
2005-01-15 22:00:18 +03:00
2010-06-18 21:08:41 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! winbindd_can_contact_domain ( domain ) ) {
2007-05-07 00:16:12 +04:00
DEBUG ( 10 , ( " msrpc_lookup_useraliases: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
2010-07-07 16:27:04 +04:00
/* Tell the cache manager not to remember this one */
status = NT_STATUS_SYNCHRONIZATION_REQUIRED ;
2010-06-18 21:08:41 +04:00
goto done ;
2007-05-07 00:16:12 +04:00
}
2010-06-18 21:08:41 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2006-06-19 20:00:32 +04:00
2010-06-18 21:08:41 +04:00
status = rpc_lookup_useraliases ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
num_sids ,
sids ,
& num_aliases ,
& alias_rids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2006-06-19 20:00:32 +04:00
2010-06-18 21:08:41 +04:00
if ( pnum_aliases ) {
* pnum_aliases = num_aliases ;
}
2005-01-15 22:00:18 +03:00
2010-06-18 21:08:41 +04:00
if ( palias_rids ) {
* palias_rids = talloc_move ( mem_ctx , & alias_rids ) ;
}
2005-01-15 22:00:18 +03:00
2010-06-18 21:08:41 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2005-01-15 22:00:18 +03:00
}
2001-12-03 04:23:42 +03:00
2001-12-05 07:48:51 +03:00
/* Lookup group membership given a rid. */
2010-06-21 13:15:18 +04:00
static NTSTATUS msrpc_lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * group_sid ,
enum lsa_SidType type ,
uint32_t * num_names ,
struct dom_sid * * sid_mem ,
char * * * names ,
uint32_t * * name_types )
2001-12-05 07:48:51 +03:00
{
2011-01-18 16:06:48 +03:00
NTSTATUS status , result ;
2001-12-05 07:48:51 +03:00
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 ;
2010-10-07 15:01:29 +04:00
struct samr_RidAttrArray * rids = NULL ;
2011-01-18 16:06:48 +03:00
struct dcerpc_binding_handle * b ;
2001-12-05 07:48:51 +03:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_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
2011-01-18 16:06:48 +03:00
b = cli - > binding_handle ;
status = dcerpc_samr_OpenGroup ( b , mem_ctx ,
2008-02-01 13:24:01 +03:00
& dom_pol ,
des_access ,
group_rid ,
2011-01-18 16:06:48 +03:00
& group_pol ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
2005-06-09 02:10:34 +04:00
return result ;
2011-01-18 16:06:48 +03:00
}
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
2011-01-18 16:06:48 +03:00
status = dcerpc_samr_QueryGroupMember ( b , mem_ctx ,
2008-02-05 12:58:37 +03:00
& group_pol ,
2011-01-18 16:06:48 +03:00
& rids ,
& result ) ;
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
2011-01-18 16:06:48 +03:00
{
NTSTATUS _result ;
dcerpc_samr_Close ( b , mem_ctx , & group_pol , & _result ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2001-12-05 07:48:51 +03:00
2011-01-18 16:06:48 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2005-06-09 02:10:34 +04:00
return result ;
2011-01-18 16:06:48 +03:00
}
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
2011-01-18 16:06:48 +03:00
status = dcerpc_samr_LookupRids ( b , mem_ctx ,
2008-02-13 12:49:55 +03:00
& dom_pol ,
num_lookup_rids ,
& rid_mem [ i ] ,
& tmp_names ,
2011-01-18 16:06:48 +03:00
& tmp_types ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
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>
2011-04-26 07:53:45 +04:00
static int get_ldap_seq ( const char * server , struct sockaddr_storage * ss , 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
*/
2011-04-26 07:53:45 +04:00
ldp = ldap_open_with_timeout ( server , ss , port , lp_ldap_timeout ( ) ) ;
2005-06-09 02:10:34 +04:00
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=*) " ,
2011-05-06 03:19:49 +04:00
discard_const_p ( 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 ) ;
2011-04-26 07:53:45 +04:00
if ( ( ret = get_ldap_seq ( addr , & domain - > dcaddr , 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 */
2010-06-21 12:48:15 +04:00
static NTSTATUS msrpc_sequence_number ( struct winbindd_domain * domain ,
uint32_t * pseq )
2001-12-05 10:52:44 +03:00
{
2010-06-21 12:48:15 +04:00
struct rpc_pipe_client * samr_pipe ;
2009-03-19 00:49:41 +03:00
struct policy_handle dom_pol ;
2010-06-21 12:48:15 +04:00
uint32_t seq ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2001-12-05 10:52:44 +03:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_sequence_number: fetch sequence_number for %s \n " , domain - > name ) ) ;
2002-07-15 14:35:28 +04:00
2010-06-21 12:48:15 +04:00
if ( pseq ) {
* pseq = DOM_SEQUENCE_NONE ;
}
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
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 ) ) ;
2010-06-21 12:48:15 +04:00
if ( pseq ) {
* pseq = time ( NULL ) ;
}
status = NT_STATUS_OK ;
goto done ;
2007-05-07 00:16:12 +04:00
}
2005-06-09 02:10:34 +04:00
# ifdef HAVE_LDAP
2010-06-21 12:48:15 +04:00
if ( domain - > active_directory ) {
int rc ;
2005-06-09 02:10:34 +04:00
DEBUG ( 8 , ( " using get_ldap_seq() to retrieve the "
" sequence number \n " ) ) ;
2010-06-21 12:48:15 +04:00
rc = get_ldap_sequence_number ( domain , & seq ) ;
if ( rc = = 0 ) {
2005-06-09 02:10:34 +04:00
DEBUG ( 10 , ( " domain_sequence_number: LDAP for "
" domain %s is %u \n " ,
2010-06-21 12:48:15 +04:00
domain - > name , seq ) ) ;
if ( pseq ) {
* pseq = seq ;
}
status = NT_STATUS_OK ;
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
2010-06-21 12:48:15 +04:00
status = cm_connect_sam ( domain , tmp_ctx , & samr_pipe , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
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
2010-06-21 12:48:15 +04:00
status = rpc_sequence_number ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
domain - > name ,
& seq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
2004-12-22 19:58:43 +03:00
}
2010-06-21 12:48:15 +04:00
if ( pseq ) {
* pseq = seq ;
2001-12-05 10:52:44 +03:00
}
2010-06-21 12:48:15 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2001-12-05 10:52:44 +03:00
}
2001-12-10 05:25:19 +03:00
/* get a list of trusted domains */
2010-06-21 13:14:12 +04:00
static NTSTATUS msrpc_trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct netr_DomainTrustList * ptrust_list )
2001-12-10 05:25:19 +03:00
{
2010-06-21 13:14:12 +04:00
struct rpc_pipe_client * lsa_pipe ;
2009-03-19 00:49:41 +03:00
struct policy_handle lsa_policy ;
2010-06-21 13:14:12 +04:00
struct netr_DomainTrust * trusts = NULL ;
uint32_t num_trusts = 0 ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
2002-07-15 14:35:28 +04:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_trusted_domains \n " ) ) ;
2009-12-28 17:51:36 +03:00
2010-06-21 13:14:12 +04:00
if ( ptrust_list ) {
ZERO_STRUCTP ( ptrust_list ) ;
}
2005-06-09 02:10:34 +04:00
2010-06-21 13:14:12 +04:00
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2009-12-28 17:51:36 +03:00
2010-06-21 13:14:12 +04:00
status = cm_connect_lsa ( domain , tmp_ctx , & lsa_pipe , & lsa_policy ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
return status ;
2009-12-28 17:51:36 +03:00
2010-06-21 13:14:12 +04:00
status = rpc_trusted_domains ( tmp_ctx ,
lsa_pipe ,
& lsa_policy ,
& num_trusts ,
& trusts ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2009-12-28 17:51:36 +03:00
2010-06-21 13:14:12 +04:00
if ( ptrust_list ) {
ptrust_list - > count = num_trusts ;
ptrust_list - > array = talloc_move ( mem_ctx , & trusts ) ;
2005-06-09 02:10:34 +04:00
}
2010-06-21 13:14:12 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2001-12-10 05:25:19 +03:00
}
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
{
2011-01-18 16:06:48 +03:00
NTSTATUS status , result ;
2006-02-04 01:19:41 +03:00
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 ;
2011-01-18 16:06:48 +03:00
struct dcerpc_binding_handle * b ;
2006-02-04 01:19:41 +03:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_lockout_policy: fetch lockout policy for %s \n " , domain - > name ) ) ;
2006-02-04 01:19:41 +03:00
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 ;
}
2011-01-18 16:06:48 +03:00
status = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-04 01:19:41 +03:00
goto done ;
}
2011-01-18 16:06:48 +03:00
b = cli - > binding_handle ;
status = dcerpc_samr_QueryDomainInfo ( b , mem_ctx ,
2008-02-05 19:25:07 +03:00
& dom_pol ,
2011-03-30 13:08:31 +04:00
DomainLockoutInformation ,
2011-01-18 16:06:48 +03:00
& info ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2011-01-18 16:06:48 +03:00
status = result ;
2006-02-04 01:19:41 +03:00
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 :
2011-01-18 16:06:48 +03:00
return status ;
2006-02-04 01:19:41 +03:00
}
/* 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
{
2011-01-18 16:06:48 +03:00
NTSTATUS status , result ;
2006-02-04 01:19:41 +03:00
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 ;
2011-01-18 16:06:48 +03:00
struct dcerpc_binding_handle * b ;
2006-02-04 01:19:41 +03:00
2010-07-06 12:58:46 +04:00
DEBUG ( 3 , ( " msrpc_password_policy: fetch password policy for %s \n " ,
domain - > name ) ) ;
2006-02-04 01:19:41 +03:00
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 ;
}
2011-01-18 16:06:48 +03:00
status = cm_connect_sam ( domain , mem_ctx , & cli , & dom_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-04 01:19:41 +03:00
goto done ;
}
2011-01-18 16:06:48 +03:00
b = cli - > binding_handle ;
status = dcerpc_samr_QueryDomainInfo ( b , mem_ctx ,
2008-02-05 19:25:07 +03:00
& dom_pol ,
2011-03-30 13:08:31 +04:00
DomainPasswordInformation ,
2011-01-18 16:06:48 +03:00
& info ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
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 :
2011-01-18 16:06:48 +03:00
return status ;
2006-02-04 01:19:41 +03:00
}
2011-04-24 01:56:27 +04:00
typedef NTSTATUS ( * lookup_sids_fn_t ) ( struct dcerpc_binding_handle * h ,
2009-09-17 11:43:36 +04:00
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 ,
2011-04-24 01:56:27 +04:00
enum lsa_SidType * * ptypes ,
NTSTATUS * result ) ;
2009-09-17 11:43:36 +04:00
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 ;
2011-04-24 01:56:27 +04:00
NTSTATUS result ;
2009-09-17 09:59:25 +04:00
struct rpc_pipe_client * cli = NULL ;
2011-04-24 01:56:27 +04:00
struct dcerpc_binding_handle * b = NULL ;
2009-09-17 09:59:25 +04:00
struct policy_handle lsa_policy ;
unsigned int orig_timeout ;
2011-04-24 01:56:27 +04:00
lookup_sids_fn_t lookup_sids_fn = dcerpc_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 ) ) {
2011-04-24 01:56:27 +04:00
lookup_sids_fn = dcerpc_lsa_lookup_sids3 ;
2009-09-17 11:43:36 +04:00
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 :
2011-04-24 01:56:27 +04:00
b = cli - > binding_handle ;
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 .
*/
2011-04-24 01:56:27 +04:00
orig_timeout = dcerpc_binding_handle_set_timeout ( b , 35000 ) ;
2009-09-17 09:59:25 +04:00
2011-04-24 01:56:27 +04:00
status = lookup_sids_fn ( b ,
2009-09-17 11:43:36 +04:00
mem_ctx ,
& lsa_policy ,
num_sids ,
sids ,
domains ,
names ,
2011-04-24 01:56:27 +04:00
types ,
& result ) ;
2009-09-17 09:59:25 +04:00
/* And restore our original timeout. */
2011-04-24 01:56:27 +04:00
dcerpc_binding_handle_set_timeout ( b , orig_timeout ) ;
2009-09-17 09:59:25 +04:00
2011-04-24 02:00:40 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_RPC_SEC_PKG_ERROR ) ) {
2011-02-01 20:46:57 +03:00
/*
* This can happen if the schannel key is not
* valid anymore , we need to invalidate the
* all connections to the dc and reestablish
* a netlogon connection first .
*/
invalidate_cm_connection ( & domain - > conn ) ;
status = NT_STATUS_ACCESS_DENIED ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-04-24 01:56:27 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
return NT_STATUS_OK ;
2009-09-17 09:59:25 +04:00
}
2011-04-24 01:57:19 +04:00
typedef NTSTATUS ( * lookup_names_fn_t ) ( struct dcerpc_binding_handle * h ,
2009-09-17 11:43:36 +04:00
TALLOC_CTX * mem_ctx ,
struct policy_handle * pol ,
2011-04-24 01:57:19 +04:00
uint32_t num_names ,
2009-09-17 11:43:36 +04:00
const char * * names ,
const char * * * dom_names ,
2011-04-24 01:57:19 +04:00
enum lsa_LookupNamesLevel level ,
2009-09-17 11:43:36 +04:00
struct dom_sid * * sids ,
2011-04-24 01:57:19 +04:00
enum lsa_SidType * * types ,
NTSTATUS * result ) ;
2009-09-17 11:43:36 +04:00
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 ;
2011-04-24 01:57:19 +04:00
NTSTATUS result ;
2009-09-17 10:06:34 +04:00
struct rpc_pipe_client * cli = NULL ;
2011-04-24 01:57:19 +04:00
struct dcerpc_binding_handle * b = NULL ;
2009-09-17 10:06:34 +04:00
struct policy_handle lsa_policy ;
2009-12-24 14:56:09 +03:00
unsigned int orig_timeout = 0 ;
2011-04-24 01:57:19 +04:00
lookup_names_fn_t lookup_names_fn = dcerpc_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 ) ) {
2011-04-24 01:57:19 +04:00
lookup_names_fn = dcerpc_lsa_lookup_names4 ;
2009-09-17 11:43:36 +04:00
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 :
2011-04-24 01:57:19 +04:00
b = cli - > binding_handle ;
2009-09-17 11:43:36 +04:00
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 .
*/
2011-04-24 01:57:19 +04:00
orig_timeout = dcerpc_binding_handle_set_timeout ( b , 35000 ) ;
2009-09-17 10:06:34 +04:00
2011-04-24 01:57:19 +04:00
status = lookup_names_fn ( b ,
2009-09-17 11:43:36 +04:00
mem_ctx ,
& lsa_policy ,
num_names ,
( const char * * ) names ,
domains ,
1 ,
sids ,
2011-04-24 01:57:19 +04:00
types ,
& result ) ;
2009-09-17 10:06:34 +04:00
/* And restore our original timeout. */
2011-04-24 01:57:19 +04:00
dcerpc_binding_handle_set_timeout ( b , orig_timeout ) ;
2009-09-17 10:06:34 +04:00
2011-04-24 02:00:40 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_RPC_SEC_PKG_ERROR ) ) {
2011-02-01 20:46:57 +03:00
/*
* This can happen if the schannel key is not
* valid anymore , we need to invalidate the
* all connections to the dc and reestablish
* a netlogon connection first .
*/
invalidate_cm_connection ( & domain - > conn ) ;
status = NT_STATUS_ACCESS_DENIED ;
}
2009-09-17 10:06:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-04-24 01:57:19 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
return NT_STATUS_OK ;
2009-09-17 10:06:34 +04:00
}
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 ,
2010-06-17 16:54:55 +04:00
msrpc_query_user_list ,
2010-06-17 15:56:54 +04:00
msrpc_enum_dom_groups ,
2010-06-17 17:52:44 +04:00
msrpc_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 ,
2010-06-18 19:47:47 +04:00
msrpc_query_user ,
2010-06-18 20:20:12 +04:00
msrpc_lookup_usergroups ,
2005-01-15 22:00:18 +03:00
msrpc_lookup_useraliases ,
2010-06-21 13:15:18 +04:00
msrpc_lookup_groupmem ,
2010-06-21 12:48:15 +04:00
msrpc_sequence_number ,
2006-02-04 01:19:41 +03:00
msrpc_lockout_policy ,
msrpc_password_policy ,
2010-06-21 13:14:12 +04:00
msrpc_trusted_domains ,
2001-12-03 04:23:42 +03:00
} ;