2007-12-11 23:31:44 +03:00
/*
* Unix SMB / CIFS implementation .
* libnet Join Support
* Copyright ( C ) Gerald ( Jerry ) Carter 2006
2008-01-04 19:01:52 +03:00
* Copyright ( C ) Guenther Deschner 2007 - 2008
2007-12-11 23:31:44 +03: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"
2008-01-13 03:40:05 +03:00
# include "libnet/libnet.h"
2007-12-11 23:31:44 +03:00
2008-01-07 20:46:07 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-16 12:37:48 +03:00
# define LIBNET_JOIN_DUMP_CTX(ctx, r, f) \
do { \
char * str = NULL ; \
str = NDR_PRINT_FUNCTION_STRING ( ctx , libnet_JoinCtx , f , r ) ; \
DEBUG ( 1 , ( " libnet_Join: \n %s " , str ) ) ; \
talloc_free ( str ) ; \
} while ( 0 )
# define LIBNET_JOIN_IN_DUMP_CTX(ctx, r) \
LIBNET_JOIN_DUMP_CTX ( ctx , r , NDR_IN | NDR_SET_VALUES )
# define LIBNET_JOIN_OUT_DUMP_CTX(ctx, r) \
LIBNET_JOIN_DUMP_CTX ( ctx , r , NDR_OUT )
# define LIBNET_UNJOIN_DUMP_CTX(ctx, r, f) \
do { \
char * str = NULL ; \
str = NDR_PRINT_FUNCTION_STRING ( ctx , libnet_UnjoinCtx , f , r ) ; \
DEBUG ( 1 , ( " libnet_Unjoin: \n %s " , str ) ) ; \
talloc_free ( str ) ; \
} while ( 0 )
# define LIBNET_UNJOIN_IN_DUMP_CTX(ctx, r) \
LIBNET_UNJOIN_DUMP_CTX ( ctx , r , NDR_IN | NDR_SET_VALUES )
# define LIBNET_UNJOIN_OUT_DUMP_CTX(ctx, r) \
LIBNET_UNJOIN_DUMP_CTX ( ctx , r , NDR_OUT )
2008-02-28 13:00:50 +03:00
# define W_ERROR_NOT_OK_GOTO_DONE(x) do { \
if ( ! W_ERROR_IS_OK ( x ) ) { \
goto done ; \
} \
} while ( 0 )
2008-01-16 12:37:48 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 20:46:07 +03:00
static void libnet_join_set_error_string ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
const char * format , . . . )
{
va_list args ;
2008-01-12 04:17:10 +03:00
if ( r - > out . error_string ) {
return ;
}
2008-01-07 20:46:07 +03:00
va_start ( args , format ) ;
2008-01-12 04:17:10 +03:00
r - > out . error_string = talloc_vasprintf ( mem_ctx , format , args ) ;
2008-01-07 20:46:07 +03:00
va_end ( args ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void libnet_unjoin_set_error_string ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r ,
const char * format , . . . )
{
va_list args ;
2008-01-12 04:17:10 +03:00
if ( r - > out . error_string ) {
return ;
}
2008-01-07 20:46:07 +03:00
va_start ( args , format ) ;
2008-01-12 04:17:10 +03:00
r - > out . error_string = talloc_vasprintf ( mem_ctx , format , args ) ;
2008-01-07 20:46:07 +03:00
va_end ( args ) ;
}
2008-01-12 04:10:17 +03:00
# ifdef WITH_ADS
2008-01-07 22:41:55 +03:00
2008-01-07 20:58:04 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_connect_ads ( const char * dns_domain_name ,
const char * netbios_domain_name ,
const char * dc_name ,
const char * user_name ,
const char * password ,
ADS_STRUCT * * ads )
{
ADS_STATUS status ;
ADS_STRUCT * my_ads = NULL ;
my_ads = ads_init ( dns_domain_name ,
netbios_domain_name ,
dc_name ) ;
if ( ! my_ads ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
if ( user_name ) {
SAFE_FREE ( my_ads - > auth . user_name ) ;
my_ads - > auth . user_name = SMB_STRDUP ( user_name ) ;
}
if ( password ) {
SAFE_FREE ( my_ads - > auth . password ) ;
my_ads - > auth . password = SMB_STRDUP ( password ) ;
}
status = ads_connect ( my_ads ) ;
if ( ! ADS_ERR_OK ( status ) ) {
ads_destroy ( & my_ads ) ;
return status ;
}
* ads = my_ads ;
return ADS_SUCCESS ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_join_connect_ads ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
status = libnet_connect_ads ( r - > in . domain_name ,
r - > in . domain_name ,
r - > in . dc_name ,
r - > in . admin_account ,
r - > in . admin_password ,
& r - > in . ads ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to connect to AD: %s " ,
2008-01-07 20:58:04 +03:00
ads_errstr ( status ) ) ;
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_unjoin_connect_ads ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
ADS_STATUS status ;
status = libnet_connect_ads ( r - > in . domain_name ,
r - > in . domain_name ,
r - > in . dc_name ,
r - > in . admin_account ,
r - > in . admin_password ,
& r - > in . ads ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to connect to AD: %s " ,
2008-01-07 20:58:04 +03:00
ads_errstr ( status ) ) ;
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 21:07:38 +03:00
static ADS_STATUS libnet_join_precreate_machine_acct ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
LDAPMessage * res = NULL ;
const char * attrs [ ] = { " dn " , NULL } ;
status = ads_search_dn ( r - > in . ads , & res , r - > in . account_ou , attrs ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
if ( ads_count_replies ( r - > in . ads , res ) ! = 1 ) {
ads_msgfree ( r - > in . ads , res ) ;
return ADS_ERROR_LDAP ( LDAP_NO_SUCH_OBJECT ) ;
}
status = ads_create_machine_acct ( r - > in . ads ,
r - > in . machine_name ,
r - > in . account_ou ) ;
ads_msgfree ( r - > in . ads , res ) ;
if ( ( status . error_type = = ENUM_ADS_ERROR_LDAP ) & &
( status . err . rc = = LDAP_ALREADY_EXISTS ) ) {
status = ADS_SUCCESS ;
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 21:11:26 +03:00
static ADS_STATUS libnet_unjoin_remove_machine_acct ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
ADS_STATUS status ;
if ( ! r - > in . ads ) {
status = libnet_unjoin_connect_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
}
2008-01-11 16:50:10 +03:00
status = ads_leave_realm ( r - > in . ads , r - > in . machine_name ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to leave realm: %s " ,
2008-01-11 16:50:10 +03:00
ads_errstr ( status ) ) ;
return status ;
}
return ADS_SUCCESS ;
2008-01-07 21:11:26 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 21:31:20 +03:00
static ADS_STATUS libnet_join_find_machine_acct ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
LDAPMessage * res = NULL ;
char * dn = NULL ;
if ( ! r - > in . machine_name ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
status = ads_find_machine_acct ( r - > in . ads ,
& res ,
r - > in . machine_name ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
if ( ads_count_replies ( r - > in . ads , res ) ! = 1 ) {
status = ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
goto done ;
}
dn = ads_get_dn ( r - > in . ads , res ) ;
if ( ! dn ) {
status = ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
goto done ;
}
r - > out . dn = talloc_strdup ( mem_ctx , dn ) ;
if ( ! r - > out . dn ) {
status = ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
goto done ;
}
done :
ads_msgfree ( r - > in . ads , res ) ;
ads_memfree ( r - > in . ads , dn ) ;
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 22:16:57 +03:00
static ADS_STATUS libnet_join_set_machine_spn ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
ADS_MODLIST mods ;
fstring my_fqdn ;
const char * spn_array [ 3 ] = { NULL , NULL , NULL } ;
char * spn = NULL ;
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , r - > in . machine_name ) ;
if ( ! spn ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
strupper_m ( spn ) ;
spn_array [ 0 ] = spn ;
if ( name_to_fqdn ( my_fqdn , r - > in . machine_name ) & &
! strequal ( my_fqdn , r - > in . machine_name ) ) {
strlower_m ( my_fqdn ) ;
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , my_fqdn ) ;
if ( ! spn ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
spn_array [ 1 ] = spn ;
}
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
status = ads_mod_str ( mem_ctx , & mods , " dNSHostName " , my_fqdn ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
status = ads_mod_strlist ( mem_ctx , & mods , " servicePrincipalName " ,
spn_array ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
return ads_gen_mod ( r - > in . ads , r - > out . dn , mods ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_join_set_machine_upn ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
ADS_MODLIST mods ;
if ( ! r - > in . create_upn ) {
return ADS_SUCCESS ;
}
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
if ( ! r - > in . upn ) {
r - > in . upn = talloc_asprintf ( mem_ctx ,
" host/%s@%s " ,
r - > in . machine_name ,
r - > out . dns_domain_name ) ;
if ( ! r - > in . upn ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
}
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
status = ads_mod_str ( mem_ctx , & mods , " userPrincipalName " , r - > in . upn ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
return ads_gen_mod ( r - > in . ads , r - > out . dn , mods ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_join_set_os_attributes ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
ADS_MODLIST mods ;
char * os_sp = NULL ;
if ( ! r - > in . os_name | | ! r - > in . os_version ) {
return ADS_SUCCESS ;
}
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
os_sp = talloc_asprintf ( mem_ctx , " Samba %s " , SAMBA_VERSION_STRING ) ;
if ( ! os_sp ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
status = ads_mod_str ( mem_ctx , & mods , " operatingSystem " ,
r - > in . os_name ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
status = ads_mod_str ( mem_ctx , & mods , " operatingSystemVersion " ,
r - > in . os_version ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
status = ads_mod_str ( mem_ctx , & mods , " operatingSystemServicePack " ,
os_sp ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
return ads_gen_mod ( r - > in . ads , r - > out . dn , mods ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool libnet_join_create_keytab ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
if ( ! lp_use_kerberos_keytab ( ) ) {
return true ;
}
2008-01-12 04:10:17 +03:00
2008-01-07 22:16:57 +03:00
if ( ! ads_keytab_create_default ( r - > in . ads ) ) {
return false ;
}
2008-01-12 04:10:17 +03:00
2008-01-07 22:16:57 +03:00
return true ;
}
2008-01-08 20:59:57 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool libnet_join_derive_salting_principal ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
uint32_t domain_func ;
ADS_STATUS status ;
const char * salt = NULL ;
char * std_salt = NULL ;
status = ads_domain_func_level ( r - > in . ads , & domain_func ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
2008-01-12 04:20:33 +03:00
" failed to determine domain functional level: %s " ,
ads_errstr ( status ) ) ;
2008-01-08 20:59:57 +03:00
return false ;
}
std_salt = kerberos_standard_des_salt ( ) ;
if ( ! std_salt ) {
libnet_join_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to obtain standard DES salt " ) ;
2008-01-08 20:59:57 +03:00
return false ;
}
salt = talloc_strdup ( mem_ctx , std_salt ) ;
if ( ! salt ) {
return false ;
}
SAFE_FREE ( std_salt ) ;
if ( domain_func = = DS_DOMAIN_FUNCTION_2000 ) {
char * upn ;
upn = ads_get_upn ( r - > in . ads , mem_ctx ,
r - > in . machine_name ) ;
if ( upn ) {
salt = talloc_strdup ( mem_ctx , upn ) ;
if ( ! salt ) {
return false ;
}
}
}
return kerberos_secrets_store_des_salt ( salt ) ;
}
2008-01-09 14:47:13 +03:00
2008-01-12 04:15:42 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS libnet_join_post_processing_ads ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
2008-02-28 13:02:01 +03:00
if ( ! r - > in . ads ) {
status = libnet_join_connect_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
}
2008-01-12 04:15:42 +03:00
status = libnet_join_set_machine_spn ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to set machine spn: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
status = libnet_join_set_os_attributes ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to set machine os attributes: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
status = libnet_join_set_machine_upn ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to set machine upn: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
if ( ! libnet_join_derive_salting_principal ( mem_ctx , r ) ) {
return ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
}
if ( ! libnet_join_create_keytab ( mem_ctx , r ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to create kerberos keytab " ) ;
return ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
}
return ADS_SUCCESS ;
}
2008-01-12 04:10:17 +03:00
# endif /* WITH_ADS */
2008-01-08 20:59:57 +03:00
2008-01-07 22:16:57 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-04 19:09:21 +03:00
static bool libnet_join_joindomain_store_secrets ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
if ( ! secrets_store_domain_sid ( r - > out . netbios_domain_name ,
r - > out . domain_sid ) )
{
return false ;
}
if ( ! secrets_store_machine_password ( r - > in . machine_password ,
r - > out . netbios_domain_name ,
SEC_CHAN_WKSTA ) )
{
return false ;
}
return true ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-04 19:09:21 +03:00
static NTSTATUS libnet_join_joindomain_rpc ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
2007-12-11 23:31:44 +03:00
{
struct cli_state * cli = NULL ;
struct rpc_pipe_client * pipe_hnd = NULL ;
POLICY_HND sam_pol , domain_pol , user_pol , lsa_pol ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
char * acct_name ;
2008-02-01 16:21:54 +03:00
struct lsa_String lsa_acct_name ;
2007-12-11 23:31:44 +03:00
uint32 user_rid ;
uint32 acb_info = ACB_WSTRUST ;
uchar pwbuf [ 532 ] ;
struct MD5Context md5ctx ;
uchar md5buffer [ 16 ] ;
DATA_BLOB digested_session_key ;
uchar md4_trust_password [ 16 ] ;
2008-02-08 03:57:55 +03:00
union lsa_PolicyInformation * info = NULL ;
2008-02-08 16:48:55 +03:00
struct samr_Ids user_rids ;
struct samr_Ids name_types ;
2008-02-12 02:51:51 +03:00
union samr_UserInfo user_info ;
2007-12-11 23:31:44 +03:00
2008-01-04 19:01:52 +03:00
if ( ! r - > in . machine_password ) {
r - > in . machine_password = talloc_strdup ( mem_ctx , generate_random_str ( DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ) ) ;
NT_STATUS_HAVE_NO_MEMORY ( r - > in . machine_password ) ;
}
2007-12-11 23:31:44 +03:00
2008-01-04 19:11:14 +03:00
status = cli_full_connection ( & cli , NULL ,
r - > in . dc_name ,
2007-12-11 23:31:44 +03:00
NULL , 0 ,
" IPC$ " , " IPC " ,
r - > in . admin_account ,
2008-01-04 19:01:52 +03:00
NULL ,
r - > in . admin_password ,
0 ,
Undefined , NULL ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
pipe_hnd = cli_rpc_pipe_open_noauth ( cli , PI_LSARPC , & status ) ;
if ( ! pipe_hnd ) {
goto done ;
}
status = rpccli_lsa_open_policy ( pipe_hnd , mem_ctx , True ,
SEC_RIGHTS_MAXIMUM_ALLOWED , & lsa_pol ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-08 03:57:55 +03:00
status = rpccli_lsa_QueryInfoPolicy2 ( pipe_hnd , mem_ctx ,
& lsa_pol ,
LSA_POLICY_INFO_DNS ,
& info ) ;
2008-01-11 16:41:34 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
r - > out . domain_is_ad = true ;
2008-02-08 03:57:55 +03:00
r - > out . netbios_domain_name = info - > dns . name . string ;
r - > out . dns_domain_name = info - > dns . dns_domain . string ;
r - > out . domain_sid = info - > dns . sid ;
2008-01-11 16:41:34 +03:00
}
2007-12-18 12:31:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-08 12:21:25 +03:00
status = rpccli_lsa_QueryInfoPolicy ( pipe_hnd , mem_ctx ,
& lsa_pol ,
LSA_POLICY_INFO_ACCOUNT_DOMAIN ,
& info ) ;
2007-12-18 12:31:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-08 12:21:25 +03:00
r - > out . netbios_domain_name = info - > account_domain . name . string ;
r - > out . domain_sid = info - > account_domain . sid ;
2007-12-18 12:31:12 +03:00
}
2007-12-11 23:31:44 +03:00
rpccli_lsa_Close ( pipe_hnd , mem_ctx , & lsa_pol ) ;
cli_rpc_pipe_close ( pipe_hnd ) ;
pipe_hnd = cli_rpc_pipe_open_noauth ( cli , PI_SAMR , & status ) ;
if ( ! pipe_hnd ) {
goto done ;
}
2008-02-04 21:43:07 +03:00
status = rpccli_samr_Connect2 ( pipe_hnd , mem_ctx ,
pipe_hnd - > cli - > desthost ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
& sam_pol ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-01 13:12:05 +03:00
status = rpccli_samr_OpenDomain ( pipe_hnd , mem_ctx ,
& sam_pol ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
r - > out . domain_sid ,
& domain_pol ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-01-11 16:42:48 +03:00
acct_name = talloc_asprintf ( mem_ctx , " %s$ " , r - > in . machine_name ) ;
2007-12-11 23:31:44 +03:00
strlower_m ( acct_name ) ;
2008-02-01 16:21:54 +03:00
init_lsa_String ( & lsa_acct_name , acct_name ) ;
2008-01-05 01:11:53 +03:00
if ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ) {
2008-01-25 03:00:51 +03:00
uint32_t acct_flags =
SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
SEC_STD_WRITE_DAC | SEC_STD_DELETE |
SAMR_USER_ACCESS_SET_PASSWORD |
SAMR_USER_ACCESS_GET_ATTRIBUTES |
SAMR_USER_ACCESS_SET_ATTRIBUTES ;
2008-02-01 16:21:54 +03:00
uint32_t access_granted = 0 ;
status = rpccli_samr_CreateUser2 ( pipe_hnd , mem_ctx ,
& domain_pol ,
& lsa_acct_name ,
ACB_WSTRUST ,
acct_flags ,
& user_pol ,
& access_granted ,
& user_rid ) ;
2008-01-05 01:11:53 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_USER_EXISTS ) ) {
2008-01-12 04:24:55 +03:00
if ( ! ( r - > in . join_flags &
WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ) ) {
2008-01-05 01:11:53 +03:00
goto done ;
}
2007-12-11 23:31:44 +03:00
}
2008-01-05 01:11:53 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( pipe_hnd , mem_ctx , & user_pol ) ;
2008-01-05 01:11:53 +03:00
}
2007-12-11 23:31:44 +03:00
}
2008-02-08 16:48:55 +03:00
status = rpccli_samr_LookupNames ( pipe_hnd , mem_ctx ,
& domain_pol ,
1 ,
& lsa_acct_name ,
& user_rids ,
& name_types ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-08 16:48:55 +03:00
if ( name_types . ids [ 0 ] ! = SID_NAME_USER ) {
2007-12-18 12:16:40 +03:00
status = NT_STATUS_INVALID_WORKSTATION ;
2007-12-11 23:31:44 +03:00
goto done ;
}
2008-02-08 16:48:55 +03:00
user_rid = user_rids . ids [ 0 ] ;
2007-12-11 23:31:44 +03:00
2008-02-01 13:57:53 +03:00
status = rpccli_samr_OpenUser ( pipe_hnd , mem_ctx ,
& domain_pol ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
user_rid ,
& user_pol ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-01-04 19:01:52 +03:00
E_md4hash ( r - > in . machine_password , md4_trust_password ) ;
encode_pw_buffer ( pwbuf , r - > in . machine_password , STR_UNICODE ) ;
2007-12-11 23:31:44 +03:00
generate_random_buffer ( ( uint8 * ) md5buffer , sizeof ( md5buffer ) ) ;
digested_session_key = data_blob_talloc ( mem_ctx , 0 , 16 ) ;
MD5Init ( & md5ctx ) ;
MD5Update ( & md5ctx , md5buffer , sizeof ( md5buffer ) ) ;
2008-01-04 19:01:52 +03:00
MD5Update ( & md5ctx , cli - > user_session_key . data ,
cli - > user_session_key . length ) ;
2007-12-11 23:31:44 +03:00
MD5Final ( digested_session_key . data , & md5ctx ) ;
SamOEMhashBlob ( pwbuf , sizeof ( pwbuf ) , & digested_session_key ) ;
memcpy ( & pwbuf [ 516 ] , md5buffer , sizeof ( md5buffer ) ) ;
acb_info | = ACB_PWNOEXP ;
2008-01-11 20:49:20 +03:00
if ( r - > out . domain_is_ad ) {
2007-12-11 23:31:44 +03:00
# if !defined(ENCTYPE_ARCFOUR_HMAC)
acb_info | = ACB_USE_DES_KEY_ONLY ;
# endif
; ;
}
2008-01-11 20:49:20 +03:00
2008-02-12 02:51:51 +03:00
ZERO_STRUCT ( user_info . info25 ) ;
2007-12-11 23:31:44 +03:00
2008-02-12 02:51:51 +03:00
user_info . info25 . info . fields_present = ACCT_NT_PWD_SET |
ACCT_LM_PWD_SET |
SAMR_FIELD_ACCT_FLAGS ;
user_info . info25 . info . acct_flags = acb_info ;
memcpy ( & user_info . info25 . password . data , pwbuf , sizeof ( pwbuf ) ) ;
2007-12-11 23:31:44 +03:00
2008-02-12 02:51:51 +03:00
status = rpccli_samr_SetUserInfo ( pipe_hnd , mem_ctx ,
& user_pol ,
25 ,
& user_info ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( pipe_hnd , mem_ctx , & user_pol ) ;
2007-12-11 23:31:44 +03:00
cli_rpc_pipe_close ( pipe_hnd ) ;
2007-12-18 12:16:40 +03:00
status = NT_STATUS_OK ;
2007-12-11 23:31:44 +03:00
done :
if ( cli ) {
cli_shutdown ( cli ) ;
}
2007-12-18 12:16:40 +03:00
return status ;
2007-12-11 23:31:44 +03:00
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-28 13:17:29 +03:00
NTSTATUS libnet_join_ok ( const char * netbios_domain_name ,
const char * machine_name ,
const char * dc_name )
{
uint32_t neg_flags = NETLOGON_NEG_AUTH2_FLAGS |
NETLOGON_NEG_SCHANNEL ;
/* FIXME: NETLOGON_NEG_SELECT_AUTH2_FLAGS */
struct cli_state * cli = NULL ;
struct rpc_pipe_client * pipe_hnd = NULL ;
struct rpc_pipe_client * netlogon_pipe = NULL ;
NTSTATUS status ;
char * machine_password = NULL ;
char * machine_account = NULL ;
if ( ! dc_name ) {
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ! secrets_init ( ) ) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
machine_password = secrets_fetch_machine_password ( netbios_domain_name ,
NULL , NULL ) ;
if ( ! machine_password ) {
return NT_STATUS_NO_TRUST_LSA_SECRET ;
}
asprintf ( & machine_account , " %s$ " , machine_name ) ;
if ( ! machine_account ) {
SAFE_FREE ( machine_password ) ;
return NT_STATUS_NO_MEMORY ;
}
status = cli_full_connection ( & cli , NULL ,
dc_name ,
NULL , 0 ,
" IPC$ " , " IPC " ,
machine_account ,
NULL ,
machine_password ,
0 ,
Undefined , NULL ) ;
free ( machine_account ) ;
free ( machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
status = cli_full_connection ( & cli , NULL ,
dc_name ,
NULL , 0 ,
" IPC$ " , " IPC " ,
" " ,
NULL ,
" " ,
0 ,
Undefined , NULL ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
netlogon_pipe = get_schannel_session_key ( cli ,
netbios_domain_name ,
& neg_flags , & status ) ;
if ( ! netlogon_pipe ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_NETWORK_RESPONSE ) ) {
cli_shutdown ( cli ) ;
return NT_STATUS_OK ;
}
DEBUG ( 0 , ( " libnet_join_ok: failed to get schannel session "
" key from server %s for domain %s. Error was %s \n " ,
cli - > desthost , netbios_domain_name , nt_errstr ( status ) ) ) ;
cli_shutdown ( cli ) ;
return status ;
}
if ( ! lp_client_schannel ( ) ) {
cli_shutdown ( cli ) ;
return NT_STATUS_OK ;
}
pipe_hnd = cli_rpc_pipe_open_schannel_with_key ( cli , PI_NETLOGON ,
PIPE_AUTH_LEVEL_PRIVACY ,
netbios_domain_name ,
netlogon_pipe - > dc ,
& status ) ;
cli_shutdown ( cli ) ;
if ( ! pipe_hnd ) {
DEBUG ( 0 , ( " libnet_join_ok: failed to open schannel session "
" on netlogon pipe to server %s for domain %s. "
" Error was %s \n " ,
cli - > desthost , netbios_domain_name , nt_errstr ( status ) ) ) ;
return status ;
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_join_post_verify ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
NTSTATUS status ;
status = libnet_join_ok ( r - > out . netbios_domain_name ,
r - > in . machine_name ,
r - > in . dc_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to verify domain membership after joining: %s " ,
get_friendly_nt_error_msg ( status ) ) ;
return WERR_SETUP_NOT_JOINED ;
}
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-04 19:09:21 +03:00
static bool libnet_join_unjoindomain_remove_secrets ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
if ( ! secrets_delete_machine_password_ex ( lp_workgroup ( ) ) ) {
return false ;
}
if ( ! secrets_delete_domain_sid ( lp_workgroup ( ) ) ) {
return false ;
}
return true ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-04 19:09:21 +03:00
static NTSTATUS libnet_join_unjoindomain_rpc ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
2007-12-19 13:02:39 +03:00
{
struct cli_state * cli = NULL ;
struct rpc_pipe_client * pipe_hnd = NULL ;
POLICY_HND sam_pol , domain_pol , user_pol ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
char * acct_name ;
uint32 user_rid ;
2008-02-08 16:48:55 +03:00
struct lsa_String lsa_acct_name ;
struct samr_Ids user_rids ;
struct samr_Ids name_types ;
2008-02-12 20:21:52 +03:00
union samr_UserInfo * info = NULL ;
2007-12-19 13:02:39 +03:00
2008-01-04 19:11:14 +03:00
status = cli_full_connection ( & cli , NULL ,
r - > in . dc_name ,
2007-12-19 13:02:39 +03:00
NULL , 0 ,
" IPC$ " , " IPC " ,
r - > in . admin_account ,
2008-01-04 19:01:52 +03:00
NULL ,
r - > in . admin_password ,
2007-12-19 13:02:39 +03:00
0 , Undefined , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
pipe_hnd = cli_rpc_pipe_open_noauth ( cli , PI_SAMR , & status ) ;
if ( ! pipe_hnd ) {
goto done ;
}
2008-02-04 21:43:07 +03:00
status = rpccli_samr_Connect2 ( pipe_hnd , mem_ctx ,
pipe_hnd - > cli - > desthost ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
& sam_pol ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-01 13:12:05 +03:00
status = rpccli_samr_OpenDomain ( pipe_hnd , mem_ctx ,
& sam_pol ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
r - > in . domain_sid ,
& domain_pol ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-01-11 16:42:48 +03:00
acct_name = talloc_asprintf ( mem_ctx , " %s$ " , r - > in . machine_name ) ;
2007-12-19 13:02:39 +03:00
strlower_m ( acct_name ) ;
2008-02-08 16:48:55 +03:00
init_lsa_String ( & lsa_acct_name , acct_name ) ;
status = rpccli_samr_LookupNames ( pipe_hnd , mem_ctx ,
& domain_pol ,
1 ,
& lsa_acct_name ,
& user_rids ,
& name_types ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-08 16:48:55 +03:00
if ( name_types . ids [ 0 ] ! = SID_NAME_USER ) {
2007-12-19 13:02:39 +03:00
status = NT_STATUS_INVALID_WORKSTATION ;
goto done ;
}
2008-02-08 16:48:55 +03:00
user_rid = user_rids . ids [ 0 ] ;
2007-12-19 13:02:39 +03:00
2008-02-01 13:57:53 +03:00
status = rpccli_samr_OpenUser ( pipe_hnd , mem_ctx ,
& domain_pol ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
user_rid ,
& user_pol ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-12 20:21:52 +03:00
status = rpccli_samr_QueryUserInfo ( pipe_hnd , mem_ctx ,
& user_pol ,
16 ,
& info ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( pipe_hnd , mem_ctx , & user_pol ) ;
2007-12-19 13:02:39 +03:00
goto done ;
}
2008-02-12 02:51:51 +03:00
info - > info16 . acct_flags | = ACB_DISABLED ;
2007-12-19 13:02:39 +03:00
2008-02-12 02:51:51 +03:00
status = rpccli_samr_SetUserInfo ( pipe_hnd , mem_ctx ,
& user_pol ,
16 ,
info ) ;
2007-12-19 13:02:39 +03:00
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( pipe_hnd , mem_ctx , & user_pol ) ;
2007-12-19 13:02:39 +03:00
done :
2008-01-04 13:21:53 +03:00
if ( pipe_hnd ) {
2008-01-30 14:39:20 +03:00
rpccli_samr_Close ( pipe_hnd , mem_ctx , & domain_pol ) ;
rpccli_samr_Close ( pipe_hnd , mem_ctx , & sam_pol ) ;
2008-01-04 13:21:53 +03:00
cli_rpc_pipe_close ( pipe_hnd ) ;
}
2007-12-19 13:02:39 +03:00
if ( cli ) {
cli_shutdown ( cli ) ;
}
return status ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-25 05:40:35 +03:00
static WERROR do_join_modify_vals_config ( struct libnet_JoinCtx * r )
2007-12-11 23:31:44 +03:00
{
WERROR werr ;
2008-01-13 03:40:05 +03:00
struct libnet_conf_ctx * ctx ;
werr = libnet_conf_open ( r , & ctx ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2007-12-11 23:31:44 +03:00
2007-12-14 19:37:24 +03:00
if ( ! ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) ) {
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " security " , " user " ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-12-14 19:37:24 +03:00
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " workgroup " ,
2008-01-03 16:15:05 +03:00
r - > in . domain_name ) ;
2008-01-13 03:40:05 +03:00
goto done ;
2007-12-14 19:37:24 +03:00
}
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " security " , " domain " ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-12-11 23:31:44 +03:00
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " workgroup " ,
2008-01-03 16:15:05 +03:00
r - > out . netbios_domain_name ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-12-11 23:31:44 +03:00
2008-01-11 16:41:34 +03:00
if ( r - > out . domain_is_ad ) {
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " security " , " ads " ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-12-11 23:31:44 +03:00
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " realm " ,
2008-01-12 04:24:55 +03:00
r - > out . dns_domain_name ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-12-11 23:31:44 +03:00
}
2008-02-28 13:00:50 +03:00
done :
2008-01-13 03:40:05 +03:00
libnet_conf_close ( ctx ) ;
2007-12-11 23:31:44 +03:00
return werr ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-25 05:38:06 +03:00
static WERROR do_unjoin_modify_vals_config ( struct libnet_UnjoinCtx * r )
2007-12-19 13:02:39 +03:00
{
2007-12-22 02:12:59 +03:00
WERROR werr = WERR_OK ;
2008-01-13 03:40:05 +03:00
struct libnet_conf_ctx * ctx ;
werr = libnet_conf_open ( r , & ctx ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2007-12-19 13:02:39 +03:00
if ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
2008-01-13 03:40:05 +03:00
werr = libnet_conf_set_global_parameter ( ctx , " security " , " user " ) ;
2008-02-28 13:00:50 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
libnet_conf_delete_global_parameter ( ctx , " realm " ) ;
2007-12-19 13:02:39 +03:00
}
2008-02-28 13:00:50 +03:00
done :
2008-01-13 03:40:05 +03:00
libnet_conf_close ( ctx ) ;
2007-12-19 13:02:39 +03:00
return werr ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-19 13:02:39 +03:00
2007-12-25 05:41:34 +03:00
static WERROR do_JoinConfig ( struct libnet_JoinCtx * r )
2007-12-11 23:31:44 +03:00
{
WERROR werr ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
return r - > out . result ;
}
if ( ! r - > in . modify_config ) {
return WERR_OK ;
}
2007-12-25 05:40:35 +03:00
werr = do_join_modify_vals_config ( r ) ;
2007-12-19 13:02:39 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
r - > out . modified_config = true ;
r - > out . result = werr ;
return werr ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-28 13:23:36 +03:00
static WERROR libnet_unjoin_config ( struct libnet_UnjoinCtx * r )
2007-12-19 13:02:39 +03:00
{
WERROR werr ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
return r - > out . result ;
}
if ( ! r - > in . modify_config ) {
return WERR_OK ;
}
2007-12-25 05:38:06 +03:00
werr = do_unjoin_modify_vals_config ( r ) ;
2007-12-11 23:31:44 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
r - > out . modified_config = true ;
r - > out . result = werr ;
return werr ;
}
2008-01-07 20:58:04 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-15 12:51:40 +03:00
static WERROR libnet_join_pre_processing ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
if ( ! r - > in . domain_name ) {
2008-02-28 13:26:47 +03:00
libnet_join_set_error_string ( mem_ctx , r ,
" No domain name defined " ) ;
2008-01-15 12:51:40 +03:00
return WERR_INVALID_PARAM ;
}
2008-01-16 19:05:38 +03:00
if ( r - > in . modify_config & & ! lp_config_backend_is_registry ( ) ) {
2008-01-15 12:51:40 +03:00
return WERR_NOT_SUPPORTED ;
}
if ( IS_DC ) {
return WERR_SETUP_DOMAIN_CONTROLLER ;
}
if ( ! secrets_init ( ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Unable to open secrets database " ) ;
return WERR_CAN_NOT_COMPLETE ;
}
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_join_post_processing ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
WERROR werr ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
return r - > out . result ;
}
werr = do_JoinConfig ( r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
if ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
saf_store ( r - > in . domain_name , r - > in . dc_name ) ;
}
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 20:58:04 +03:00
static int libnet_destroy_JoinCtx ( struct libnet_JoinCtx * r )
{
if ( r - > in . ads ) {
ads_destroy ( & r - > in . ads ) ;
}
return 0 ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int libnet_destroy_UnjoinCtx ( struct libnet_UnjoinCtx * r )
{
if ( r - > in . ads ) {
ads_destroy ( & r - > in . ads ) ;
}
return 0 ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-11 23:31:44 +03:00
WERROR libnet_init_JoinCtx ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * * r )
{
struct libnet_JoinCtx * ctx ;
ctx = talloc_zero ( mem_ctx , struct libnet_JoinCtx ) ;
if ( ! ctx ) {
return WERR_NOMEM ;
}
2008-01-07 20:58:04 +03:00
talloc_set_destructor ( ctx , libnet_destroy_JoinCtx ) ;
ctx - > in . machine_name = talloc_strdup ( mem_ctx , global_myname ( ) ) ;
W_ERROR_HAVE_NO_MEMORY ( ctx - > in . machine_name ) ;
2007-12-11 23:31:44 +03:00
* r = ctx ;
return WERR_OK ;
}
2008-01-07 20:58:04 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-19 13:02:39 +03:00
WERROR libnet_init_UnjoinCtx ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * * r )
{
struct libnet_UnjoinCtx * ctx ;
ctx = talloc_zero ( mem_ctx , struct libnet_UnjoinCtx ) ;
if ( ! ctx ) {
return WERR_NOMEM ;
}
2008-01-07 20:58:04 +03:00
talloc_set_destructor ( ctx , libnet_destroy_UnjoinCtx ) ;
ctx - > in . machine_name = talloc_strdup ( mem_ctx , global_myname ( ) ) ;
W_ERROR_HAVE_NO_MEMORY ( ctx - > in . machine_name ) ;
2007-12-19 13:02:39 +03:00
* r = ctx ;
return WERR_OK ;
}
2008-01-07 21:07:38 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_DomainJoin ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
NTSTATUS status ;
2008-01-12 04:10:17 +03:00
# ifdef WITH_ADS
2008-01-07 21:07:38 +03:00
ADS_STATUS ads_status ;
2008-01-12 04:22:44 +03:00
# endif /* WITH_ADS */
2008-01-07 21:07:38 +03:00
2008-01-12 04:22:44 +03:00
if ( ! r - > in . dc_name ) {
struct DS_DOMAIN_CONTROLLER_INFO * info ;
status = dsgetdcname ( mem_ctx ,
r - > in . domain_name ,
NULL ,
NULL ,
DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
DS_RETURN_DNS_NAME ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
2008-01-16 12:48:11 +03:00
" failed to find DC for domain %s " ,
r - > in . domain_name ,
get_friendly_nt_error_msg ( status ) ) ;
2008-01-12 04:22:44 +03:00
return WERR_DOMAIN_CONTROLLER_NOT_FOUND ;
}
r - > in . dc_name = talloc_strdup ( mem_ctx ,
info - > domain_controller_name ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > in . dc_name ) ;
}
# ifdef WITH_ADS
2008-01-07 21:07:38 +03:00
if ( r - > in . account_ou ) {
2008-01-12 04:22:44 +03:00
2008-01-07 21:07:38 +03:00
ads_status = libnet_join_connect_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
2008-01-12 04:19:21 +03:00
return WERR_DEFAULT_JOIN_REQUIRED ;
2008-01-07 21:07:38 +03:00
}
2008-01-12 04:22:44 +03:00
2008-01-07 21:07:38 +03:00
ads_status = libnet_join_precreate_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to precreate account in ou %s: %s " ,
2008-01-07 21:07:38 +03:00
r - > in . account_ou ,
ads_errstr ( ads_status ) ) ;
2008-01-12 04:19:21 +03:00
return WERR_DEFAULT_JOIN_REQUIRED ;
2008-01-07 21:07:38 +03:00
}
r - > in . join_flags & = ~ WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ;
}
2008-01-12 04:10:17 +03:00
# endif /* WITH_ADS */
2008-01-12 04:20:33 +03:00
2008-01-07 21:07:38 +03:00
status = libnet_join_joindomain_rpc ( mem_ctx , r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-12 04:20:33 +03:00
libnet_join_set_error_string ( mem_ctx , r ,
" failed to join domain over rpc: %s " ,
2008-01-16 12:48:11 +03:00
get_friendly_nt_error_msg ( status ) ) ;
2008-01-07 21:07:38 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_USER_EXISTS ) ) {
return WERR_SETUP_ALREADY_JOINED ;
}
return ntstatus_to_werror ( status ) ;
}
if ( ! libnet_join_joindomain_store_secrets ( mem_ctx , r ) ) {
return WERR_SETUP_NOT_JOINED ;
}
2008-01-12 04:10:17 +03:00
# ifdef WITH_ADS
2008-01-12 04:15:42 +03:00
if ( r - > out . domain_is_ad ) {
ads_status = libnet_join_post_processing_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
return WERR_GENERAL_FAILURE ;
}
2008-01-08 20:59:57 +03:00
}
2008-01-12 04:10:17 +03:00
# endif /* WITH_ADS */
2008-01-10 01:15:56 +03:00
2008-01-07 21:07:38 +03:00
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-11 23:31:44 +03:00
WERROR libnet_Join ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
WERROR werr ;
2008-01-15 19:00:14 +03:00
if ( r - > in . debug ) {
2008-01-16 12:37:48 +03:00
LIBNET_JOIN_IN_DUMP_CTX ( mem_ctx , r ) ;
2008-01-15 19:00:14 +03:00
}
2008-01-15 12:51:40 +03:00
werr = libnet_join_pre_processing ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
2007-12-22 01:04:26 +03:00
}
2007-12-14 19:37:24 +03:00
if ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
2008-01-07 21:07:38 +03:00
werr = libnet_DomainJoin ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-01-15 12:51:40 +03:00
goto done ;
2008-01-04 19:09:21 +03:00
}
2008-02-28 13:17:29 +03:00
werr = libnet_join_post_verify ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2007-12-14 19:37:24 +03:00
}
2008-01-15 12:51:40 +03:00
werr = libnet_join_post_processing ( mem_ctx , r ) ;
2007-12-11 23:31:44 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-01-15 12:51:40 +03:00
goto done ;
2007-12-11 23:31:44 +03:00
}
2008-01-15 12:51:40 +03:00
done :
2008-01-16 12:37:48 +03:00
r - > out . result = werr ;
2008-01-15 19:00:14 +03:00
if ( r - > in . debug ) {
2008-01-16 12:37:48 +03:00
LIBNET_JOIN_OUT_DUMP_CTX ( mem_ctx , r ) ;
2008-01-15 19:00:14 +03:00
}
2007-12-11 23:31:44 +03:00
return werr ;
}
2007-12-19 13:02:39 +03:00
2008-01-07 21:11:26 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_DomainUnjoin ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
NTSTATUS status ;
2008-01-16 12:56:40 +03:00
if ( ! r - > in . domain_sid ) {
struct dom_sid sid ;
if ( ! secrets_fetch_domain_sid ( lp_workgroup ( ) , & sid ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" Unable to fetch domain sid: are we joined? " ) ;
return WERR_SETUP_NOT_JOINED ;
}
r - > in . domain_sid = sid_dup_talloc ( mem_ctx , & sid ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > in . domain_sid ) ;
}
2008-01-15 12:58:27 +03:00
if ( ! r - > in . dc_name ) {
struct DS_DOMAIN_CONTROLLER_INFO * info ;
status = dsgetdcname ( mem_ctx ,
r - > in . domain_name ,
NULL ,
NULL ,
DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
DS_RETURN_DNS_NAME ,
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
2008-01-16 12:48:11 +03:00
" failed to find DC for domain %s " ,
r - > in . domain_name ,
get_friendly_nt_error_msg ( status ) ) ;
2008-01-15 12:58:27 +03:00
return WERR_DOMAIN_CONTROLLER_NOT_FOUND ;
}
r - > in . dc_name = talloc_strdup ( mem_ctx ,
info - > domain_controller_name ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > in . dc_name ) ;
}
2008-01-07 21:11:26 +03:00
status = libnet_join_unjoindomain_rpc ( mem_ctx , r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-08 13:46:11 +03:00
libnet_unjoin_set_error_string ( mem_ctx , r ,
2008-01-16 12:48:11 +03:00
" failed to disable machine account via rpc: %s " ,
get_friendly_nt_error_msg ( status ) ) ;
2008-01-07 21:11:26 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NO_SUCH_USER ) ) {
return WERR_SETUP_NOT_JOINED ;
}
return ntstatus_to_werror ( status ) ;
}
2008-02-28 13:19:57 +03:00
r - > out . disabled_machine_account = true ;
2008-01-12 04:10:17 +03:00
# ifdef WITH_ADS
2008-01-07 21:11:26 +03:00
if ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ) {
ADS_STATUS ads_status ;
libnet_unjoin_connect_ads ( mem_ctx , r ) ;
ads_status = libnet_unjoin_remove_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
2008-01-11 17:03:31 +03:00
" failed to remove machine account from AD: %s " ,
2008-01-07 21:11:26 +03:00
ads_errstr ( ads_status ) ) ;
2008-02-28 13:19:57 +03:00
} else {
r - > out . deleted_machine_account = true ;
/* dirty hack */
r - > out . dns_domain_name = talloc_strdup ( mem_ctx ,
r - > in . ads - > server . realm ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > out . dns_domain_name ) ;
2008-01-07 21:11:26 +03:00
}
}
2008-01-12 04:10:17 +03:00
# endif /* WITH_ADS */
2008-01-07 21:11:26 +03:00
libnet_join_unjoindomain_remove_secrets ( mem_ctx , r ) ;
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-15 12:51:40 +03:00
static WERROR libnet_unjoin_pre_processing ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
2008-02-28 13:26:47 +03:00
if ( ! r - > in . domain_name ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" No domain name defined " ) ;
return WERR_INVALID_PARAM ;
}
2008-01-16 19:05:38 +03:00
if ( r - > in . modify_config & & ! lp_config_backend_is_registry ( ) ) {
2008-01-15 12:51:40 +03:00
return WERR_NOT_SUPPORTED ;
}
if ( ! secrets_init ( ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" Unable to open secrets database " ) ;
return WERR_CAN_NOT_COMPLETE ;
}
return WERR_OK ;
}
2008-02-28 13:23:36 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_unjoin_post_processing ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
saf_delete ( r - > out . netbios_domain_name ) ;
saf_delete ( r - > out . dns_domain_name ) ;
return libnet_unjoin_config ( r ) ;
}
2008-01-16 12:48:11 +03:00
2008-01-15 12:51:40 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-19 13:02:39 +03:00
WERROR libnet_Unjoin ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r )
{
WERROR werr ;
2008-01-15 19:00:14 +03:00
if ( r - > in . debug ) {
2008-01-16 12:37:48 +03:00
LIBNET_UNJOIN_IN_DUMP_CTX ( mem_ctx , r ) ;
2008-01-15 19:00:14 +03:00
}
2008-01-15 12:51:40 +03:00
werr = libnet_unjoin_pre_processing ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
2007-12-19 13:02:39 +03:00
}
if ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
2008-01-07 21:11:26 +03:00
werr = libnet_DomainUnjoin ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-02-28 13:23:36 +03:00
libnet_unjoin_config ( r ) ;
2008-01-15 12:51:40 +03:00
goto done ;
2007-12-19 13:02:39 +03:00
}
}
2008-02-28 13:23:36 +03:00
werr = libnet_unjoin_post_processing ( mem_ctx , r ) ;
2007-12-19 13:02:39 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-01-15 12:51:40 +03:00
goto done ;
2007-12-19 13:02:39 +03:00
}
2008-01-15 12:51:40 +03:00
done :
2008-01-16 12:37:48 +03:00
r - > out . result = werr ;
2008-01-15 19:00:14 +03:00
if ( r - > in . debug ) {
2008-01-16 12:37:48 +03:00
LIBNET_UNJOIN_OUT_DUMP_CTX ( mem_ctx , r ) ;
2008-01-15 19:00:14 +03:00
}
2007-12-19 13:02:39 +03:00
return werr ;
}