2009-07-28 23:06:11 +04:00
/*
Unix SMB / CIFS implementation .
In - Child server implementation of the routines defined in wbint . idl
Copyright ( C ) Volker Lendecke 2009
2009-10-06 20:26:33 +04:00
Copyright ( C ) Guenther Deschner 2009
2009-07-28 23:06:11 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "winbindd/winbindd.h"
# include "winbindd/winbindd_proto.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2011-05-02 15:21:53 +04:00
# include "ntdomain.h"
2009-07-28 23:06:11 +04:00
# include "librpc/gen_ndr/srv_wbint.h"
2011-01-12 13:55:34 +03:00
# include "../librpc/gen_ndr/ndr_netlogon_c.h"
2010-08-18 20:13:42 +04:00
# include "idmap.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2009-07-28 23:06:11 +04:00
2010-07-28 12:28:36 +04:00
void _wbint_Ping ( struct pipes_struct * p , struct wbint_Ping * r )
2009-07-28 23:06:11 +04:00
{
* r - > out . out_data = r - > in . in_data ;
}
2009-08-04 01:44:46 +04:00
2011-06-04 01:28:33 +04:00
static bool reset_cm_connection_on_error ( struct winbindd_domain * domain ,
NTSTATUS status )
{
if ( NT_STATUS_EQUAL ( status , NT_STATUS_IO_TIMEOUT ) ) {
invalidate_cm_connection ( & domain - > conn ) ;
/* We invalidated the connection. */
return true ;
}
return false ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupSid ( struct pipes_struct * p , struct wbint_LookupSid * r )
2009-08-04 01:44:46 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
char * dom_name ;
char * name ;
enum lsa_SidType type ;
NTSTATUS status ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
status = domain - > methods - > sid_to_name ( domain , p - > mem_ctx , r - > in . sid ,
& dom_name , & name , & type ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-04 01:44:46 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* r - > out . domain = dom_name ;
* r - > out . name = name ;
* r - > out . type = type ;
return NT_STATUS_OK ;
}
2009-08-04 15:22:34 +04:00
2011-03-11 14:48:11 +03:00
NTSTATUS _wbint_LookupSids ( struct pipes_struct * p , struct wbint_LookupSids * r )
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2014-02-20 16:14:31 +04:00
struct lsa_RefDomainList * domains = r - > out . domains ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2011-03-11 14:48:11 +03:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
/*
* This breaks the winbindd_domain - > methods abstraction : This
* is only called for remote domains , and both winbindd_msrpc
* and winbindd_ad call into lsa_lookupsids anyway . Caching is
* done at the wbint RPC layer .
*/
2011-06-04 01:28:33 +04:00
status = rpc_lookup_sids ( p - > mem_ctx , domain , r - > in . sids ,
2014-02-20 16:14:31 +04:00
& domains , & r - > out . names ) ;
if ( domains ! = NULL ) {
r - > out . domains = domains ;
}
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2011-03-11 14:48:11 +03:00
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupName ( struct pipes_struct * p , struct wbint_LookupName * r )
2009-08-04 15:22:34 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-04 15:22:34 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > name_to_sid (
2009-08-04 15:22:34 +04:00
domain , p - > mem_ctx , r - > in . domain , r - > in . name , r - > in . flags ,
r - > out . sid , r - > out . type ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-04 15:22:34 +04:00
}
2009-08-04 21:28:59 +04:00
2011-03-23 20:18:13 +03:00
NTSTATUS _wbint_Sids2UnixIDs ( struct pipes_struct * p ,
struct wbint_Sids2UnixIDs * r )
{
uint32_t i , j ;
struct id_map * ids = NULL ;
struct id_map * * id_ptrs = NULL ;
struct dom_sid * sids = NULL ;
uint32_t * id_idx = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < r - > in . domains - > count ; i + + ) {
struct lsa_DomainInfo * d = & r - > in . domains - > domains [ i ] ;
struct idmap_domain * dom ;
uint32_t num_ids ;
2012-11-25 05:13:15 +04:00
dom = idmap_find_domain_with_sid ( d - > name . string , d - > sid ) ;
2011-03-23 20:18:13 +03:00
if ( dom = = NULL ) {
2012-11-25 05:13:15 +04:00
DEBUG ( 10 , ( " idmap domain %s:%s not found \n " ,
d - > name . string , sid_string_dbg ( d - > sid ) ) ) ;
2011-03-23 20:18:13 +03:00
continue ;
}
num_ids = 0 ;
for ( j = 0 ; j < r - > in . ids - > num_ids ; j + + ) {
if ( r - > in . ids - > ids [ j ] . domain_index = = i ) {
num_ids + = 1 ;
}
}
2011-06-07 05:10:15 +04:00
ids = talloc_realloc ( talloc_tos ( ) , ids ,
2011-03-23 20:18:13 +03:00
struct id_map , num_ids ) ;
if ( ids = = NULL ) {
goto nomem ;
}
2011-06-07 05:10:15 +04:00
id_ptrs = talloc_realloc ( talloc_tos ( ) , id_ptrs ,
2011-03-23 20:18:13 +03:00
struct id_map * , num_ids + 1 ) ;
if ( id_ptrs = = NULL ) {
goto nomem ;
}
2011-06-07 05:10:15 +04:00
id_idx = talloc_realloc ( talloc_tos ( ) , id_idx ,
2011-03-23 20:18:13 +03:00
uint32_t , num_ids ) ;
if ( id_idx = = NULL ) {
goto nomem ;
}
2011-06-07 05:10:15 +04:00
sids = talloc_realloc ( talloc_tos ( ) , sids ,
2011-03-23 20:18:13 +03:00
struct dom_sid , num_ids ) ;
if ( sids = = NULL ) {
goto nomem ;
}
num_ids = 0 ;
2012-11-18 22:29:37 +04:00
/*
* Convert the input data into a list of
* id_map structs suitable for handing in
* to the idmap sids_to_unixids method .
*/
2011-03-23 20:18:13 +03:00
for ( j = 0 ; j < r - > in . ids - > num_ids ; j + + ) {
struct wbint_TransID * id = & r - > in . ids - > ids [ j ] ;
if ( id - > domain_index ! = i ) {
continue ;
}
id_idx [ num_ids ] = j ;
id_ptrs [ num_ids ] = & ids [ num_ids ] ;
ids [ num_ids ] . sid = & sids [ num_ids ] ;
sid_compose ( ids [ num_ids ] . sid , d - > sid , id - > rid ) ;
ids [ num_ids ] . xid . type = id - > type ;
ids [ num_ids ] . status = ID_UNKNOWN ;
num_ids + = 1 ;
}
id_ptrs [ num_ids ] = NULL ;
status = dom - > methods - > sids_to_unixids ( dom , id_ptrs ) ;
DEBUG ( 10 , ( " sids_to_unixids returned %s \n " ,
nt_errstr ( status ) ) ) ;
2012-11-18 22:58:07 +04:00
/*
* Extract the results for handing them back to the caller .
*/
2011-03-23 20:18:13 +03:00
for ( j = 0 ; j < num_ids ; j + + ) {
struct wbint_TransID * id = & r - > in . ids - > ids [ id_idx [ j ] ] ;
if ( ids [ j ] . status ! = ID_MAPPED ) {
2012-11-18 16:51:13 +04:00
id - > xid . id = UINT32_MAX ;
id - > xid . type = ID_TYPE_NOT_SPECIFIED ;
2011-03-23 20:18:13 +03:00
continue ;
}
2012-11-18 16:51:13 +04:00
id - > xid = ids [ j ] . xid ;
2011-03-23 20:18:13 +03:00
}
}
status = NT_STATUS_OK ;
nomem :
TALLOC_FREE ( ids ) ;
TALLOC_FREE ( id_ptrs ) ;
TALLOC_FREE ( id_idx ) ;
TALLOC_FREE ( sids ) ;
return status ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_Uid2Sid ( struct pipes_struct * p , struct wbint_Uid2Sid * r )
2009-08-04 21:52:39 +04:00
{
2009-08-09 15:17:35 +04:00
return idmap_uid_to_sid ( r - > in . dom_name ? r - > in . dom_name : " " ,
r - > out . sid , r - > in . uid ) ;
2009-08-04 21:52:39 +04:00
}
2009-08-04 22:19:03 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_Gid2Sid ( struct pipes_struct * p , struct wbint_Gid2Sid * r )
2009-08-04 22:19:03 +04:00
{
2009-08-09 15:17:35 +04:00
return idmap_gid_to_sid ( r - > in . dom_name ? r - > in . dom_name : " " ,
r - > out . sid , r - > in . gid ) ;
2009-08-04 22:19:03 +04:00
}
2009-08-04 23:23:13 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_AllocateUid ( struct pipes_struct * p , struct wbint_AllocateUid * r )
2009-08-30 11:41:43 +04:00
{
struct unixid xid ;
NTSTATUS status ;
status = idmap_allocate_uid ( & xid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* r - > out . uid = xid . id ;
return NT_STATUS_OK ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_AllocateGid ( struct pipes_struct * p , struct wbint_AllocateGid * r )
2009-08-30 11:46:34 +04:00
{
struct unixid xid ;
NTSTATUS status ;
status = idmap_allocate_gid ( & xid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* r - > out . gid = xid . id ;
return NT_STATUS_OK ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_QueryUser ( struct pipes_struct * p , struct wbint_QueryUser * r )
2009-08-04 23:23:13 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-04 23:23:13 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > query_user ( domain , p - > mem_ctx , r - > in . sid ,
r - > out . info ) ;
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-04 23:23:13 +04:00
}
2009-08-04 23:54:05 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupUserAliases ( struct pipes_struct * p ,
2009-08-04 23:54:05 +04:00
struct wbint_LookupUserAliases * r )
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-04 23:54:05 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > lookup_useraliases (
2009-08-04 23:54:05 +04:00
domain , p - > mem_ctx , r - > in . sids - > num_sids , r - > in . sids - > sids ,
& r - > out . rids - > num_rids , & r - > out . rids - > rids ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-04 23:54:05 +04:00
}
2009-08-05 00:07:01 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupUserGroups ( struct pipes_struct * p ,
2009-08-05 00:07:01 +04:00
struct wbint_LookupUserGroups * r )
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-05 00:07:01 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > lookup_usergroups (
2009-08-05 00:07:01 +04:00
domain , p - > mem_ctx , r - > in . sid ,
& r - > out . sids - > num_sids , & r - > out . sids - > sids ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-05 00:07:01 +04:00
}
2009-08-15 13:16:28 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_QuerySequenceNumber ( struct pipes_struct * p ,
2009-08-15 13:16:28 +04:00
struct wbint_QuerySequenceNumber * r )
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-15 13:16:28 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > sequence_number ( domain , r - > out . sequence ) ;
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-15 13:16:28 +04:00
}
2009-08-16 12:58:43 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupGroupMembers ( struct pipes_struct * p ,
2009-08-16 12:58:43 +04:00
struct wbint_LookupGroupMembers * r )
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
uint32_t i , num_names ;
struct dom_sid * sid_mem ;
char * * names ;
uint32_t * name_types ;
NTSTATUS status ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
status = domain - > methods - > lookup_groupmem (
2009-08-28 16:25:11 +04:00
domain , p - > mem_ctx , r - > in . sid , r - > in . type ,
2009-08-16 12:58:43 +04:00
& num_names , & sid_mem , & names , & name_types ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-16 12:58:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-08-23 14:43:43 +04:00
r - > out . members - > num_principals = num_names ;
r - > out . members - > principals = talloc_array (
2009-08-23 14:38:35 +04:00
r - > out . members , struct wbint_Principal , num_names ) ;
2009-08-23 14:43:43 +04:00
if ( r - > out . members - > principals = = NULL ) {
2009-08-16 12:58:43 +04:00
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_names ; i + + ) {
2009-08-23 14:43:43 +04:00
struct wbint_Principal * m = & r - > out . members - > principals [ i ] ;
2009-08-16 12:58:43 +04:00
sid_copy ( & m - > sid , & sid_mem [ i ] ) ;
2009-08-23 14:43:43 +04:00
m - > name = talloc_move ( r - > out . members - > principals , & names [ i ] ) ;
2009-08-16 12:58:43 +04:00
m - > type = ( enum lsa_SidType ) name_types [ i ] ;
}
return NT_STATUS_OK ;
}
2009-08-18 00:40:19 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_QueryUserList ( struct pipes_struct * p ,
struct wbint_QueryUserList * r )
2009-08-18 00:40:19 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
2011-06-04 01:28:33 +04:00
NTSTATUS status ;
2009-08-18 00:40:19 +04:00
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2011-06-04 01:28:33 +04:00
status = domain - > methods - > query_user_list (
2009-08-18 00:40:19 +04:00
domain , p - > mem_ctx , & r - > out . users - > num_userinfos ,
& r - > out . users - > userinfos ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
return status ;
2009-08-18 00:40:19 +04:00
}
2009-08-26 00:13:34 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_QueryGroupList ( struct pipes_struct * p ,
struct wbint_QueryGroupList * r )
2009-08-27 21:54:18 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
uint32_t i , num_groups ;
2011-03-22 19:43:39 +03:00
struct wb_acct_info * groups ;
2009-08-27 21:54:18 +04:00
struct wbint_Principal * result ;
NTSTATUS status ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
status = domain - > methods - > enum_dom_groups ( domain , talloc_tos ( ) ,
& num_groups , & groups ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-27 21:54:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
result = talloc_array ( r - > out . groups , struct wbint_Principal ,
num_groups ) ;
if ( result = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_groups ; i + + ) {
sid_compose ( & result [ i ] . sid , & domain - > sid , groups [ i ] . rid ) ;
result [ i ] . type = SID_NAME_DOM_GRP ;
result [ i ] . name = talloc_strdup ( result , groups [ i ] . acct_name ) ;
if ( result [ i ] . name = = NULL ) {
TALLOC_FREE ( result ) ;
TALLOC_FREE ( groups ) ;
return NT_STATUS_NO_MEMORY ;
}
}
r - > out . groups - > num_principals = num_groups ;
r - > out . groups - > principals = result ;
2010-06-14 13:49:32 +04:00
TALLOC_FREE ( groups ) ;
2009-08-27 21:54:18 +04:00
return NT_STATUS_OK ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_DsGetDcName ( struct pipes_struct * p , struct wbint_DsGetDcName * r )
2009-08-26 00:13:34 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
struct rpc_pipe_client * netlogon_pipe ;
struct netr_DsRGetDCNameInfo * dc_info ;
NTSTATUS status ;
WERROR werr ;
unsigned int orig_timeout ;
2011-01-12 13:55:34 +03:00
struct dcerpc_binding_handle * b ;
2009-08-26 00:13:34 +04:00
if ( domain = = NULL ) {
return dsgetdcname ( p - > mem_ctx , winbind_messaging_context ( ) ,
r - > in . domain_name , r - > in . domain_guid ,
r - > in . site_name ? r - > in . site_name : " " ,
r - > in . flags ,
r - > out . dc_info ) ;
}
status = cm_connect_netlogon ( domain , & netlogon_pipe ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-26 00:13:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " Can't contact the NETLOGON pipe \n " ) ) ;
return status ;
}
2011-01-12 13:55:34 +03:00
b = netlogon_pipe - > binding_handle ;
2009-08-26 00:13:34 +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 ( netlogon_pipe , 35000 ) ;
if ( domain - > active_directory ) {
2011-01-12 13:55:34 +03:00
status = dcerpc_netr_DsRGetDCName ( b ,
p - > mem_ctx , domain - > dcname ,
2009-08-26 00:13:34 +04:00
r - > in . domain_name , NULL , r - > in . domain_guid ,
r - > in . flags , r - > out . dc_info , & werr ) ;
if ( NT_STATUS_IS_OK ( status ) & & W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2011-06-04 01:28:33 +04:00
if ( reset_cm_connection_on_error ( domain , status ) ) {
/* Re-initialize. */
status = cm_connect_netlogon ( domain , & netlogon_pipe ) ;
reset_cm_connection_on_error ( domain , status ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " Can't contact the NETLOGON pipe \n " ) ) ;
return status ;
}
b = netlogon_pipe - > binding_handle ;
/* This call can take a long time - allow the server to time out.
35 seconds should do it . */
orig_timeout = rpccli_set_timeout ( netlogon_pipe , 35000 ) ;
}
2009-08-26 00:13:34 +04:00
}
/*
* Fallback to less capable methods
*/
dc_info = talloc_zero ( r - > out . dc_info , struct netr_DsRGetDCNameInfo ) ;
if ( dc_info = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
if ( r - > in . flags & DS_PDC_REQUIRED ) {
2011-01-12 13:55:34 +03:00
status = dcerpc_netr_GetDcName ( b ,
p - > mem_ctx , domain - > dcname ,
2009-08-26 00:13:34 +04:00
r - > in . domain_name , & dc_info - > dc_unc , & werr ) ;
} else {
2011-01-12 13:55:34 +03:00
status = dcerpc_netr_GetAnyDCName ( b ,
p - > mem_ctx , domain - > dcname ,
2009-08-26 00:13:34 +04:00
r - > in . domain_name , & dc_info - > dc_unc , & werr ) ;
}
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-26 00:13:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-12 13:55:34 +03:00
DEBUG ( 10 , ( " dcerpc_netr_Get[Any]DCName failed: %s \n " ,
2009-08-26 00:13:34 +04:00
nt_errstr ( status ) ) ) ;
goto done ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
2011-01-12 13:55:34 +03:00
DEBUG ( 10 , ( " dcerpc_netr_Get[Any]DCName failed: %s \n " ,
2009-08-26 00:13:34 +04:00
win_errstr ( werr ) ) ) ;
status = werror_to_ntstatus ( werr ) ;
goto done ;
}
* r - > out . dc_info = dc_info ;
status = NT_STATUS_OK ;
done :
/* And restore our original timeout. */
rpccli_set_timeout ( netlogon_pipe , orig_timeout ) ;
return status ;
}
2009-08-27 19:11:24 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_LookupRids ( struct pipes_struct * p , struct wbint_LookupRids * r )
2009-08-27 19:11:24 +04:00
{
struct winbindd_domain * domain = wb_child_domain ( ) ;
char * domain_name ;
char * * names ;
enum lsa_SidType * types ;
struct wbint_Principal * result ;
NTSTATUS status ;
int i ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
status = domain - > methods - > rids_to_names (
2011-06-27 16:34:39 +04:00
domain , talloc_tos ( ) , r - > in . domain_sid , r - > in . rids - > rids ,
2009-08-27 19:11:24 +04:00
r - > in . rids - > num_rids , & domain_name , & names , & types ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-08-27 19:11:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-12-04 22:16:00 +03:00
* r - > out . domain_name = talloc_move ( r - > out . domain_name , & domain_name ) ;
2009-08-27 19:11:24 +04:00
result = talloc_array ( p - > mem_ctx , struct wbint_Principal ,
r - > in . rids - > num_rids ) ;
if ( result = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < r - > in . rids - > num_rids ; i + + ) {
2011-06-27 16:34:39 +04:00
sid_compose ( & result [ i ] . sid , r - > in . domain_sid ,
r - > in . rids - > rids [ i ] ) ;
2009-08-27 19:11:24 +04:00
result [ i ] . type = types [ i ] ;
result [ i ] . name = talloc_move ( result , & names [ i ] ) ;
}
TALLOC_FREE ( types ) ;
TALLOC_FREE ( names ) ;
r - > out . names - > num_principals = r - > in . rids - > num_rids ;
r - > out . names - > principals = result ;
return NT_STATUS_OK ;
}
2009-09-06 11:32:34 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_CheckMachineAccount ( struct pipes_struct * p ,
2009-09-06 11:32:34 +04:00
struct wbint_CheckMachineAccount * r )
{
struct winbindd_domain * domain ;
int num_retries = 0 ;
NTSTATUS status ;
domain = wb_child_domain ( ) ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2009-11-23 15:58:23 +03:00
again :
2009-09-06 11:32:34 +04:00
invalidate_cm_connection ( & domain - > conn ) ;
2013-08-07 13:32:44 +04:00
domain - > conn . netlogon_force_reauth = true ;
2009-09-06 11:32:34 +04:00
{
struct rpc_pipe_client * netlogon_pipe ;
status = cm_connect_netlogon ( domain , & netlogon_pipe ) ;
}
/* There is a race condition between fetching the trust account
password and the periodic machine password change . So it ' s
possible that the trust account password has been changed on us .
We are returned NT_STATUS_ACCESS_DENIED if this happens . */
# define MAX_RETRIES 3
if ( ( num_retries < MAX_RETRIES )
& & NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
num_retries + + ;
goto again ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " could not open handle to NETLOGON pipe \n " ) ) ;
goto done ;
}
/* Pass back result code - zero for success, other values for
specific failures . */
2009-10-06 19:46:25 +04:00
DEBUG ( 3 , ( " domain %s secret is %s \n " , domain - > name ,
NT_STATUS_IS_OK ( status ) ? " good " : " bad " ) ) ;
2009-09-06 11:32:34 +04:00
done :
DEBUG ( NT_STATUS_IS_OK ( status ) ? 5 : 2 ,
2009-10-06 19:46:25 +04:00
( " Checking the trust account password for domain %s returned %s \n " ,
domain - > name , nt_errstr ( status ) ) ) ;
2009-09-06 11:32:34 +04:00
return status ;
}
2009-09-06 16:47:06 +04:00
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_ChangeMachineAccount ( struct pipes_struct * p ,
2009-10-06 20:26:33 +04:00
struct wbint_ChangeMachineAccount * r )
{
2013-09-16 20:37:34 +04:00
struct messaging_context * msg_ctx = winbind_messaging_context ( ) ;
2009-10-06 20:26:33 +04:00
struct winbindd_domain * domain ;
NTSTATUS status ;
struct rpc_pipe_client * netlogon_pipe ;
domain = wb_child_domain ( ) ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2013-09-16 20:37:34 +04:00
status = cm_connect_netlogon ( domain , & netlogon_pipe ) ;
2009-10-06 20:26:33 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " could not open handle to NETLOGON pipe \n " ) ) ;
goto done ;
}
2013-09-16 20:37:34 +04:00
status = trust_pw_change ( domain - > conn . netlogon_creds ,
msg_ctx ,
netlogon_pipe - > binding_handle ,
domain - > name ,
true ) ; /* force */
2009-10-06 20:26:33 +04:00
/* Pass back result code - zero for success, other values for
specific failures . */
DEBUG ( 3 , ( " domain %s secret %s \n " , domain - > name ,
NT_STATUS_IS_OK ( status ) ? " changed " : " unchanged " ) ) ;
done :
DEBUG ( NT_STATUS_IS_OK ( status ) ? 5 : 2 ,
( " Changing the trust account password for domain %s returned %s \n " ,
domain - > name , nt_errstr ( status ) ) ) ;
return status ;
}
2010-07-28 12:28:36 +04:00
NTSTATUS _wbint_PingDc ( struct pipes_struct * p , struct wbint_PingDc * r )
2009-12-21 23:50:43 +03:00
{
NTSTATUS status ;
struct winbindd_domain * domain ;
struct rpc_pipe_client * netlogon_pipe ;
union netr_CONTROL_QUERY_INFORMATION info ;
WERROR werr ;
fstring logon_server ;
2011-01-12 13:55:34 +03:00
struct dcerpc_binding_handle * b ;
2009-12-21 23:50:43 +03:00
domain = wb_child_domain ( ) ;
if ( domain = = NULL ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
status = cm_connect_netlogon ( domain , & netlogon_pipe ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2009-12-21 23:50:43 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-05-24 23:40:49 +04:00
DEBUG ( 3 , ( " could not open handle to NETLOGON pipe: %s \n " ,
nt_errstr ( status ) ) ) ;
2009-12-21 23:50:43 +03:00
return status ;
}
2011-01-12 13:55:34 +03:00
b = netlogon_pipe - > binding_handle ;
2009-12-21 23:50:43 +03:00
fstr_sprintf ( logon_server , " \\ \\ %s " , domain - > dcname ) ;
2012-08-10 19:10:42 +04:00
* r - > out . dcname = talloc_strdup ( p - > mem_ctx , domain - > dcname ) ;
2013-02-25 17:55:48 +04:00
if ( * r - > out . dcname = = NULL ) {
2012-08-10 19:10:42 +04:00
DEBUG ( 2 , ( " Could not allocate memory \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2009-12-21 23:50:43 +03:00
/*
* This provokes a WERR_NOT_SUPPORTED error message . This is
* documented in the wspp docs . I could not get a successful
* call to work , but the main point here is testing that the
* netlogon pipe works .
*/
2011-01-12 13:55:34 +03:00
status = dcerpc_netr_LogonControl ( b , p - > mem_ctx ,
2009-12-21 23:50:43 +03:00
logon_server , NETLOGON_CONTROL_QUERY ,
2 , & info , & werr ) ;
2011-06-04 01:28:33 +04:00
reset_cm_connection_on_error ( domain , status ) ;
2011-01-12 13:55:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " dcerpc_netr_LogonControl failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2009-12-21 23:50:43 +03:00
return status ;
}
2011-01-12 13:55:34 +03:00
if ( ! W_ERROR_EQUAL ( werr , WERR_NOT_SUPPORTED ) ) {
DEBUG ( 2 , ( " dcerpc_netr_LogonControl returned %s, expected "
" WERR_NOT_SUPPORTED \n " ,
win_errstr ( werr ) ) ) ;
return werror_to_ntstatus ( werr ) ;
}
2009-12-21 23:50:43 +03:00
DEBUG ( 5 , ( " winbindd_dual_ping_dc succeeded \n " ) ) ;
return NT_STATUS_OK ;
}