2010-06-07 12:18:01 +04:00
/*
* Unix SMB / CIFS implementation .
*
* Winbind rpc backend functions
*
* Copyright ( c ) 2000 - 2003 Tim Potter
* Copyright ( c ) 2001 Andrew Tridgell
* Copyright ( c ) 2005 Volker Lendecke
* Copyright ( c ) 2008 Guenther Deschner ( pidl conversion )
* Copyright ( c ) 2010 Andreas Schneider < asn @ samba . org >
*
* 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.h"
2010-06-17 15:57:12 +04:00
# include "winbindd_rpc.h"
2016-12-27 15:52:00 +03:00
# include "lib/util_unixsids.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2018-03-21 10:44:31 +03:00
# include "rpc_client/cli_pipe.h"
2011-01-18 14:43:02 +03:00
# include "../librpc/gen_ndr/ndr_samr_c.h"
2010-06-07 12:18:01 +04:00
# include "rpc_client/cli_samr.h"
2011-01-18 20:02:27 +03:00
# include "../librpc/gen_ndr/ndr_lsa_c.h"
2010-06-07 12:18:01 +04:00
# include "rpc_client/cli_lsarpc.h"
2010-07-06 23:29:32 +04:00
# include "rpc_server/rpc_ncacn_np.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-03-22 18:50:02 +03:00
# include "passdb/machine_sid.h"
2011-03-25 04:28:05 +03:00
# include "auth.h"
2021-06-19 18:06:59 +03:00
# include "source3/lib/global_contexts.h"
2010-06-07 12:18:01 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2018-03-21 10:43:10 +03:00
/*
* The other end of this won ' t go away easily , so we can trust it
*
* It is either a long - lived process with the same lifetime as
* winbindd or a part of this process
*/
struct winbind_internal_pipes {
2021-06-19 18:06:59 +03:00
struct tevent_timer * shutdown_timer ;
2018-03-21 10:43:10 +03:00
struct rpc_pipe_client * samr_pipe ;
struct policy_handle samr_domain_hnd ;
struct rpc_pipe_client * lsa_pipe ;
struct policy_handle lsa_hnd ;
} ;
2010-07-06 19:02:33 +04:00
NTSTATUS open_internal_samr_conn ( TALLOC_CTX * mem_ctx ,
struct winbindd_domain * domain ,
struct rpc_pipe_client * * samr_pipe ,
struct policy_handle * samr_domain_hnd )
2010-06-07 12:18:01 +04:00
{
2011-01-18 14:43:02 +03:00
NTSTATUS status , result ;
2010-06-07 12:18:01 +04:00
struct policy_handle samr_connect_hnd ;
2011-01-18 14:43:02 +03:00
struct dcerpc_binding_handle * b ;
2010-06-07 12:18:01 +04:00
2014-05-16 10:10:23 +04:00
status = wb_open_internal_pipe ( mem_ctx , & ndr_table_samr , samr_pipe ) ;
2010-06-07 12:18:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-03-01 17:56:06 +03:00
DBG_ERR ( " Could not connect to %s pipe: %s \n " ,
ndr_table_samr . name , nt_errstr ( status ) ) ;
2010-06-07 12:18:01 +04:00
return status ;
}
2011-01-18 14:43:02 +03:00
b = ( * samr_pipe ) - > binding_handle ;
status = dcerpc_samr_Connect2 ( b , mem_ctx ,
2010-06-07 12:18:01 +04:00
( * samr_pipe ) - > desthost ,
SEC_FLAG_MAXIMUM_ALLOWED ,
2011-01-18 14:43:02 +03:00
& samr_connect_hnd ,
& result ) ;
2010-06-07 12:18:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-01-18 14:43:02 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2010-06-07 12:18:01 +04:00
2011-01-18 14:43:02 +03:00
status = dcerpc_samr_OpenDomain ( b , mem_ctx ,
2010-06-07 12:18:01 +04:00
& samr_connect_hnd ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& domain - > sid ,
2011-01-18 14:43:02 +03:00
samr_domain_hnd ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-06-07 12:18:01 +04:00
2011-01-18 14:43:02 +03:00
return result ;
2010-06-07 12:18:01 +04:00
}
2015-02-03 18:22:25 +03:00
NTSTATUS open_internal_lsa_conn ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * * lsa_pipe ,
struct policy_handle * lsa_hnd )
2010-06-07 12:18:01 +04:00
{
NTSTATUS status ;
2014-05-16 10:10:23 +04:00
status = wb_open_internal_pipe ( mem_ctx , & ndr_table_lsarpc , lsa_pipe ) ;
2010-06-07 12:18:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-03-01 17:56:06 +03:00
DBG_ERR ( " Could not connect to %s pipe: %s \n " ,
ndr_table_lsarpc . name , nt_errstr ( status ) ) ;
2010-06-07 12:18:01 +04:00
return status ;
}
status = rpccli_lsa_open_policy ( ( * lsa_pipe ) ,
mem_ctx ,
true ,
SEC_FLAG_MAXIMUM_ALLOWED ,
lsa_hnd ) ;
return status ;
}
2021-06-19 18:06:59 +03:00
static void cached_internal_pipe_close (
struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval current_time ,
void * private_data )
{
struct winbindd_domain * domain = talloc_get_type_abort (
private_data , struct winbindd_domain ) ;
/*
2022-04-13 12:01:00 +03:00
* Freeing samr_pipes closes the cached pipes .
2021-06-19 18:06:59 +03:00
*
* We can do a hard close because at the time of this commit
2023-07-18 12:45:25 +03:00
* we only use synchronous calls to external pipes . So we can ' t
2021-06-19 18:06:59 +03:00
* have any outstanding requests . Also , we don ' t set
* dcerpc_binding_handle_set_sync_ev in winbind , so we don ' t
* get nested event loops . Once we start to get async in
* winbind children , we need to check for outstanding calls
*/
2022-04-13 12:01:00 +03:00
TALLOC_FREE ( domain - > backend_data . samr_pipes ) ;
2021-06-19 18:06:59 +03:00
}
2018-03-21 10:43:10 +03:00
static NTSTATUS open_cached_internal_pipe_conn (
struct winbindd_domain * domain ,
struct rpc_pipe_client * * samr_pipe ,
struct policy_handle * samr_domain_hnd ,
struct rpc_pipe_client * * lsa_pipe ,
struct policy_handle * lsa_hnd )
{
2022-04-13 12:15:35 +03:00
struct winbind_internal_pipes * internal_pipes =
domain - > backend_data . samr_pipes ;
2018-03-21 10:43:10 +03:00
2022-04-13 12:15:35 +03:00
if ( internal_pipes = = NULL ) {
2018-03-21 10:43:10 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status ;
internal_pipes = talloc_zero ( frame ,
struct winbind_internal_pipes ) ;
status = open_internal_samr_conn (
internal_pipes ,
domain ,
& internal_pipes - > samr_pipe ,
& internal_pipes - > samr_domain_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
status = open_internal_lsa_conn ( internal_pipes ,
& internal_pipes - > lsa_pipe ,
& internal_pipes - > lsa_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2021-06-19 18:06:59 +03:00
internal_pipes - > shutdown_timer = tevent_add_timer (
global_event_context ( ) ,
internal_pipes ,
timeval_current_ofs ( 5 , 0 ) ,
cached_internal_pipe_close ,
domain ) ;
if ( internal_pipes - > shutdown_timer = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
2022-04-13 12:01:00 +03:00
domain - > backend_data . samr_pipes =
2022-04-13 12:15:35 +03:00
talloc_steal ( domain , internal_pipes ) ;
2018-03-21 10:43:10 +03:00
TALLOC_FREE ( frame ) ;
}
if ( samr_domain_hnd ) {
* samr_domain_hnd = internal_pipes - > samr_domain_hnd ;
}
if ( samr_pipe ) {
* samr_pipe = internal_pipes - > samr_pipe ;
}
if ( lsa_hnd ) {
* lsa_hnd = internal_pipes - > lsa_hnd ;
}
if ( lsa_pipe ) {
* lsa_pipe = internal_pipes - > lsa_pipe ;
}
2021-06-19 18:06:59 +03:00
tevent_update_timer (
internal_pipes - > shutdown_timer ,
timeval_current_ofs ( 5 , 0 ) ) ;
2018-03-21 10:43:10 +03:00
return NT_STATUS_OK ;
}
2018-03-21 10:44:31 +03:00
static bool reset_connection_on_error ( struct winbindd_domain * domain ,
struct rpc_pipe_client * p ,
NTSTATUS status )
{
2020-08-07 13:07:28 +03:00
struct dcerpc_binding_handle * b = p - > binding_handle ;
2018-03-21 10:44:31 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_IO_TIMEOUT ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_IO_DEVICE_ERROR ) )
{
2022-04-13 12:01:00 +03:00
TALLOC_FREE ( domain - > backend_data . samr_pipes ) ;
2018-03-21 10:44:31 +03:00
return true ;
}
2020-08-07 13:07:28 +03:00
if ( ! dcerpc_binding_handle_is_connected ( b ) ) {
2022-04-13 12:01:00 +03:00
TALLOC_FREE ( domain - > backend_data . samr_pipes ) ;
2018-03-21 10:44:31 +03:00
return true ;
}
return false ;
}
2010-06-07 12:18:01 +04:00
/*********************************************************************
SAM specific functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* List all domain groups */
static NTSTATUS sam_enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-06-07 18:39:44 +04:00
uint32_t * pnum_info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * pinfo )
2010-06-07 12:18:01 +04:00
{
2010-06-07 18:39:44 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-07 18:39:44 +04:00
uint32_t num_info = 0 ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-07 18:39:44 +04:00
2010-06-17 15:57:12 +04:00
DEBUG ( 3 , ( " sam_enum_dom_groups \n " ) ) ;
2010-06-07 18:39:44 +04:00
if ( pnum_info ) {
* pnum_info = 0 ;
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-07 18:39:44 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2018-03-21 10:43:10 +03:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 18:39:44 +04:00
}
2010-06-17 15:57:12 +04:00
status = rpc_enum_dom_groups ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& num_info ,
& info ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-17 15:57:12 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2018-03-21 10:43:10 +03:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-17 15:57:12 +04:00
}
2010-06-07 18:39:44 +04:00
if ( pnum_info ) {
* pnum_info = num_info ;
}
if ( pinfo ) {
* pinfo = talloc_move ( mem_ctx , & info ) ;
}
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* Query display info for a domain */
static NTSTATUS sam_query_user_list ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2017-01-03 15:11:30 +03:00
uint32_t * * prids )
2010-06-07 12:18:01 +04:00
{
2010-06-07 18:18:12 +04:00
struct rpc_pipe_client * samr_pipe = NULL ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2017-01-11 22:52:44 +03:00
uint32_t * rids = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-07 18:18:12 +04:00
2010-06-17 16:55:19 +04:00
DEBUG ( 3 , ( " samr_query_user_list \n " ) ) ;
2010-06-07 18:18:12 +04:00
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-07 18:18:12 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-17 16:55:19 +04:00
goto done ;
2010-06-07 18:18:12 +04:00
}
2010-06-17 16:55:19 +04:00
status = rpc_query_user_list ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
2017-01-03 15:11:30 +03:00
& rids ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-17 16:55:19 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-06-07 18:18:12 +04:00
2017-01-11 22:52:44 +03:00
if ( prids ! = NULL ) {
2017-01-03 15:11:30 +03:00
* prids = talloc_move ( mem_ctx , & rids ) ;
2010-06-07 18:18:12 +04:00
}
2010-06-17 16:55:19 +04:00
done :
2017-01-10 16:24:22 +03:00
TALLOC_FREE ( rids ) ;
2010-06-07 18:18:12 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* get a list of trusted domains - builtin domain */
static NTSTATUS sam_trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-06-21 13:13:50 +04:00
struct netr_DomainTrustList * ptrust_list )
2010-06-07 12:18:01 +04:00
{
2010-06-07 23:46:02 +04:00
struct rpc_pipe_client * lsa_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle lsa_policy = { 0 } ;
2010-06-21 13:13:50 +04:00
struct netr_DomainTrust * trusts = NULL ;
uint32_t num_trusts = 0 ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-07 23:46:02 +04:00
DEBUG ( 3 , ( " samr: trusted domains \n " ) ) ;
2010-06-21 13:13:50 +04:00
if ( ptrust_list ) {
ZERO_STRUCTP ( ptrust_list ) ;
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
NULL ,
NULL ,
& lsa_pipe ,
& lsa_policy ) ;
2010-06-07 23:46:02 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-21 13:13:50 +04:00
goto done ;
2010-06-07 23:46:02 +04:00
}
2010-06-21 13:13:50 +04:00
status = rpc_trusted_domains ( tmp_ctx ,
lsa_pipe ,
& lsa_policy ,
& num_trusts ,
& trusts ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , lsa_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-21 13:13:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-06-07 23:46:02 +04:00
2010-06-21 13:13:50 +04:00
if ( ptrust_list ) {
ptrust_list - > count = num_trusts ;
ptrust_list - > array = talloc_move ( mem_ctx , & trusts ) ;
2010-06-07 23:46:02 +04:00
}
2010-06-21 13:13:50 +04:00
done :
2010-06-07 23:46:02 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* Lookup group membership given a rid. */
static NTSTATUS sam_lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * group_sid ,
enum lsa_SidType type ,
2010-06-08 00:15:37 +04:00
uint32_t * pnum_names ,
struct dom_sid * * psid_mem ,
char * * * pnames ,
uint32_t * * pname_types )
2010-06-07 12:18:01 +04:00
{
2010-06-08 00:15:37 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2010-06-08 00:15:37 +04:00
uint32_t num_names = 0 ;
struct dom_sid * sid_mem = NULL ;
char * * names = NULL ;
uint32_t * name_types = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-08 00:15:37 +04:00
2010-06-21 12:28:47 +04:00
DEBUG ( 3 , ( " sam_lookup_groupmem \n " ) ) ;
2010-06-08 00:15:37 +04:00
2010-06-21 12:28:47 +04:00
/* Paranoia check */
if ( sid_check_is_in_builtin ( group_sid ) & & ( type ! = SID_NAME_ALIAS ) ) {
/* There's no groups, only aliases in BUILTIN */
2021-02-24 00:09:24 +03:00
status = NT_STATUS_NO_SUCH_GROUP ;
goto done ;
2010-06-08 00:15:37 +04:00
}
2010-06-21 12:28:47 +04:00
if ( pnum_names ) {
2011-03-16 23:29:02 +03:00
* pnum_names = 0 ;
2010-06-08 00:15:37 +04:00
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-08 00:15:37 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-21 12:28:47 +04:00
goto done ;
2010-06-08 00:15:37 +04:00
}
2010-06-21 12:28:47 +04:00
status = rpc_lookup_groupmem ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
domain - > name ,
& domain - > sid ,
group_sid ,
type ,
& num_names ,
& sid_mem ,
& names ,
& name_types ) ;
2010-06-08 00:15:37 +04:00
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-08 00:15:37 +04:00
if ( pnum_names ) {
2010-06-21 12:28:47 +04:00
* pnum_names = num_names ;
2010-06-08 00:15:37 +04:00
}
if ( pnames ) {
* pnames = talloc_move ( mem_ctx , & names ) ;
}
if ( pname_types ) {
* pname_types = talloc_move ( mem_ctx , & name_types ) ;
}
if ( psid_mem ) {
* psid_mem = talloc_move ( mem_ctx , & sid_mem ) ;
}
2010-06-21 12:28:47 +04:00
done :
2010-06-08 00:15:37 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
2023-03-08 10:40:58 +03:00
/* Lookup alias membership */
static NTSTATUS sam_lookup_aliasmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * group_sid ,
enum lsa_SidType type ,
uint32_t * pnum_sids ,
struct dom_sid * * psid_mem )
{
struct rpc_pipe_client * samr_pipe ;
struct policy_handle dom_pol = { 0 } ;
uint32_t num_sids = 0 ;
struct dom_sid * sid_mem = NULL ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
NTSTATUS status ;
bool retry = false ;
DBG_INFO ( " sam_lookup_aliasmem \n " ) ;
/* Paranoia check */
if ( type ! = SID_NAME_ALIAS ) {
status = NT_STATUS_NO_SUCH_ALIAS ;
goto done ;
}
if ( pnum_sids ) {
* pnum_sids = 0 ;
}
again :
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
status = rpc_lookup_aliasmem ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
group_sid ,
type ,
& num_sids ,
& sid_mem ) ;
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
if ( pnum_sids ) {
* pnum_sids = num_sids ;
}
if ( psid_mem ) {
* psid_mem = talloc_move ( mem_ctx , & sid_mem ) ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
}
2010-06-07 12:18:01 +04:00
/*********************************************************************
BUILTIN specific functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* List all domain groups */
static NTSTATUS builtin_enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2015-04-24 05:04:23 +03:00
uint32_t * num_entries ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * info )
2010-06-07 12:18:01 +04:00
{
/* BUILTIN doesn't have domain groups */
* num_entries = 0 ;
* info = NULL ;
return NT_STATUS_OK ;
}
/* Query display info for a domain */
static NTSTATUS builtin_query_user_list ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2017-01-03 15:11:30 +03:00
uint32_t * * rids )
2010-06-07 12:18:01 +04:00
{
/* We don't have users */
2017-01-03 15:11:30 +03:00
* rids = NULL ;
2010-06-07 12:18:01 +04:00
return NT_STATUS_OK ;
}
/* get a list of trusted domains - builtin domain */
static NTSTATUS builtin_trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct netr_DomainTrustList * trusts )
{
ZERO_STRUCTP ( trusts ) ;
return NT_STATUS_OK ;
}
/*********************************************************************
COMMON functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* List all local groups (aliases) */
2010-06-17 17:53:06 +04:00
static NTSTATUS sam_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 )
2010-06-07 12:18:01 +04:00
{
2010-06-08 10:47:13 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-08 10:47:13 +04:00
uint32_t num_info = 0 ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-08 10:47:13 +04:00
DEBUG ( 3 , ( " samr: enum local groups \n " ) ) ;
if ( pnum_info ) {
* pnum_info = 0 ;
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-08 10:47:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-17 17:53:06 +04:00
goto done ;
2010-06-08 10:47:13 +04:00
}
2010-06-17 17:53:06 +04:00
status = rpc_enum_local_groups ( mem_ctx ,
samr_pipe ,
& dom_pol ,
& num_info ,
2018-03-21 10:44:31 +03:00
2010-06-17 17:53:06 +04:00
& info ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-17 17:53:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-06-08 10:47:13 +04:00
if ( pnum_info ) {
* pnum_info = num_info ;
}
if ( pinfo ) {
* pinfo = talloc_move ( mem_ctx , & info ) ;
}
2010-06-17 17:53:06 +04:00
done :
2010-06-08 10:47:13 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* convert a single name to a sid in a domain */
2010-06-17 18:07:02 +04:00
static NTSTATUS sam_name_to_sid ( struct winbindd_domain * domain ,
2010-06-07 12:18:01 +04:00
TALLOC_CTX * mem_ctx ,
const char * domain_name ,
const char * name ,
uint32_t flags ,
2019-03-12 02:11:01 +03:00
const char * * pdom_name ,
2010-06-17 18:07:02 +04:00
struct dom_sid * psid ,
enum lsa_SidType * ptype )
2010-06-07 12:18:01 +04:00
{
2021-02-23 12:38:16 +03:00
struct rpc_pipe_client * samr_pipe = NULL ;
struct dcerpc_binding_handle * h = NULL ;
struct policy_handle dom_pol = { . handle_type = 0 , } ;
2010-06-17 18:07:02 +04:00
struct dom_sid sid ;
2021-02-23 10:27:07 +03:00
const char * dom_name = domain_name ;
2021-02-23 12:38:16 +03:00
struct lsa_String lsa_name = { . string = name } ;
struct samr_Ids rids = { . count = 0 } ;
struct samr_Ids types = { . count = 0 } ;
2010-06-17 18:07:02 +04:00
enum lsa_SidType type ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2021-02-23 10:27:07 +03:00
NTSTATUS status = NT_STATUS_NONE_MAPPED ;
2021-02-23 12:38:16 +03:00
NTSTATUS result ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2021-02-23 10:27:07 +03:00
bool ok ;
2010-06-08 16:42:59 +04:00
2021-02-23 10:16:04 +03:00
DBG_NOTICE ( " %s \\ %s \n " , domain_name , name ) ;
2010-06-08 16:42:59 +04:00
2024-02-16 18:44:57 +03:00
* ptype = SID_NAME_UNKNOWN ;
2021-02-23 10:27:07 +03:00
if ( strequal ( domain_name , unix_users_domain_name ( ) ) ) {
struct passwd * pwd = NULL ;
if ( name [ 0 ] = = ' \0 ' ) {
sid_copy ( & sid , & global_sid_Unix_Users ) ;
type = SID_NAME_DOMAIN ;
goto done ;
}
pwd = Get_Pwnam_alloc ( tmp_ctx , name ) ;
if ( pwd = = NULL ) {
goto fail ;
}
ok = sid_compose ( & sid , & global_sid_Unix_Users , pwd - > pw_uid ) ;
if ( ! ok ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto fail ;
}
type = SID_NAME_USER ;
goto done ;
}
if ( strequal ( domain_name , unix_groups_domain_name ( ) ) ) {
struct group * grp = NULL ;
if ( name [ 0 ] = = ' \0 ' ) {
sid_copy ( & sid , & global_sid_Unix_Groups ) ;
type = SID_NAME_DOMAIN ;
goto done ;
}
grp = getgrnam ( name ) ;
if ( grp = = NULL ) {
goto fail ;
}
ok = sid_compose ( & sid , & global_sid_Unix_Groups , grp - > gr_gid ) ;
if ( ! ok ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto fail ;
}
type = SID_NAME_DOM_GRP ;
goto done ;
}
if ( name [ 0 ] = = ' \0 ' ) {
sid_copy ( & sid , & domain - > sid ) ;
type = SID_NAME_DOMAIN ;
goto done ;
}
2021-02-23 12:38:16 +03:00
ok = lookup_wellknown_name ( tmp_ctx , name , & sid , & dom_name ) ;
2021-02-23 10:27:07 +03:00
if ( ok ) {
type = SID_NAME_WKN_GRP ;
goto done ;
}
2021-02-23 12:38:16 +03:00
{
char * normalized = NULL ;
NTSTATUS nstatus = normalize_name_unmap (
tmp_ctx , name , & normalized ) ;
if ( NT_STATUS_IS_OK ( nstatus ) | |
NT_STATUS_EQUAL ( nstatus , NT_STATUS_FILE_RENAMED ) ) {
2021-12-14 18:27:17 +03:00
lsa_name . string = normalized ;
2021-02-23 12:38:16 +03:00
}
}
2018-03-21 10:44:31 +03:00
again :
2021-02-23 12:38:16 +03:00
status = open_cached_internal_pipe_conn (
domain , & samr_pipe , & dom_pol , NULL , NULL ) ;
2010-06-08 16:42:59 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-02-23 10:27:07 +03:00
goto fail ;
2010-06-08 16:42:59 +04:00
}
2021-02-23 12:38:16 +03:00
h = samr_pipe - > binding_handle ;
2010-06-08 16:42:59 +04:00
2021-02-23 12:38:16 +03:00
status = dcerpc_samr_LookupNames (
h , tmp_ctx , & dom_pol , 1 , & lsa_name , & rids , & types , & result ) ;
2018-03-21 10:44:31 +03:00
2021-02-23 12:38:16 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
2018-03-21 10:44:31 +03:00
retry = true ;
goto again ;
}
2010-06-08 16:42:59 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-02-23 12:38:16 +03:00
DBG_DEBUG ( " dcerpc_samr_LookupNames returned %s \n " ,
nt_errstr ( status ) ) ;
2021-02-23 10:27:07 +03:00
goto fail ;
2010-06-08 16:42:59 +04:00
}
2021-02-23 12:38:16 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
DBG_DEBUG ( " dcerpc_samr_LookupNames resulted in %s \n " ,
nt_errstr ( status ) ) ;
status = result ;
goto fail ;
}
sid_compose ( & sid , & domain - > sid , rids . ids [ 0 ] ) ;
type = types . ids [ 0 ] ;
2010-06-08 16:42:59 +04:00
2021-02-23 10:27:07 +03:00
done :
2019-03-12 02:11:01 +03:00
if ( pdom_name ! = NULL ) {
* pdom_name = talloc_strdup ( mem_ctx , dom_name ) ;
if ( * pdom_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
2021-02-23 10:27:07 +03:00
goto fail ;
2019-03-12 02:11:01 +03:00
}
}
2010-06-17 18:07:02 +04:00
if ( psid ) {
sid_copy ( psid , & sid ) ;
2010-06-08 16:42:59 +04:00
}
2010-06-17 18:07:02 +04:00
if ( ptype ) {
* ptype = type ;
2010-06-08 16:42:59 +04:00
}
2021-02-23 10:27:07 +03:00
status = NT_STATUS_OK ;
fail :
2024-02-16 18:44:57 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NONE_MAPPED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_SOME_NOT_MAPPED ) )
{
status = NT_STATUS_OK ;
}
2010-06-08 16:42:59 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* convert a domain SID to a user or group name */
2010-06-17 18:25:33 +04:00
static NTSTATUS sam_sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * sid ,
char * * pdomain_name ,
char * * pname ,
enum lsa_SidType * ptype )
2010-06-07 12:18:01 +04:00
{
2021-02-23 13:49:16 +03:00
struct rpc_pipe_client * samr_pipe = NULL ;
struct dcerpc_binding_handle * h = NULL ;
struct policy_handle dom_pol = { . handle_type = 0 , } ;
const char * domain_name = " " ;
const char * name = " " ;
enum lsa_SidType type = SID_NAME_USE_NONE ;
struct lsa_Strings names = { . count = 0 , } ;
struct samr_Ids types = { . count = 0 } ;
struct dom_sid domain_sid ;
uint32_t rid ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2021-02-23 13:49:16 +03:00
NTSTATUS status = NT_STATUS_NONE_MAPPED ;
NTSTATUS result ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2021-02-23 13:49:16 +03:00
bool ok ;
2010-06-09 13:52:26 +04:00
2010-06-17 18:25:33 +04:00
DEBUG ( 3 , ( " sam_sid_to_name \n " ) ) ;
2021-02-23 13:49:16 +03:00
if ( sid_check_is_unix_users ( sid ) ) {
domain_name = unix_users_domain_name ( ) ;
type = SID_NAME_DOMAIN ;
goto done ;
}
if ( sid_check_is_in_unix_users ( sid ) ) {
struct passwd * pwd = NULL ;
ok = sid_peek_rid ( sid , & rid ) ;
if ( ! ok ) {
goto fail ;
}
pwd = getpwuid ( rid ) ;
if ( pwd = = NULL ) {
goto fail ;
}
domain_name = unix_users_domain_name ( ) ;
name = talloc_strdup ( tmp_ctx , pwd - > pw_name ) ;
if ( name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
type = SID_NAME_USER ;
goto done ;
}
if ( sid_check_is_unix_groups ( sid ) ) {
domain_name = unix_groups_domain_name ( ) ;
type = SID_NAME_DOMAIN ;
goto done ;
}
if ( sid_check_is_in_unix_groups ( sid ) ) {
struct group * grp = NULL ;
ok = sid_peek_rid ( sid , & rid ) ;
if ( ! ok ) {
goto fail ;
}
grp = getgrgid ( rid ) ;
if ( grp = = NULL ) {
goto fail ;
}
domain_name = unix_groups_domain_name ( ) ;
name = talloc_strdup ( tmp_ctx , grp - > gr_name ) ;
if ( name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
type = SID_NAME_DOM_GRP ;
goto done ;
}
ok = lookup_wellknown_sid ( tmp_ctx , sid , & domain_name , & name ) ;
if ( ok ) {
type = SID_NAME_WKN_GRP ;
2021-02-24 00:09:24 +03:00
goto done ;
2010-06-09 13:52:26 +04:00
}
2021-02-23 13:49:16 +03:00
if ( dom_sid_equal ( sid , & domain - > sid ) ) {
domain_name = domain - > name ;
type = SID_NAME_DOMAIN ;
goto done ;
}
sid_copy ( & domain_sid , sid ) ;
ok = sid_split_rid ( & domain_sid , & rid ) ;
if ( ! ok ) {
goto fail ;
}
if ( ! dom_sid_equal ( & domain_sid , & domain - > sid ) ) {
goto fail ;
}
2018-03-21 10:44:31 +03:00
again :
2021-02-23 13:49:16 +03:00
status = open_cached_internal_pipe_conn (
domain , & samr_pipe , & dom_pol , NULL , NULL ) ;
2010-06-09 13:52:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-02-23 13:49:16 +03:00
goto fail ;
2010-06-09 13:52:26 +04:00
}
2021-02-23 13:49:16 +03:00
h = samr_pipe - > binding_handle ;
2010-06-09 13:52:26 +04:00
2021-02-23 13:49:16 +03:00
status = dcerpc_samr_LookupRids (
h , tmp_ctx , & dom_pol , 1 , & rid , & names , & types , & result ) ;
2010-06-09 13:52:26 +04:00
2021-02-23 13:49:16 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
2018-03-21 10:44:31 +03:00
retry = true ;
goto again ;
}
2021-02-23 13:49:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " dcerpc_samr_LookupRids failed: %s \n " ,
nt_errstr ( status ) ) ;
goto fail ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
DBG_DEBUG ( " dcerpc_samr_LookupRids resulted in %s \n " ,
nt_errstr ( result ) ) ;
status = result ;
goto fail ;
}
domain_name = domain - > name ;
name = names . names [ 0 ] . string ;
type = types . ids [ 0 ] ;
if ( name ! = NULL ) {
char * normalized = NULL ;
NTSTATUS nstatus = normalize_name_map (
tmp_ctx , domain_name , name , & normalized ) ;
if ( NT_STATUS_IS_OK ( nstatus ) | |
NT_STATUS_EQUAL ( nstatus , NT_STATUS_FILE_RENAMED ) ) {
name = normalized ;
}
}
done :
2010-06-17 18:25:33 +04:00
if ( ptype ) {
* ptype = type ;
2010-06-09 13:52:26 +04:00
}
2010-06-17 18:25:33 +04:00
if ( pname ) {
2021-02-23 13:49:16 +03:00
* pname = talloc_strdup ( mem_ctx , name ) ;
if ( * pname = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2010-06-09 13:52:26 +04:00
}
2010-06-17 18:25:33 +04:00
if ( pdomain_name ) {
2021-02-23 13:49:16 +03:00
* pdomain_name = talloc_strdup ( mem_ctx , domain_name ) ;
if ( * pdomain_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2010-06-09 13:52:26 +04:00
}
2021-02-23 13:49:16 +03:00
status = NT_STATUS_OK ;
fail :
2010-06-09 13:52:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
2010-06-17 21:32:18 +04:00
static NTSTATUS sam_rids_to_names ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2011-03-10 18:23:20 +03:00
const struct dom_sid * domain_sid ,
2015-04-24 05:04:23 +03:00
uint32_t * rids ,
2010-06-17 21:32:18 +04:00
size_t num_rids ,
char * * pdomain_name ,
char * * * pnames ,
enum lsa_SidType * * ptypes )
2010-06-07 12:18:01 +04:00
{
2021-02-23 18:03:17 +03:00
struct rpc_pipe_client * samr_pipe = NULL ;
struct dcerpc_binding_handle * h = NULL ;
struct policy_handle dom_pol = { . handle_type = 0 , } ;
2010-06-09 16:33:02 +04:00
enum lsa_SidType * types = NULL ;
char * * names = NULL ;
2021-02-23 18:03:17 +03:00
const char * domain_name = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2021-02-23 18:03:17 +03:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
NTSTATUS result ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2021-02-23 18:03:17 +03:00
uint32_t i ;
2010-06-09 16:33:02 +04:00
2010-06-17 21:32:18 +04:00
DEBUG ( 3 , ( " sam_rids_to_names for %s \n " , domain - > name ) ) ;
2021-02-23 18:03:17 +03:00
types = talloc_array ( tmp_ctx , enum lsa_SidType , num_rids ) ;
if ( types = = NULL ) {
goto fail ;
}
names = talloc_array ( tmp_ctx , char * , num_rids ) ;
if ( names = = NULL ) {
goto fail ;
}
if ( sid_check_is_unix_users ( domain_sid ) ) {
domain_name = unix_users_domain_name ( ) ;
domain_sid = & global_sid_Unix_Users ;
}
if ( sid_check_is_unix_groups ( domain_sid ) ) {
domain_name = unix_groups_domain_name ( ) ;
domain_sid = & global_sid_Unix_Groups ;
}
/* Here we're only interested in the domain name being set */
sid_check_is_wellknown_domain ( domain_sid , & domain_name ) ;
if ( domain_name ! = NULL ) {
uint32_t num_mapped = 0 ;
/*
* Do unix users / groups and wkn in a loop . There is no
* getpwuids ( ) call & friends anyway
*/
for ( i = 0 ; i < num_rids ; i + + ) {
struct dom_sid sid ;
char * name = NULL ;
sid_compose ( & sid , domain_sid , rids [ i ] ) ;
types [ i ] = SID_NAME_UNKNOWN ;
names [ i ] = NULL ;
status = sam_sid_to_name (
domain ,
tmp_ctx ,
& sid ,
2021-12-14 17:46:05 +03:00
NULL ,
2021-02-23 18:03:17 +03:00
& name ,
& types [ i ] ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
names [ i ] = talloc_move ( names , & name ) ;
num_mapped + = 1 ;
}
}
2021-02-24 00:09:24 +03:00
status = NT_STATUS_NONE_MAPPED ;
2021-02-23 18:03:17 +03:00
if ( num_mapped > 0 ) {
status = ( num_mapped = = num_rids ) ?
NT_STATUS_OK : STATUS_SOME_UNMAPPED ;
}
2021-02-24 00:09:24 +03:00
goto done ;
2010-06-09 16:33:02 +04:00
}
2021-02-23 18:03:17 +03:00
domain_name = domain - > name ;
2018-03-21 10:44:31 +03:00
again :
2021-02-23 18:03:17 +03:00
status = open_cached_internal_pipe_conn (
domain , & samr_pipe , & dom_pol , NULL , NULL ) ;
2010-06-09 16:33:02 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-17 21:32:18 +04:00
goto done ;
2010-06-09 16:33:02 +04:00
}
2021-02-23 18:03:17 +03:00
h = samr_pipe - > binding_handle ;
2010-06-09 16:33:02 +04:00
2023-04-26 18:19:29 +03:00
/*
* Magic number 1000 comes from samr . idl
*/
2018-03-21 10:44:31 +03:00
2023-04-26 18:19:29 +03:00
for ( i = 0 ; i < num_rids ; i + = 1000 ) {
uint32_t num_lookup_rids = MIN ( num_rids - i , 1000 ) ;
struct lsa_Strings lsa_names = {
. count = 0 ,
} ;
struct samr_Ids samr_types = {
. count = 0 ,
} ;
uint32_t j ;
status = dcerpc_samr_LookupRids ( h ,
tmp_ctx ,
& dom_pol ,
num_lookup_rids ,
& rids [ i ] ,
& lsa_names ,
& samr_types ,
& result ) ;
if ( ! retry & &
reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-09 16:33:02 +04:00
2023-04-26 18:19:29 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " dcerpc_samr_LookupRids failed: %s \n " ,
nt_errstr ( status ) ) ;
goto fail ;
}
if ( ! NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_EQUAL ( result , STATUS_SOME_UNMAPPED ) ) {
DBG_DEBUG ( " dcerpc_samr_LookupRids resulted in %s \n " ,
nt_errstr ( result ) ) ;
status = result ;
goto fail ;
}
2021-02-23 18:03:17 +03:00
2023-04-26 18:19:29 +03:00
for ( j = 0 ; j < num_lookup_rids ; j + + ) {
uint32_t dst = i + j ;
types [ dst ] = samr_types . ids [ j ] ;
names [ dst ] = talloc_move (
names ,
discard_const_p ( char * ,
& lsa_names . names [ j ] . string ) ) ;
if ( names [ dst ] ! = NULL ) {
char * normalized = NULL ;
NTSTATUS nstatus =
normalize_name_map ( names ,
domain_name ,
names [ dst ] ,
& normalized ) ;
if ( NT_STATUS_IS_OK ( nstatus ) | |
NT_STATUS_EQUAL ( nstatus ,
NT_STATUS_FILE_RENAMED ) ) {
names [ dst ] = normalized ;
}
2021-02-23 18:03:17 +03:00
}
}
2023-04-26 18:19:29 +03:00
TALLOC_FREE ( samr_types . ids ) ;
TALLOC_FREE ( lsa_names . names ) ;
2021-02-23 18:03:17 +03:00
}
done :
2010-06-09 16:33:02 +04:00
if ( pdomain_name ) {
2021-02-23 18:03:17 +03:00
* pdomain_name = talloc_strdup ( mem_ctx , domain_name ) ;
if ( * pdomain_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2010-06-09 16:33:02 +04:00
}
if ( ptypes ) {
* ptypes = talloc_move ( mem_ctx , & types ) ;
}
if ( pnames ) {
* pnames = talloc_move ( mem_ctx , & names ) ;
}
2021-02-23 18:03:17 +03:00
fail :
2010-06-09 16:33:02 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
2010-06-21 12:53:15 +04:00
static NTSTATUS sam_lockout_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo12 * lockout_policy )
2010-06-07 12:18:01 +04:00
{
2010-06-09 16:39:55 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2010-06-09 16:39:55 +04:00
union samr_DomainInfo * info = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2011-01-18 14:43:02 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = NULL ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-09 16:39:55 +04:00
2010-06-21 12:53:15 +04:00
DEBUG ( 3 , ( " sam_lockout_policy \n " ) ) ;
2010-06-09 16:39:55 +04:00
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-09 16:39:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
2011-01-18 14:43:02 +03:00
b = samr_pipe - > binding_handle ;
status = dcerpc_samr_QueryDomainInfo ( b ,
2010-06-09 16:39:55 +04:00
mem_ctx ,
& dom_pol ,
2011-08-26 18:35:29 +04:00
DomainLockoutInformation ,
2011-01-18 14:43:02 +03:00
& info ,
& result ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-09 16:39:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
2011-01-18 14:43:02 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto error ;
}
2010-06-09 16:39:55 +04:00
* lockout_policy = info - > info12 ;
error :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
2010-06-21 12:54:53 +04:00
static NTSTATUS sam_password_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo1 * passwd_policy )
2010-06-07 12:18:01 +04:00
{
2010-06-09 16:41:54 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2010-06-09 16:41:54 +04:00
union samr_DomainInfo * info = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2011-01-18 14:43:02 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = NULL ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-09 16:41:54 +04:00
2010-06-21 12:54:53 +04:00
DEBUG ( 3 , ( " sam_password_policy \n " ) ) ;
2010-06-09 16:41:54 +04:00
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-09 16:41:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
2011-01-18 14:43:02 +03:00
b = samr_pipe - > binding_handle ;
status = dcerpc_samr_QueryDomainInfo ( b ,
2010-06-09 16:41:54 +04:00
mem_ctx ,
& dom_pol ,
2011-08-26 18:35:29 +04:00
DomainPasswordInformation ,
2011-01-18 14:43:02 +03:00
& info ,
& result ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-09 16:41:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
2011-01-18 14:43:02 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto error ;
}
2010-06-09 16:41:54 +04:00
* passwd_policy = info - > info1 ;
error :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
2017-03-02 16:53:47 +03:00
/* Lookup groups a user is a member of. */
static NTSTATUS sam_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 )
{
struct rpc_pipe_client * samr_pipe ;
struct policy_handle dom_pol ;
struct dom_sid * user_grpsids = NULL ;
uint32_t num_groups = 0 ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2017-03-02 16:53:47 +03:00
DEBUG ( 3 , ( " sam_lookup_usergroups \n " ) ) ;
ZERO_STRUCT ( dom_pol ) ;
if ( pnum_groups ) {
* pnum_groups = 0 ;
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2017-03-02 16:53:47 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
status = rpc_lookup_usergroups ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
& domain - > sid ,
user_sid ,
& num_groups ,
& user_grpsids ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2017-03-02 16:53:47 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
if ( pnum_groups ) {
* pnum_groups = num_groups ;
}
if ( puser_grpsids ) {
* puser_grpsids = talloc_move ( mem_ctx , & user_grpsids ) ;
}
done :
TALLOC_FREE ( tmp_ctx ) ;
return status ;
}
2010-06-18 21:08:28 +04:00
static NTSTATUS sam_lookup_useraliases ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32_t num_sids ,
const struct dom_sid * sids ,
uint32_t * pnum_aliases ,
uint32_t * * palias_rids )
2010-06-07 12:18:01 +04:00
{
2010-06-09 17:12:37 +04:00
struct rpc_pipe_client * samr_pipe ;
2017-01-03 12:54:33 +03:00
struct policy_handle dom_pol = { 0 } ;
2010-06-09 17:12:37 +04:00
uint32_t num_aliases = 0 ;
2010-06-18 21:08:28 +04:00
uint32_t * alias_rids = NULL ;
2021-02-24 00:09:24 +03:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
2018-03-21 10:43:10 +03:00
NTSTATUS status ;
2018-03-21 10:44:31 +03:00
bool retry = false ;
2010-06-09 17:12:37 +04:00
2010-06-18 21:08:28 +04:00
DEBUG ( 3 , ( " sam_lookup_useraliases \n " ) ) ;
2010-06-09 17:12:37 +04:00
if ( pnum_aliases ) {
* pnum_aliases = 0 ;
}
2018-03-21 10:44:31 +03:00
again :
2018-03-21 10:43:10 +03:00
status = open_cached_internal_pipe_conn ( domain ,
& samr_pipe ,
& dom_pol ,
NULL ,
NULL ) ;
2010-06-09 17:12:37 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-18 21:08:28 +04:00
goto done ;
2010-06-09 17:12:37 +04:00
}
2010-06-18 21:08:28 +04:00
status = rpc_lookup_useraliases ( tmp_ctx ,
samr_pipe ,
& dom_pol ,
num_sids ,
sids ,
& num_aliases ,
& alias_rids ) ;
2018-03-21 10:44:31 +03:00
if ( ! retry & & reset_connection_on_error ( domain , samr_pipe , status ) ) {
retry = true ;
goto again ;
}
2010-06-18 21:08:28 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-06-09 17:12:37 +04:00
if ( pnum_aliases ) {
* pnum_aliases = num_aliases ;
}
2010-06-18 21:08:28 +04:00
if ( palias_rids ) {
* palias_rids = talloc_move ( mem_ctx , & alias_rids ) ;
}
done :
2010-07-06 03:05:39 +04:00
2010-06-09 17:12:37 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return status ;
2010-06-07 12:18:01 +04:00
}
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods builtin_passdb_methods = {
. consistent = false ,
. query_user_list = builtin_query_user_list ,
. enum_dom_groups = builtin_enum_dom_groups ,
2010-06-17 17:53:06 +04:00
. enum_local_groups = sam_enum_local_groups ,
2010-06-17 18:07:02 +04:00
. name_to_sid = sam_name_to_sid ,
2010-06-17 18:25:33 +04:00
. sid_to_name = sam_sid_to_name ,
2010-06-17 21:32:18 +04:00
. rids_to_names = sam_rids_to_names ,
2017-03-02 16:53:47 +03:00
. lookup_usergroups = sam_lookup_usergroups ,
2010-06-18 21:08:28 +04:00
. lookup_useraliases = sam_lookup_useraliases ,
2010-06-07 12:18:01 +04:00
. lookup_groupmem = sam_lookup_groupmem ,
2023-03-08 10:40:58 +03:00
. lookup_aliasmem = sam_lookup_aliasmem ,
2010-06-21 12:53:15 +04:00
. lockout_policy = sam_lockout_policy ,
2010-06-21 12:54:53 +04:00
. password_policy = sam_password_policy ,
2010-06-07 12:18:01 +04:00
. trusted_domains = builtin_trusted_domains
} ;
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods sam_passdb_methods = {
. consistent = false ,
. query_user_list = sam_query_user_list ,
. enum_dom_groups = sam_enum_dom_groups ,
2010-06-17 17:53:06 +04:00
. enum_local_groups = sam_enum_local_groups ,
2010-06-17 18:07:02 +04:00
. name_to_sid = sam_name_to_sid ,
2010-06-17 18:25:33 +04:00
. sid_to_name = sam_sid_to_name ,
2010-06-17 21:32:18 +04:00
. rids_to_names = sam_rids_to_names ,
2017-03-02 16:53:47 +03:00
. lookup_usergroups = sam_lookup_usergroups ,
2010-06-18 21:08:28 +04:00
. lookup_useraliases = sam_lookup_useraliases ,
2010-06-07 12:18:01 +04:00
. lookup_groupmem = sam_lookup_groupmem ,
2023-03-08 10:40:58 +03:00
. lookup_aliasmem = sam_lookup_aliasmem ,
2010-06-21 12:53:15 +04:00
. lockout_policy = sam_lockout_policy ,
2010-06-21 12:54:53 +04:00
. password_policy = sam_password_policy ,
2010-06-07 12:18:01 +04:00
. trusted_domains = sam_trusted_domains
} ;