2005-09-26 01:01:56 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Volker Lendecke 2005
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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-09-26 01:01:56 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-09-26 01:01:56 +04:00
*/
/*
a composite API for finding a DC and its name
*/
# include "includes.h"
2010-03-08 22:33:48 +03:00
# include <tevent.h>
2005-09-26 01:01:56 +04:00
# include "libcli/composite/composite.h"
# include "winbind/wb_async_helpers.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_lsa_c.h"
# include "librpc/gen_ndr/ndr_samr_c.h"
2006-03-07 14:07:23 +03:00
2011-03-19 02:44:11 +03:00
# include "winbind/wb_helper.h"
2005-09-26 01:01:56 +04:00
2005-10-19 17:45:44 +04:00
struct lsa_lookupsids_state {
struct composite_context * ctx ;
2010-03-09 19:54:12 +03:00
uint32_t num_sids ;
2005-10-19 17:45:44 +04:00
struct lsa_LookupSids r ;
struct lsa_SidArray sids ;
struct lsa_TransNameArray names ;
2008-10-24 04:01:16 +04:00
struct lsa_RefDomainList * domains ;
2005-10-19 17:45:44 +04:00
uint32_t count ;
struct wb_sid_object * * result ;
} ;
2010-03-08 22:33:48 +03:00
static void lsa_lookupsids_recv_names ( struct tevent_req * subreq ) ;
2005-10-19 17:45:44 +04:00
2005-11-05 12:34:07 +03:00
struct composite_context * wb_lsa_lookupsids_send ( TALLOC_CTX * mem_ctx ,
2014-01-14 15:11:17 +04:00
struct tevent_context * ev ,
struct dcerpc_binding_handle * lsa_binding ,
2005-10-19 17:45:44 +04:00
struct policy_handle * handle ,
2010-03-09 19:54:12 +03:00
uint32_t num_sids ,
2005-10-19 17:45:44 +04:00
const struct dom_sid * * sids )
{
struct composite_context * result ;
struct lsa_lookupsids_state * state ;
2010-03-09 19:54:12 +03:00
uint32_t i ;
2010-03-08 22:33:48 +03:00
struct tevent_req * subreq ;
2005-10-19 17:45:44 +04:00
2014-01-14 15:11:17 +04:00
result = composite_create ( mem_ctx , ev ) ;
2005-10-19 17:45:44 +04:00
if ( result = = NULL ) goto failed ;
state = talloc ( result , struct lsa_lookupsids_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
state - > ctx = result ;
state - > sids . num_sids = num_sids ;
state - > sids . sids = talloc_array ( state , struct lsa_SidPtr , num_sids ) ;
if ( state - > sids . sids = = NULL ) goto failed ;
for ( i = 0 ; i < num_sids ; i + + ) {
state - > sids . sids [ i ] . sid = dom_sid_dup ( state - > sids . sids ,
sids [ i ] ) ;
if ( state - > sids . sids [ i ] . sid = = NULL ) goto failed ;
}
2008-10-24 04:01:16 +04:00
state - > domains = talloc ( state , struct lsa_RefDomainList ) ;
if ( state - > domains = = NULL ) goto failed ;
2005-10-19 17:45:44 +04:00
state - > count = 0 ;
state - > num_sids = num_sids ;
state - > names . count = 0 ;
state - > names . names = NULL ;
state - > r . in . handle = handle ;
state - > r . in . sids = & state - > sids ;
state - > r . in . names = & state - > names ;
state - > r . in . level = 1 ;
state - > r . in . count = & state - > count ;
state - > r . out . names = & state - > names ;
state - > r . out . count = & state - > count ;
2008-10-24 04:01:16 +04:00
state - > r . out . domains = & state - > domains ;
2005-10-19 17:45:44 +04:00
2014-01-14 15:11:17 +04:00
subreq = dcerpc_lsa_LookupSids_r_send ( state , ev ,
lsa_binding ,
2010-03-08 22:33:48 +03:00
& state - > r ) ;
if ( subreq = = NULL ) goto failed ;
tevent_req_set_callback ( subreq , lsa_lookupsids_recv_names , state ) ;
2005-10-19 17:45:44 +04:00
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
2010-03-08 22:33:48 +03:00
static void lsa_lookupsids_recv_names ( struct tevent_req * subreq )
2005-10-19 17:45:44 +04:00
{
struct lsa_lookupsids_state * state =
2010-03-08 22:33:48 +03:00
tevent_req_callback_data ( subreq ,
struct lsa_lookupsids_state ) ;
2010-03-09 19:54:12 +03:00
uint32_t i ;
2005-10-19 17:45:44 +04:00
2010-03-08 22:33:48 +03:00
state - > ctx - > status = dcerpc_lsa_LookupSids_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2005-10-19 17:45:44 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > r . out . result ;
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) & &
! NT_STATUS_EQUAL ( state - > ctx - > status , STATUS_SOME_UNMAPPED ) ) {
composite_error ( state - > ctx , state - > ctx - > status ) ;
return ;
}
2013-11-08 08:38:01 +04:00
if ( state - > names . count ! = state - > num_sids ) {
composite_error ( state - > ctx ,
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2005-10-19 17:45:44 +04:00
state - > result = talloc_array ( state , struct wb_sid_object * ,
state - > num_sids ) ;
if ( composite_nomem ( state - > result , state - > ctx ) ) return ;
for ( i = 0 ; i < state - > num_sids ; i + + ) {
struct lsa_TranslatedName * name =
& state - > r . out . names - > names [ i ] ;
2006-08-31 12:22:13 +04:00
struct lsa_DomainInfo * dom ;
2008-10-24 04:01:16 +04:00
struct lsa_RefDomainList * domains =
state - > domains ;
2005-10-19 17:45:44 +04:00
state - > result [ i ] = talloc_zero ( state - > result ,
struct wb_sid_object ) ;
if ( composite_nomem ( state - > result [ i ] , state - > ctx ) ) return ;
state - > result [ i ] - > type = name - > sid_type ;
if ( state - > result [ i ] - > type = = SID_NAME_UNKNOWN ) {
continue ;
}
2013-11-08 08:38:01 +04:00
if ( domains = = NULL ) {
composite_error ( state - > ctx ,
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2008-10-24 04:01:16 +04:00
if ( name - > sid_index > = domains - > count ) {
2005-10-19 17:45:44 +04:00
composite_error ( state - > ctx ,
2013-11-08 08:38:01 +04:00
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2005-10-19 17:45:44 +04:00
return ;
}
2008-10-24 04:01:16 +04:00
dom = & domains - > domains [ name - > sid_index ] ;
2005-10-19 17:45:44 +04:00
state - > result [ i ] - > domain = talloc_reference ( state - > result [ i ] ,
dom - > name . string ) ;
if ( ( name - > sid_type = = SID_NAME_DOMAIN ) | |
( name - > name . string = = NULL ) ) {
state - > result [ i ] - > name =
talloc_strdup ( state - > result [ i ] , " " ) ;
} else {
state - > result [ i ] - > name =
talloc_steal ( state - > result [ i ] ,
name - > name . string ) ;
}
if ( composite_nomem ( state - > result [ i ] - > name , state - > ctx ) ) {
return ;
}
}
composite_done ( state - > ctx ) ;
}
NTSTATUS wb_lsa_lookupsids_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * names )
{
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
struct lsa_lookupsids_state * state =
talloc_get_type ( c - > private_data ,
struct lsa_lookupsids_state ) ;
* names = talloc_steal ( mem_ctx , state - > result ) ;
}
talloc_free ( c ) ;
return status ;
}
2005-10-07 23:08:51 +04:00
struct lsa_lookupnames_state {
struct composite_context * ctx ;
uint32_t num_names ;
struct lsa_LookupNames r ;
struct lsa_TransSidArray sids ;
2008-10-24 15:43:21 +04:00
struct lsa_RefDomainList * domains ;
2005-10-07 23:08:51 +04:00
uint32_t count ;
struct wb_sid_object * * result ;
} ;
2010-03-08 22:33:48 +03:00
static void lsa_lookupnames_recv_sids ( struct tevent_req * subreq ) ;
2005-10-07 23:08:51 +04:00
2005-11-05 12:34:07 +03:00
struct composite_context * wb_lsa_lookupnames_send ( TALLOC_CTX * mem_ctx ,
2014-01-14 15:11:17 +04:00
struct tevent_context * ev ,
struct dcerpc_binding_handle * lsa_binding ,
2005-10-07 23:08:51 +04:00
struct policy_handle * handle ,
2010-03-09 19:54:12 +03:00
uint32_t num_names ,
2005-10-07 23:08:51 +04:00
const char * * names )
{
struct composite_context * result ;
struct lsa_lookupnames_state * state ;
2010-03-08 22:33:48 +03:00
struct tevent_req * subreq ;
2005-10-07 23:08:51 +04:00
struct lsa_String * lsa_names ;
2010-03-09 19:54:12 +03:00
uint32_t i ;
2005-10-07 23:08:51 +04:00
2014-01-14 15:11:17 +04:00
result = composite_create ( mem_ctx , ev ) ;
2005-10-07 23:08:51 +04:00
if ( result = = NULL ) goto failed ;
state = talloc ( result , struct lsa_lookupnames_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
2005-10-08 20:25:00 +04:00
state - > ctx = result ;
2005-10-07 23:08:51 +04:00
state - > sids . count = 0 ;
state - > sids . sids = NULL ;
state - > num_names = num_names ;
state - > count = 0 ;
lsa_names = talloc_array ( state , struct lsa_String , num_names ) ;
if ( lsa_names = = NULL ) goto failed ;
for ( i = 0 ; i < num_names ; i + + ) {
lsa_names [ i ] . string = names [ i ] ;
}
2008-10-24 15:43:21 +04:00
state - > domains = talloc ( state , struct lsa_RefDomainList ) ;
if ( state - > domains = = NULL ) goto failed ;
2005-10-07 23:08:51 +04:00
state - > r . in . handle = handle ;
state - > r . in . num_names = num_names ;
state - > r . in . names = lsa_names ;
state - > r . in . sids = & state - > sids ;
state - > r . in . level = 1 ;
state - > r . in . count = & state - > count ;
state - > r . out . count = & state - > count ;
state - > r . out . sids = & state - > sids ;
2008-10-24 15:43:21 +04:00
state - > r . out . domains = & state - > domains ;
2005-10-07 23:08:51 +04:00
2014-01-14 15:11:17 +04:00
subreq = dcerpc_lsa_LookupNames_r_send ( state , ev ,
lsa_binding ,
2010-03-08 22:33:48 +03:00
& state - > r ) ;
if ( subreq = = NULL ) goto failed ;
tevent_req_set_callback ( subreq , lsa_lookupnames_recv_sids , state ) ;
2005-10-07 23:08:51 +04:00
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
2010-03-08 22:33:48 +03:00
static void lsa_lookupnames_recv_sids ( struct tevent_req * subreq )
2005-10-07 23:08:51 +04:00
{
struct lsa_lookupnames_state * state =
2010-03-08 22:33:48 +03:00
tevent_req_callback_data ( subreq ,
struct lsa_lookupnames_state ) ;
2010-03-09 19:54:12 +03:00
uint32_t i ;
2005-10-07 23:08:51 +04:00
2010-03-08 22:33:48 +03:00
state - > ctx - > status = dcerpc_lsa_LookupNames_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
state - > ctx - > status = state - > r . out . result ;
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) & &
! NT_STATUS_EQUAL ( state - > ctx - > status , STATUS_SOME_UNMAPPED ) ) {
2005-10-10 23:57:55 +04:00
composite_error ( state - > ctx , state - > ctx - > status ) ;
2005-10-08 20:25:00 +04:00
return ;
2005-10-07 23:08:51 +04:00
}
2013-11-08 09:40:55 +04:00
if ( state - > sids . count ! = state - > num_names ) {
composite_error ( state - > ctx ,
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2005-10-07 23:08:51 +04:00
state - > result = talloc_array ( state , struct wb_sid_object * ,
state - > num_names ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > result , state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
for ( i = 0 ; i < state - > num_names ; i + + ) {
struct lsa_TranslatedSid * sid = & state - > r . out . sids - > sids [ i ] ;
2008-10-24 15:43:21 +04:00
struct lsa_RefDomainList * domains = state - > domains ;
2006-08-31 12:22:13 +04:00
struct lsa_DomainInfo * dom ;
2005-10-07 23:08:51 +04:00
state - > result [ i ] = talloc_zero ( state - > result ,
struct wb_sid_object ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > result [ i ] , state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
state - > result [ i ] - > type = sid - > sid_type ;
if ( state - > result [ i ] - > type = = SID_NAME_UNKNOWN ) {
continue ;
}
2013-11-08 09:40:55 +04:00
if ( domains = = NULL ) {
composite_error ( state - > ctx ,
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2008-10-24 15:43:21 +04:00
if ( sid - > sid_index > = domains - > count ) {
2005-10-10 23:57:55 +04:00
composite_error ( state - > ctx ,
2013-11-08 09:40:55 +04:00
NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2005-10-08 20:25:00 +04:00
return ;
2005-10-07 23:08:51 +04:00
}
2008-10-24 15:43:21 +04:00
dom = & domains - > domains [ sid - > sid_index ] ;
2005-10-07 23:08:51 +04:00
state - > result [ i ] - > sid = dom_sid_add_rid ( state - > result [ i ] ,
dom - > sid , sid - > rid ) ;
}
2005-10-10 23:57:55 +04:00
composite_done ( state - > ctx ) ;
2005-10-07 23:08:51 +04:00
}
NTSTATUS wb_lsa_lookupnames_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * sids )
{
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
struct lsa_lookupnames_state * state =
talloc_get_type ( c - > private_data ,
struct lsa_lookupnames_state ) ;
* sids = talloc_steal ( mem_ctx , state - > result ) ;
}
talloc_free ( c ) ;
return status ;
}
2005-10-16 16:43:09 +04:00
struct samr_getuserdomgroups_state {
struct composite_context * ctx ;
2014-01-14 15:11:17 +04:00
struct dcerpc_binding_handle * samr_binding ;
2005-10-16 16:43:09 +04:00
2010-03-09 19:54:12 +03:00
uint32_t num_rids ;
2005-10-16 16:43:09 +04:00
uint32_t * rids ;
2008-11-05 12:58:35 +03:00
struct samr_RidWithAttributeArray * rid_array ;
2005-10-16 16:43:09 +04:00
struct policy_handle * user_handle ;
struct samr_OpenUser o ;
struct samr_GetGroupsForUser g ;
struct samr_Close c ;
} ;
2010-03-08 22:33:48 +03:00
static void samr_usergroups_recv_open ( struct tevent_req * subreq ) ;
static void samr_usergroups_recv_groups ( struct tevent_req * subreq ) ;
static void samr_usergroups_recv_close ( struct tevent_req * subreq ) ;
2005-10-16 16:43:09 +04:00
2005-11-05 12:34:07 +03:00
struct composite_context * wb_samr_userdomgroups_send ( TALLOC_CTX * mem_ctx ,
2014-01-14 15:11:17 +04:00
struct tevent_context * ev ,
struct dcerpc_binding_handle * samr_binding ,
2005-10-16 16:43:09 +04:00
struct policy_handle * domain_handle ,
uint32_t rid )
{
struct composite_context * result ;
struct samr_getuserdomgroups_state * state ;
2010-03-08 22:33:48 +03:00
struct tevent_req * subreq ;
2005-10-16 16:43:09 +04:00
2014-01-14 15:11:17 +04:00
result = composite_create ( mem_ctx , ev ) ;
2005-10-16 16:43:09 +04:00
if ( result = = NULL ) goto failed ;
state = talloc ( result , struct samr_getuserdomgroups_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
state - > ctx = result ;
2014-01-14 15:11:17 +04:00
state - > samr_binding = samr_binding ;
2005-10-16 16:43:09 +04:00
state - > user_handle = talloc ( state , struct policy_handle ) ;
if ( state - > user_handle = = NULL ) goto failed ;
state - > o . in . domain_handle = domain_handle ;
state - > o . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
state - > o . in . rid = rid ;
state - > o . out . user_handle = state - > user_handle ;
2010-03-08 22:33:48 +03:00
subreq = dcerpc_samr_OpenUser_r_send ( state ,
2014-01-14 15:11:17 +04:00
state - > ctx - > event_ctx ,
state - > samr_binding ,
2010-03-08 22:33:48 +03:00
& state - > o ) ;
if ( subreq = = NULL ) goto failed ;
tevent_req_set_callback ( subreq , samr_usergroups_recv_open , state ) ;
2005-10-16 16:43:09 +04:00
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
2010-03-08 22:33:48 +03:00
static void samr_usergroups_recv_open ( struct tevent_req * subreq )
2005-10-16 16:43:09 +04:00
{
struct samr_getuserdomgroups_state * state =
2010-03-08 22:33:48 +03:00
tevent_req_callback_data ( subreq ,
struct samr_getuserdomgroups_state ) ;
2005-10-16 16:43:09 +04:00
2010-03-08 22:33:48 +03:00
state - > ctx - > status = dcerpc_samr_OpenUser_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2005-10-16 16:43:09 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > o . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > g . in . user_handle = state - > user_handle ;
2008-11-05 12:58:35 +03:00
state - > g . out . rids = & state - > rid_array ;
2005-10-16 16:43:09 +04:00
2010-03-08 22:33:48 +03:00
subreq = dcerpc_samr_GetGroupsForUser_r_send ( state ,
state - > ctx - > event_ctx ,
2014-01-14 15:11:17 +04:00
state - > samr_binding ,
2010-03-08 22:33:48 +03:00
& state - > g ) ;
if ( composite_nomem ( subreq , state - > ctx ) ) return ;
tevent_req_set_callback ( subreq , samr_usergroups_recv_groups , state ) ;
2005-10-16 16:43:09 +04:00
}
2010-03-08 22:33:48 +03:00
static void samr_usergroups_recv_groups ( struct tevent_req * subreq )
2005-10-16 16:43:09 +04:00
{
struct samr_getuserdomgroups_state * state =
2010-03-08 22:33:48 +03:00
tevent_req_callback_data ( subreq ,
struct samr_getuserdomgroups_state ) ;
2005-10-16 16:43:09 +04:00
2010-03-08 22:33:48 +03:00
state - > ctx - > status = dcerpc_samr_GetGroupsForUser_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2005-10-16 16:43:09 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > g . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > c . in . handle = state - > user_handle ;
state - > c . out . handle = state - > user_handle ;
2010-03-08 22:33:48 +03:00
subreq = dcerpc_samr_Close_r_send ( state ,
state - > ctx - > event_ctx ,
2014-01-14 15:11:17 +04:00
state - > samr_binding ,
2010-03-08 22:33:48 +03:00
& state - > c ) ;
if ( composite_nomem ( subreq , state - > ctx ) ) return ;
tevent_req_set_callback ( subreq , samr_usergroups_recv_close , state ) ;
2005-10-16 16:43:09 +04:00
}
2010-03-08 22:33:48 +03:00
static void samr_usergroups_recv_close ( struct tevent_req * subreq )
2005-10-16 16:43:09 +04:00
{
struct samr_getuserdomgroups_state * state =
2010-03-08 22:33:48 +03:00
tevent_req_callback_data ( subreq ,
struct samr_getuserdomgroups_state ) ;
2005-10-16 16:43:09 +04:00
2010-03-08 22:33:48 +03:00
state - > ctx - > status = dcerpc_samr_Close_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2005-10-16 16:43:09 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > c . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
composite_done ( state - > ctx ) ;
}
NTSTATUS wb_samr_userdomgroups_recv ( struct composite_context * ctx ,
TALLOC_CTX * mem_ctx ,
2010-03-09 19:54:12 +03:00
uint32_t * num_rids , uint32_t * * rids )
2005-10-16 16:43:09 +04:00
{
struct samr_getuserdomgroups_state * state =
talloc_get_type ( ctx - > private_data ,
struct samr_getuserdomgroups_state ) ;
2010-03-09 19:54:12 +03:00
uint32_t i ;
2005-10-16 16:43:09 +04:00
NTSTATUS status = composite_wait ( ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
2008-11-05 12:58:35 +03:00
* num_rids = state - > rid_array - > count ;
2005-10-16 16:43:09 +04:00
* rids = talloc_array ( mem_ctx , uint32_t , * num_rids ) ;
if ( * rids = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < * num_rids ; i + + ) {
2008-11-05 12:58:35 +03:00
( * rids ) [ i ] = state - > rid_array - > rids [ i ] . rid ;
2005-10-16 16:43:09 +04:00
}
done :
talloc_free ( ctx ) ;
return status ;
}