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"
/*********************************************************
Change the domain password on the PDC .
Just changes the password betwen the two values specified .
Caller must have the cli connected to the netlogon pipe
already .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
static NTSTATUS just_change_the_password ( struct rpc_pipe_client * cli , TALLOC_CTX * mem_ctx ,
2005-10-18 03:24:00 +00:00
const unsigned char orig_trust_passwd_hash [ 16 ] ,
const unsigned char new_trust_passwd_hash [ 16 ] ,
2003-04-16 10:20:14 +00:00
uint32 sec_channel_type )
2001-12-05 11:00:26 +00:00
{
NTSTATUS result ;
2002-08-30 10:46:59 +00:00
2005-09-30 17:13:37 +00:00
/* Check if the netlogon pipe is open using schannel. If so we
already have valid creds . If not we must set them up . */
if ( cli - > auth . auth_type ! = PIPE_AUTH_TYPE_SCHANNEL ) {
2008-01-17 10:11:11 +01:00
uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS ;
2005-09-30 17:13:37 +00:00
result = rpccli_netlogon_setup_creds ( cli ,
2005-11-04 00:03:55 +00:00
cli - > cli - > desthost , /* server name */
lp_workgroup ( ) , /* domain */
global_myname ( ) , /* client name */
global_myname ( ) , /* machine account name */
2005-09-30 17:13:37 +00:00
orig_trust_passwd_hash ,
sec_channel_type ,
& neg_flags ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
DEBUG ( 3 , ( " just_change_the_password: unable to setup creds (%s)! \n " ,
nt_errstr ( result ) ) ) ;
return result ;
}
2001-12-05 11:00:26 +00:00
}
2005-09-30 17:13:37 +00:00
2008-02-16 16:04:01 +01:00
{
struct netr_Authenticator clnt_creds , srv_cred ;
struct samr_Password new_password ;
netlogon_creds_client_step ( cli - > dc , & clnt_creds ) ;
cred_hash3 ( new_password . hash ,
new_trust_passwd_hash ,
cli - > dc - > sess_key , 1 ) ;
result = rpccli_netr_ServerPasswordSet ( cli , mem_ctx ,
cli - > dc - > remote_machine ,
cli - > dc - > mach_acct ,
sec_channel_type ,
global_myname ( ) ,
& clnt_creds ,
& srv_cred ,
& new_password ) ;
/* Always check returned credentials. */
if ( ! netlogon_creds_client_check ( cli - > dc , & srv_cred . cred ) ) {
DEBUG ( 0 , ( " rpccli_netr_ServerPasswordSet: "
" credentials chain check failed \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
}
2001-12-05 11:00:26 +00:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
DEBUG ( 0 , ( " just_change_the_password: unable to change password (%s)! \n " ,
2002-03-17 04:36:35 +00:00
nt_errstr ( result ) ) ) ;
2001-12-05 11:00:26 +00:00
}
return result ;
}
/*********************************************************
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 ,
unsigned char orig_trust_passwd_hash [ 16 ] ,
uint32 sec_channel_type )
2001-12-05 11:00:26 +00:00
{
unsigned char new_trust_passwd_hash [ 16 ] ;
char * new_trust_passwd ;
char * str ;
NTSTATUS nt_status ;
/* Create a random machine account password */
str = generate_random_str ( DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ) ;
2006-06-19 20:00:51 +00:00
if ( ( new_trust_passwd = talloc_strdup ( mem_ctx , str ) ) = = NULL ) {
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2001-12-05 11:00:26 +00: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
nt_status = just_change_the_password ( cli , mem_ctx , orig_trust_passwd_hash ,
2003-04-16 10:20:14 +00:00
new_trust_passwd_hash , sec_channel_type ) ;
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 " ,
2008-03-28 15:49:13 +01:00
current_timestring ( debug_ctx ( ) , 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 .
*/
2007-03-13 20:53:38 +00:00
if ( ! secrets_store_machine_password ( new_trust_passwd , domain , sec_channel_type ) ) {
2001-12-05 11:00:26 +00:00
nt_status = NT_STATUS_UNSUCCESSFUL ;
}
}
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 ] ;
2003-04-16 10:20:14 +00:00
uint32 sec_channel_type = 0 ;
2001-12-05 11:00:26 +00:00
if ( ! secrets_fetch_trust_account_password ( domain ,
old_trust_passwd_hash ,
2003-04-16 10:20:14 +00:00
NULL , & 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 ;
}
2003-04-16 10:20:14 +00:00
return trust_pw_change_and_store_it ( cli , mem_ctx , domain ,
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 ,
2003-07-01 03:49:41 +00:00
DOM_SID * * sids )
{
POLICY_HND pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
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 ;
2005-09-30 17:13:37 +00:00
struct rpc_pipe_client * lsa_pipe ;
2007-10-18 17:40:25 -07:00
bool retry ;
2008-02-13 00:25:40 +01:00
struct lsa_DomainList dom_list ;
int i ;
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
2007-10-24 14:16:54 -07:00
result = cli_full_connection ( & cli , global_myname ( ) , dc_name , & dc_ss , 0 , " IPC$ " , " IPC " ,
2003-07-30 23:49:29 +00:00
" " , " " , " " , 0 , Undefined , & retry ) ;
2003-07-01 03:49:41 +00:00
if ( ! NT_STATUS_IS_OK ( result ) )
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
2005-09-30 17:13:37 +00:00
lsa_pipe = cli_rpc_pipe_open_noauth ( cli , PI_LSARPC , & result ) ;
if ( ! lsa_pipe ) {
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
/* get a handle */
2003-07-01 17:51:52 +00:00
2005-09-30 17:13:37 +00:00
result = rpccli_lsa_open_policy ( lsa_pipe , mem_ctx , True ,
2008-02-27 15:49:31 +01:00
LSA_POLICY_VIEW_LOCAL_INFORMATION , & pol ) ;
2003-07-01 03:49:41 +00:00
if ( ! NT_STATUS_IS_OK ( result ) )
goto done ;
/* Lookup list of trusted domains */
2008-02-13 00:25:40 +01:00
result = rpccli_lsa_EnumTrustDom ( lsa_pipe , mem_ctx ,
& pol ,
& enum_ctx ,
& dom_list ,
( uint32_t ) - 1 ) ;
2003-07-01 17:51:52 +00:00
if ( ! NT_STATUS_IS_OK ( result ) )
2003-07-01 03:49:41 +00:00
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 ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
* sids = TALLOC_ZERO_ARRAY ( mem_ctx , DOM_SID , * num_domains ) ;
if ( ! * sids ) {
result = NT_STATUS_NO_MEMORY ;
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
2003-07-01 17:51:52 +00:00
return NT_STATUS_IS_OK ( result ) ;
2003-03-14 17:05:13 +00:00
}