2003-07-01 17:51:52 +00:00
/*
2002-01-30 06:08:46 +00:00
* Unix SMB / CIFS implementation .
2003-03-14 17:05:13 +00:00
* Routines to operate on various trust relationships
* Copyright ( C ) Andrew Bartlett 2001
* Copyright ( C ) Rafal Szczesniak 2003
2001-12-05 11:00:26 +00: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 19:25:36 +00:00
* the Free Software Foundation ; either version 3 of the License , or
2001-12-05 11:00:26 +00: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 05:23:25 +00:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2001-12-05 11:00:26 +00:00
*/
# include "includes.h"
2009-03-16 21:27:58 +11:00
# include "../libcli/auth/libcli_auth.h"
2011-01-18 14:59:20 +01:00
# include "../librpc/gen_ndr/ndr_lsa_c.h"
2010-05-18 18:26:16 +02:00
# include "rpc_client/cli_lsarpc.h"
2010-05-18 18:26:03 +02:00
# include "rpc_client/cli_netlogon.h"
2011-02-28 10:19:44 +01:00
# include "rpc_client/cli_pipe.h"
2010-06-30 12:10:55 +02:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2010-08-05 02:25:37 +02:00
# include "secrets.h"
2011-03-18 18:58:37 +01:00
# include "passdb.h"
2001-12-05 11:00:26 +00:00
/*********************************************************
Change the domain password on the PDC .
Store the password ourselves , but use the supplied password
Caller must have already setup the connection to the NETLOGON pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
NTSTATUS trust_pw_change_and_store_it ( struct rpc_pipe_client * cli , TALLOC_CTX * mem_ctx ,
2003-04-16 10:20:14 +00:00
const char * domain ,
2009-10-08 00:34:05 +02:00
const char * account_name ,
2003-04-16 10:20:14 +00:00
unsigned char orig_trust_passwd_hash [ 16 ] ,
2009-10-13 10:15:34 +02:00
enum netr_SchannelType sec_channel_type )
2001-12-05 11:00:26 +00:00
{
unsigned char new_trust_passwd_hash [ 16 ] ;
char * new_trust_passwd ;
NTSTATUS nt_status ;
2009-10-04 15:13:44 +02:00
2009-10-08 00:39:40 +02:00
switch ( sec_channel_type ) {
case SEC_CHAN_WKSTA :
case SEC_CHAN_DOMAIN :
break ;
default :
return NT_STATUS_NOT_SUPPORTED ;
}
2001-12-05 11:00:26 +00:00
/* Create a random machine account password */
2008-10-19 10:05:48 +02:00
new_trust_passwd = generate_random_str ( mem_ctx , DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ) ;
2006-06-19 20:00:51 +00:00
2008-10-19 10:05:48 +02:00
if ( new_trust_passwd = = NULL ) {
2006-06-19 20:00:51 +00:00
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2009-10-04 15:13:44 +02:00
2002-06-25 07:58:29 +00:00
E_md4hash ( new_trust_passwd , new_trust_passwd_hash ) ;
2001-12-05 11:00:26 +00:00
2009-10-05 22:14:06 +02:00
nt_status = rpccli_netlogon_set_trust_password ( cli , mem_ctx ,
2009-10-08 00:34:05 +02:00
account_name ,
2009-10-05 22:14:06 +02:00
orig_trust_passwd_hash ,
new_trust_passwd ,
new_trust_passwd_hash ,
sec_channel_type ) ;
2009-10-04 15:13:44 +02:00
2001-12-05 11:00:26 +00:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2002-06-25 08:57:24 +00:00
DEBUG ( 3 , ( " %s : trust_pw_change_and_store_it: Changed password. \n " ,
2009-11-03 10:59:18 +01:00
current_timestring ( talloc_tos ( ) , False ) ) ) ;
2001-12-05 11:00:26 +00:00
/*
* Return the result of trying to write the new password
* back into the trust account file .
*/
2009-10-08 00:39:40 +02:00
switch ( sec_channel_type ) {
case SEC_CHAN_WKSTA :
if ( ! secrets_store_machine_password ( new_trust_passwd , domain , sec_channel_type ) ) {
nt_status = NT_STATUS_UNSUCCESSFUL ;
}
break ;
case SEC_CHAN_DOMAIN : {
char * pwd ;
struct dom_sid sid ;
time_t pass_last_set_time ;
/* we need to get the sid first for the
* pdb_set_trusteddom_pw call */
if ( ! pdb_get_trusteddom_pw ( domain , & pwd , & sid , & pass_last_set_time ) ) {
nt_status = NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE ;
}
if ( ! pdb_set_trusteddom_pw ( domain , new_trust_passwd , & sid ) ) {
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
break ;
}
default :
break ;
2001-12-05 11:00:26 +00:00
}
}
return nt_status ;
}
/*********************************************************
Change the domain password on the PDC .
Do most of the legwork ourselfs . Caller must have
already setup the connection to the NETLOGON pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
NTSTATUS trust_pw_find_change_and_store_it ( struct rpc_pipe_client * cli ,
2003-04-16 10:20:14 +00:00
TALLOC_CTX * mem_ctx ,
2002-11-12 23:15:52 +00:00
const char * domain )
2001-12-05 11:00:26 +00:00
{
unsigned char old_trust_passwd_hash [ 16 ] ;
2009-10-13 10:15:34 +02:00
enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL ;
2009-10-08 00:39:40 +02:00
const char * account_name ;
2003-04-16 10:20:14 +00:00
2009-10-08 00:39:40 +02:00
if ( ! get_trust_pw_hash ( domain , old_trust_passwd_hash , & account_name ,
& sec_channel_type ) ) {
2001-12-05 11:00:26 +00:00
DEBUG ( 0 , ( " could not fetch domain secrets for domain %s! \n " , domain ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2009-10-04 15:13:44 +02:00
2003-04-16 10:20:14 +00:00
return trust_pw_change_and_store_it ( cli , mem_ctx , domain ,
2009-10-08 00:39:40 +02:00
account_name ,
2003-04-16 10:20:14 +00:00
old_trust_passwd_hash ,
sec_channel_type ) ;
2003-03-14 17:05:13 +00:00
}
2003-07-01 03:49:41 +00:00
/*********************************************************************
Enumerate the list of trusted domains from a DC
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-18 17:40:25 -07:00
bool enumerate_domain_trusts ( TALLOC_CTX * mem_ctx , const char * domain ,
2003-07-01 17:51:52 +00:00
char * * * domain_names , uint32 * num_domains ,
2010-05-21 11:25:01 +10:00
struct dom_sid * * sids )
2003-07-01 03:49:41 +00:00
{
2009-03-18 22:49:41 +01:00
struct policy_handle pol ;
2011-01-18 14:59:20 +01:00
NTSTATUS status , result ;
2003-07-01 03:49:41 +00:00
fstring dc_name ;
2007-10-24 14:16:54 -07:00
struct sockaddr_storage dc_ss ;
2003-07-01 03:49:41 +00:00
uint32 enum_ctx = 0 ;
struct cli_state * cli = NULL ;
2009-11-12 13:56:33 -08:00
struct rpc_pipe_client * lsa_pipe = NULL ;
2008-02-13 00:25:40 +01:00
struct lsa_DomainList dom_list ;
int i ;
2011-01-18 14:59:20 +01:00
struct dcerpc_binding_handle * b = NULL ;
2003-07-01 17:51:52 +00:00
2003-07-01 03:49:41 +00:00
* domain_names = NULL ;
* num_domains = 0 ;
* sids = NULL ;
2003-07-01 17:51:52 +00:00
2003-07-01 03:49:41 +00:00
/* lookup a DC first */
2003-07-01 17:51:52 +00:00
2007-10-24 14:16:54 -07:00
if ( ! get_dc_name ( domain , NULL , dc_name , & dc_ss ) ) {
2003-07-01 03:49:41 +00:00
DEBUG ( 3 , ( " enumerate_domain_trusts: can't locate a DC for domain %s \n " ,
domain ) ) ;
return False ;
}
2003-07-01 17:51:52 +00:00
2003-07-01 03:49:41 +00:00
/* setup the anonymous connection */
2003-07-01 17:51:52 +00:00
2011-01-18 14:59:20 +01:00
status = cli_full_connection ( & cli , global_myname ( ) , dc_name , & dc_ss , 0 , " IPC$ " , " IPC " ,
2010-12-20 16:37:23 +01:00
" " , " " , " " , 0 , Undefined ) ;
2011-01-18 14:59:20 +01:00
if ( ! NT_STATUS_IS_OK ( status ) )
2003-07-01 03:49:41 +00:00
goto done ;
2003-07-01 17:51:52 +00:00
2003-07-01 03:49:41 +00:00
/* open the LSARPC_PIPE */
2003-07-01 17:51:52 +00:00
2011-01-18 14:59:20 +01:00
status = cli_rpc_pipe_open_noauth ( cli , & ndr_table_lsarpc . syntax_id ,
2008-07-20 11:04:31 +02:00
& lsa_pipe ) ;
2011-01-18 14:59:20 +01:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-07-01 03:49:41 +00:00
goto done ;
}
2003-07-01 17:51:52 +00:00
2011-01-18 14:59:20 +01:00
b = lsa_pipe - > binding_handle ;
2003-07-01 03:49:41 +00:00
/* get a handle */
2003-07-01 17:51:52 +00:00
2011-01-18 14:59:20 +01:00
status = rpccli_lsa_open_policy ( lsa_pipe , mem_ctx , True ,
2008-02-27 15:49:31 +01:00
LSA_POLICY_VIEW_LOCAL_INFORMATION , & pol ) ;
2011-01-18 14:59:20 +01:00
if ( ! NT_STATUS_IS_OK ( status ) )
2003-07-01 03:49:41 +00:00
goto done ;
/* Lookup list of trusted domains */
2011-01-18 14:59:20 +01:00
status = dcerpc_lsa_EnumTrustDom ( b , mem_ctx ,
2008-02-13 00:25:40 +01:00
& pol ,
& enum_ctx ,
& dom_list ,
2011-01-18 14:59:20 +01:00
( uint32_t ) - 1 ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
2003-07-01 03:49:41 +00:00
goto done ;
2011-01-18 14:59:20 +01:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2003-07-01 17:51:52 +00:00
2008-02-13 00:25:40 +01:00
* num_domains = dom_list . count ;
* domain_names = TALLOC_ZERO_ARRAY ( mem_ctx , char * , * num_domains ) ;
if ( ! * domain_names ) {
2011-01-18 14:59:20 +01:00
status = NT_STATUS_NO_MEMORY ;
2008-02-13 00:25:40 +01:00
goto done ;
}
2010-05-21 11:25:01 +10:00
* sids = TALLOC_ZERO_ARRAY ( mem_ctx , struct dom_sid , * num_domains ) ;
2008-02-13 00:25:40 +01:00
if ( ! * sids ) {
2011-01-18 14:59:20 +01:00
status = NT_STATUS_NO_MEMORY ;
2008-02-13 00:25:40 +01:00
goto done ;
}
for ( i = 0 ; i < * num_domains ; i + + ) {
( * domain_names ) [ i ] = CONST_DISCARD ( char * , dom_list . domains [ i ] . name . string ) ;
( * sids ) [ i ] = * dom_list . domains [ i ] . sid ;
}
2003-07-01 17:51:52 +00:00
done :
2003-07-01 03:49:41 +00:00
/* cleanup */
2003-09-16 03:54:42 +00:00
if ( cli ) {
2003-11-22 06:15:28 +00:00
DEBUG ( 10 , ( " enumerate_domain_trusts: shutting down connection... \n " ) ) ;
2003-09-16 03:54:42 +00:00
cli_shutdown ( cli ) ;
}
2003-03-15 08:18:29 +00:00
2011-01-18 14:59:20 +01:00
return NT_STATUS_IS_OK ( status ) ;
2003-03-14 17:05:13 +00:00
}
2010-06-30 12:10:55 +02:00
NTSTATUS change_trust_account_password ( const char * domain , const char * remote_machine )
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
struct sockaddr_storage pdc_ss ;
fstring dc_name ;
struct cli_state * cli = NULL ;
struct rpc_pipe_client * netlogon_pipe = NULL ;
DEBUG ( 5 , ( " change_trust_account_password: Attempting to change trust account password in domain %s.... \n " ,
domain ) ) ;
if ( remote_machine = = NULL | | ! strcmp ( remote_machine , " * " ) ) {
/* Use the PDC *only* for this */
if ( ! get_pdc_ip ( domain , & pdc_ss ) ) {
DEBUG ( 0 , ( " Can't get IP for PDC for domain %s \n " , domain ) ) ;
goto failed ;
}
if ( ! name_status_find ( domain , 0x1b , 0x20 , & pdc_ss , dc_name ) )
goto failed ;
} else {
/* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */
fstrcpy ( dc_name , remote_machine ) ;
}
/* if this next call fails, then give up. We can't do
password changes on BDC ' s - - jerry */
if ( ! NT_STATUS_IS_OK ( cli_full_connection ( & cli , global_myname ( ) , dc_name ,
NULL , 0 ,
" IPC$ " , " IPC " ,
" " , " " ,
2010-12-20 16:37:23 +01:00
" " , 0 , Undefined ) ) ) {
2010-06-30 12:10:55 +02:00
DEBUG ( 0 , ( " modify_trust_password: Connection to %s failed! \n " , dc_name ) ) ;
nt_status = NT_STATUS_UNSUCCESSFUL ;
goto failed ;
}
/*
* Ok - we have an anonymous connection to the IPC $ share .
* Now start the NT Domain stuff : - ) .
*/
/* Shouldn't we open this with schannel ? JRA. */
nt_status = cli_rpc_pipe_open_noauth (
cli , & ndr_table_netlogon . syntax_id , & netlogon_pipe ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " modify_trust_password: unable to open the domain client session to machine %s. Error was : %s. \n " ,
dc_name , nt_errstr ( nt_status ) ) ) ;
cli_shutdown ( cli ) ;
cli = NULL ;
goto failed ;
}
nt_status = trust_pw_find_change_and_store_it (
netlogon_pipe , netlogon_pipe , domain ) ;
cli_shutdown ( cli ) ;
cli = NULL ;
failed :
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " %s : change_trust_account_password: Failed to change password for domain %s. \n " ,
current_timestring ( talloc_tos ( ) , False ) , domain ) ) ;
}
else
DEBUG ( 5 , ( " change_trust_account_password: sucess! \n " ) ) ;
return nt_status ;
}