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"
2010-07-02 02:32:52 +04:00
# include "ads.h"
2010-07-02 02:14:04 +04:00
# include "librpc/gen_ndr/ndr_libnet_join.h"
# include "libnet/libnet_join.h"
2009-03-17 12:06:46 +03:00
# include "libcli/auth/libcli_auth.h"
2011-01-17 17:19:18 +03:00
# include "../librpc/gen_ndr/ndr_samr_c.h"
2010-05-18 20:59:45 +04:00
# include "rpc_client/init_samr.h"
2011-01-18 16:55:48 +03:00
# include "../librpc/gen_ndr/ndr_lsa_c.h"
2010-05-18 20:26:16 +04:00
# include "rpc_client/cli_lsarpc.h"
2011-01-12 13:21:18 +03:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2010-05-18 20:26:03 +04:00
# include "rpc_client/cli_netlogon.h"
2010-05-18 04:27:34 +04:00
# include "lib/smbconf/smbconf.h"
# include "lib/smbconf/smbconf_reg.h"
2010-07-01 01:38:57 +04:00
# include "../libds/common/flags.h"
2010-08-05 04:25:37 +04:00
# include "secrets.h"
2010-08-20 01:15:22 +04:00
# include "rpc_client/init_lsa.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-03-18 20:58:37 +03:00
# include "passdb.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2012-05-19 19:15:23 +04:00
# include "../libcli/smb/smbXcli_base.h"
2012-07-23 06:47:01 +04:00
# include "lib/param/loadparm.h"
2013-09-02 21:32:23 +04:00
# include "libcli/auth/netlogon_creds_cli.h"
# include "auth/credentials/credentials.h"
2016-03-02 20:07:53 +03:00
# include "krb5_env.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 ) ) ; \
2008-03-04 13:07:13 +03:00
TALLOC_FREE ( str ) ; \
2008-01-16 12:37:48 +03:00
} 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 ) ) ; \
2008-03-04 13:07:13 +03:00
TALLOC_FREE ( str ) ; \
2008-01-16 12:37:48 +03:00
} 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 )
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-08 07:18:31 +03:00
static void libnet_join_set_error_string ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
const char * format , . . . )
PRINTF_ATTRIBUTE ( 3 , 4 ) ;
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 ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-08 07:18:31 +03:00
static void libnet_unjoin_set_error_string ( TALLOC_CTX * mem_ctx ,
struct libnet_UnjoinCtx * r ,
const char * format , . . . )
PRINTF_ATTRIBUTE ( 3 , 4 ) ;
2008-01-07 20:46:07 +03:00
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 ) ;
}
2011-02-11 13:14:57 +03:00
# ifdef HAVE_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 ,
2016-03-02 20:07:53 +03:00
const char * ccname ,
2008-01-07 20:58:04 +03:00
ADS_STRUCT * * ads )
{
ADS_STATUS status ;
ADS_STRUCT * my_ads = NULL ;
2010-08-13 01:51:02 +04:00
char * cp ;
2008-01-07 20:58:04 +03:00
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 ) ;
2010-08-13 01:51:02 +04:00
if ( ( cp = strchr_m ( my_ads - > auth . user_name , ' @ ' ) ) ! = 0 ) {
* cp + + = ' \0 ' ;
SAFE_FREE ( my_ads - > auth . realm ) ;
my_ads - > auth . realm = smb_xstrdup ( cp ) ;
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( my_ads - > auth . realm ) ) {
ads_destroy ( & my_ads ) ;
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2010-08-13 01:51:02 +04:00
}
2008-01-07 20:58:04 +03:00
}
if ( password ) {
SAFE_FREE ( my_ads - > auth . password ) ;
my_ads - > auth . password = SMB_STRDUP ( password ) ;
}
2016-03-02 20:07:53 +03:00
if ( ccname ! = NULL ) {
SAFE_FREE ( my_ads - > auth . ccache_name ) ;
my_ads - > auth . ccache_name = SMB_STRDUP ( ccname ) ;
setenv ( KRB5_ENV_CCNAME , my_ads - > auth . ccache_name , 1 ) ;
}
2008-06-24 15:06:38 +04:00
status = ads_connect_user_creds ( my_ads ) ;
2008-01-07 20:58:04 +03:00
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 ,
2016-03-02 20:07:53 +03:00
struct libnet_JoinCtx * r ,
bool use_machine_creds )
2008-01-07 20:58:04 +03:00
{
ADS_STATUS status ;
2016-03-02 20:07:53 +03:00
const char * username ;
const char * password ;
const char * ccname = NULL ;
if ( use_machine_creds ) {
if ( r - > in . machine_name = = NULL | |
r - > in . machine_password = = NULL ) {
return ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
}
username = talloc_strdup ( mem_ctx , r - > in . machine_name ) ;
if ( username = = NULL ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
if ( username [ strlen ( username ) ] ! = ' $ ' ) {
username = talloc_asprintf ( username , " %s$ " , username ) ;
if ( username = = NULL ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
}
password = r - > in . machine_password ;
ccname = " MEMORY:libnet_join_machine_creds " ;
} else {
username = r - > in . admin_account ;
password = r - > in . admin_password ;
/*
* when r - > in . use_kerberos is set to allow " net ads join -k " we
* may not override the provided credential cache - gd
*/
if ( ! r - > in . use_kerberos ) {
ccname = " MEMORY:libnet_join_user_creds " ;
}
}
2008-01-07 20:58:04 +03:00
2008-04-22 03:54:49 +04:00
status = libnet_connect_ads ( r - > out . dns_domain_name ,
r - > out . netbios_domain_name ,
2008-01-07 20:58:04 +03:00
r - > in . dc_name ,
2016-03-02 20:07:53 +03:00
username ,
password ,
ccname ,
2008-01-07 20:58:04 +03:00
& 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 ) ) ;
2008-02-28 13:29:56 +03:00
return status ;
}
if ( ! r - > out . netbios_domain_name ) {
r - > out . netbios_domain_name = talloc_strdup ( mem_ctx ,
r - > in . ads - > server . workgroup ) ;
ADS_ERROR_HAVE_NO_MEMORY ( r - > out . netbios_domain_name ) ;
2008-01-07 20:58:04 +03:00
}
2008-02-28 13:29:56 +03:00
if ( ! r - > out . dns_domain_name ) {
r - > out . dns_domain_name = talloc_strdup ( mem_ctx ,
r - > in . ads - > config . realm ) ;
ADS_ERROR_HAVE_NO_MEMORY ( r - > out . dns_domain_name ) ;
}
r - > out . domain_is_ad = true ;
return ADS_SUCCESS ;
2008-01-07 20:58:04 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-02 20:07:53 +03:00
static ADS_STATUS libnet_join_connect_ads_user ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
return libnet_join_connect_ads ( mem_ctx , r , false ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-12 01:15:06 +03:00
2016-03-02 20:07:53 +03:00
static ADS_STATUS libnet_join_connect_ads_machine ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
return libnet_join_connect_ads ( mem_ctx , r , true ) ;
}
2016-03-12 01:15:06 +03:00
2016-03-02 20:07:53 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-07 20:58:04 +03:00
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 ,
2016-03-02 20:07:53 +03:00
NULL ,
2008-01-07 20:58:04 +03:00
& 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-02-28 21:44:34 +03:00
join a domain using ADS ( LDAP mods )
2008-01-07 20:58:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 } ;
2008-02-28 21:44:34 +03:00
bool moved = false ;
2008-01-07 21:07:38 +03:00
2008-05-15 01:50:25 +04:00
status = ads_check_ou_dn ( mem_ctx , r - > in . ads , & r - > in . account_ou ) ;
2008-03-28 18:39:02 +03:00
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
2008-01-07 21:07:38 +03:00
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 ) ;
}
2008-02-28 21:44:34 +03:00
ads_msgfree ( r - > in . ads , res ) ;
/* Attempt to create the machine account and bail if this fails.
Assume that the admin wants exactly what they requested */
2008-01-07 21:07:38 +03:00
status = ads_create_machine_acct ( r - > in . ads ,
r - > in . machine_name ,
2016-03-11 18:04:52 +03:00
r - > in . account_ou ,
r - > in . desired_encryption_types ) ;
2008-01-07 21:07:38 +03:00
2008-02-28 21:44:34 +03:00
if ( ADS_ERR_OK ( status ) ) {
DEBUG ( 1 , ( " machine account creation created \n " ) ) ;
return status ;
} else if ( ( status . error_type = = ENUM_ADS_ERROR_LDAP ) & &
( status . err . rc = = LDAP_ALREADY_EXISTS ) ) {
2008-01-07 21:07:38 +03:00
status = ADS_SUCCESS ;
}
2008-02-28 21:44:34 +03:00
if ( ! ADS_ERR_OK ( status ) ) {
DEBUG ( 1 , ( " machine account creation failed \n " ) ) ;
return status ;
}
status = ads_move_machine_acct ( r - > in . ads ,
r - > in . machine_name ,
r - > in . account_ou ,
& moved ) ;
if ( ! ADS_ERR_OK ( status ) ) {
DEBUG ( 1 , ( " failure to locate/move pre-existing "
" machine account \n " ) ) ;
return status ;
}
DEBUG ( 1 , ( " The machine account %s the specified OU. \n " ,
moved ? " was moved into " : " already exists in " ) ) ;
2008-01-07 21:07:38 +03:00
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 ) {
2009-06-23 00:35:58 +04:00
status = libnet_unjoin_connect_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" failed to connect to AD: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
2008-01-07 21:11:26 +03:00
}
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 ;
}
2009-03-18 09:35:03 +03:00
dn = ads_get_dn ( r - > in . ads , mem_ctx , res ) ;
2008-01-07 21:31:20 +03:00
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 ;
}
2016-03-11 18:05:53 +03:00
if ( ! ads_pull_uint32 ( r - > in . ads , res , " msDS-SupportedEncryptionTypes " ,
& r - > out . set_encryption_types ) ) {
r - > out . set_encryption_types = 0 ;
}
2008-01-07 21:31:20 +03:00
done :
ads_msgfree ( r - > in . ads , res ) ;
2009-03-18 09:35:03 +03:00
TALLOC_FREE ( dn ) ;
2008-01-07 21:31:20 +03:00
return status ;
}
2014-09-26 05:09:08 +04:00
static ADS_STATUS libnet_join_get_machine_spns ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
char * * * spn_array ,
size_t * num_spns )
{
ADS_STATUS status ;
if ( r - > in . machine_name = = NULL ) {
return ADS_ERROR_SYSTEM ( EINVAL ) ;
}
status = ads_get_service_principal_names ( mem_ctx ,
r - > in . ads ,
r - > in . machine_name ,
spn_array ,
num_spns ) ;
return status ;
}
2008-01-07 21:31:20 +03:00
/****************************************************************
2008-02-28 21:44:34 +03:00
Set a machines dNSHostName and servicePrincipalName attributes
2008-01-07 21:31:20 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ;
2014-09-26 05:35:43 +04:00
const char * * spn_array = NULL ;
size_t num_spns = 0 ;
2008-01-07 22:16:57 +03:00
char * spn = NULL ;
2014-09-26 05:35:43 +04:00
bool ok ;
2016-04-26 18:21:46 +03:00
const char * * netbios_aliases = NULL ;
2008-01-07 22:16:57 +03:00
2008-02-28 21:44:34 +03:00
/* Find our DN */
2008-01-07 22:16:57 +03:00
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
2014-09-26 05:35:43 +04:00
status = libnet_join_get_machine_spns ( mem_ctx ,
r ,
discard_const_p ( char * * , & spn_array ) ,
& num_spns ) ;
if ( ! ADS_ERR_OK ( status ) ) {
DEBUG ( 5 , ( " Retrieving the servicePrincipalNames failed. \n " ) ) ;
}
2008-02-28 21:44:34 +03:00
/* Windows only creates HOST/shortname & HOST/fqdn. */
2008-01-07 22:16:57 +03:00
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , r - > in . machine_name ) ;
if ( ! spn ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( spn ) ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2014-09-26 05:35:43 +04:00
ok = ads_element_in_array ( spn_array , num_spns , spn ) ;
if ( ! ok ) {
ok = add_string_to_array ( spn_array , spn ,
2014-11-14 16:12:26 +03:00
& spn_array , & num_spns ) ;
2014-09-26 05:35:43 +04:00
if ( ! ok ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
}
2008-01-07 22:16:57 +03:00
2008-10-06 16:49:10 +04:00
if ( ! name_to_fqdn ( my_fqdn , r - > in . machine_name )
| | ( strchr ( my_fqdn , ' . ' ) = = NULL ) ) {
fstr_sprintf ( my_fqdn , " %s.%s " , r - > in . machine_name ,
r - > out . dns_domain_name ) ;
}
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( my_fqdn ) ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2008-01-07 22:16:57 +03:00
2008-10-06 16:49:10 +04:00
if ( ! strequal ( my_fqdn , r - > in . machine_name ) ) {
2008-01-07 22:16:57 +03:00
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , my_fqdn ) ;
if ( ! spn ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2014-09-26 05:35:43 +04:00
ok = ads_element_in_array ( spn_array , num_spns , spn ) ;
if ( ! ok ) {
ok = add_string_to_array ( spn_array , spn ,
2014-11-14 16:12:26 +03:00
& spn_array , & num_spns ) ;
2014-09-26 05:35:43 +04:00
if ( ! ok ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
}
}
2016-04-26 18:21:46 +03:00
netbios_aliases = lp_netbios_aliases ( ) ;
if ( netbios_aliases ! = NULL ) {
for ( ; * netbios_aliases ! = NULL ; netbios_aliases + + ) {
/*
* Add HOST / NETBIOSNAME
*/
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , * netbios_aliases ) ;
if ( spn = = NULL ) {
TALLOC_FREE ( spn ) ;
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
if ( ! strupper_m ( spn ) ) {
TALLOC_FREE ( spn ) ;
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
ok = ads_element_in_array ( spn_array , num_spns , spn ) ;
if ( ok ) {
TALLOC_FREE ( spn ) ;
continue ;
}
ok = add_string_to_array ( spn_array , spn ,
& spn_array , & num_spns ) ;
if ( ! ok ) {
TALLOC_FREE ( spn ) ;
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
TALLOC_FREE ( spn ) ;
/*
* Add HOST / netbiosname . domainname
*/
if ( r - > out . dns_domain_name = = NULL ) {
continue ;
}
fstr_sprintf ( my_fqdn , " %s.%s " ,
* netbios_aliases ,
r - > out . dns_domain_name ) ;
spn = talloc_asprintf ( mem_ctx , " HOST/%s " , my_fqdn ) ;
if ( spn = = NULL ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
ok = ads_element_in_array ( spn_array , num_spns , spn ) ;
if ( ok ) {
TALLOC_FREE ( spn ) ;
continue ;
}
ok = add_string_to_array ( spn_array , spn ,
& spn_array , & num_spns ) ;
if ( ! ok ) {
TALLOC_FREE ( spn ) ;
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
TALLOC_FREE ( spn ) ;
}
}
2014-09-26 05:35:43 +04:00
/* make sure to NULL terminate the array */
spn_array = talloc_realloc ( mem_ctx , spn_array , const char * , num_spns + 1 ) ;
if ( spn_array = = NULL ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
2008-01-07 22:16:57 +03:00
}
2014-09-26 05:35:43 +04:00
spn_array [ num_spns ] = NULL ;
2008-01-07 22:16:57 +03:00
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2008-02-28 21:44:34 +03:00
/* fields of primary importance */
2008-01-07 22:16:57 +03:00
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 ;
}
2008-02-28 21:44:34 +03:00
/* Find our DN */
2008-01-07 22:16:57 +03:00
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
if ( ! r - > in . upn ) {
2013-11-15 20:02:20 +04:00
const char * realm = r - > out . dns_domain_name ;
2013-11-06 21:21:32 +04:00
/* in case we are about to generate a keytab during the join
* make sure the default upn we create is usable with kinit - k .
* gd */
if ( USE_KERBEROS_KEYTAB ) {
realm = talloc_strdup_upper ( mem_ctx ,
r - > out . dns_domain_name ) ;
}
if ( ! realm ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2008-01-07 22:16:57 +03:00
r - > in . upn = talloc_asprintf ( mem_ctx ,
" host/%s@%s " ,
r - > in . machine_name ,
2013-11-06 21:21:32 +04:00
realm ) ;
2008-01-07 22:16:57 +03:00
if ( ! r - > in . upn ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
}
2008-02-28 21:44:34 +03:00
/* now do the mods */
2008-01-07 22:16:57 +03:00
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR_LDAP ( LDAP_NO_MEMORY ) ;
}
2008-02-28 21:44:34 +03:00
/* fields of primary importance */
2008-01-07 22:16:57 +03:00
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 ;
}
2008-02-28 21:44:34 +03:00
/* Find our DN */
2008-01-07 22:16:57 +03:00
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
2008-02-28 21:44:34 +03:00
/* now do the mods */
2008-01-07 22:16:57 +03:00
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2014-10-02 19:13:18 +04:00
if ( r - > in . os_servicepack ) {
/*
* if blank string then leave os_sp equal to NULL to force
* attribute delete ( LDAP_MOD_DELETE )
*/
if ( ! strequal ( r - > in . os_servicepack , " " ) ) {
os_sp = talloc_strdup ( mem_ctx , r - > in . os_servicepack ) ;
}
} else {
os_sp = talloc_asprintf ( mem_ctx , " Samba %s " ,
samba_version_string ( ) ) ;
}
if ( ! os_sp & & ! strequal ( r - > in . os_servicepack , " " ) ) {
2008-01-07 22:16:57 +03:00
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2008-02-28 21:44:34 +03:00
/* fields of primary importance */
2008-01-07 22:16:57 +03:00
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 ) ;
}
2016-03-12 01:14:13 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-12 01:15:06 +03:00
2016-03-12 01:14:13 +03:00
static ADS_STATUS libnet_join_set_etypes ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
ADS_STATUS status ;
ADS_MODLIST mods ;
const char * etype_list_str ;
2016-03-11 18:04:52 +03:00
etype_list_str = talloc_asprintf ( mem_ctx , " %d " ,
r - > in . desired_encryption_types ) ;
2016-03-12 01:14:13 +03:00
if ( ! etype_list_str ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
/* Find our DN */
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
2016-03-11 18:05:53 +03:00
if ( r - > in . desired_encryption_types = = r - > out . set_encryption_types ) {
return ADS_SUCCESS ;
}
2016-03-12 01:14:13 +03:00
/* now do the mods */
mods = ads_init_mods ( mem_ctx ) ;
if ( ! mods ) {
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
status = ads_mod_str ( mem_ctx , & mods , " msDS-SupportedEncryptionTypes " ,
etype_list_str ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
2016-03-11 18:05:53 +03:00
status = ads_gen_mod ( r - > in . ads , r - > out . dn , mods ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
r - > out . set_encryption_types = r - > in . desired_encryption_types ;
return ADS_SUCCESS ;
2016-03-12 01:14:13 +03:00
}
2016-03-12 01:15:06 +03:00
2008-01-07 22:16:57 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool libnet_join_create_keytab ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
2009-01-16 04:02:41 +03:00
if ( ! USE_SYSTEM_KEYTAB ) {
2008-01-07 22:16:57 +03:00
return true ;
}
2008-01-12 04:10:17 +03:00
2008-07-03 14:01:36 +04:00
if ( ads_keytab_create_default ( r - > in . ads ) ! = 0 ) {
2008-01-07 22:16:57 +03:00
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 ;
}
2008-02-28 21:44:34 +03:00
/* go ahead and setup the default salt */
2008-01-08 20:59:57 +03:00
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 ) ;
2008-02-28 21:44:34 +03:00
/* if it's a Windows functional domain, we have to look for the UPN */
2008-01-08 20:59:57 +03:00
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 ;
2016-03-12 01:15:06 +03:00
bool need_etype_update = false ;
2008-01-12 04:15:42 +03:00
2008-02-28 13:02:01 +03:00
if ( ! r - > in . ads ) {
2016-03-02 20:07:53 +03:00
status = libnet_join_connect_ads_user ( mem_ctx , r ) ;
2008-02-28 13:02:01 +03:00
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 ,
2014-07-02 15:25:12 +04:00
" Failed to set machine spn: %s \n "
" Do you have sufficient permissions to create machine "
" accounts? " ,
2008-01-12 04:15:42 +03:00
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 ;
}
2016-03-12 01:15:06 +03:00
status = libnet_join_find_machine_acct ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
if ( r - > in . desired_encryption_types ! = r - > out . set_encryption_types ) {
uint32_t func_level = 0 ;
status = ads_domain_func_level ( r - > in . ads , & func_level ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to query domain controller functional level: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
if ( func_level > = DS_DOMAIN_FUNCTION_2008 ) {
need_etype_update = true ;
}
}
if ( need_etype_update ) {
/*
* We need to reconnect as machine account in order
* to update msDS - SupportedEncryptionTypes reliable
*/
if ( r - > in . ads - > auth . ccache_name ! = NULL ) {
ads_kdestroy ( r - > in . ads - > auth . ccache_name ) ;
}
ads_destroy ( & r - > in . ads ) ;
status = libnet_join_connect_ads_machine ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to connect as machine account: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
status = libnet_join_set_etypes ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to set machine kerberos encryption types: %s " ,
ads_errstr ( status ) ) ;
return status ;
}
}
2008-01-12 04:15:42 +03:00
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 ;
}
2011-02-11 13:14:57 +03:00
# endif /* HAVE_ADS */
2008-01-08 20:59:57 +03:00
2008-01-07 22:16:57 +03:00
/****************************************************************
2008-02-28 21:44:34 +03:00
Store the machine password and domain SID
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 ) )
{
2008-02-28 21:44:34 +03:00
DEBUG ( 1 , ( " Failed to save domain sid \n " ) ) ;
2008-01-04 19:09:21 +03:00
return false ;
}
if ( ! secrets_store_machine_password ( r - > in . machine_password ,
r - > out . netbios_domain_name ,
2008-03-04 21:04:54 +03:00
r - > in . secure_channel_type ) )
2008-01-04 19:09:21 +03:00
{
2008-02-28 21:44:34 +03:00
DEBUG ( 1 , ( " Failed to save machine password \n " ) ) ;
2008-01-04 19:09:21 +03:00
return false ;
}
return true ;
}
2008-07-30 23:38:21 +04:00
/****************************************************************
Connect dc ' s IPC $ share
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS libnet_join_connect_dc_ipc ( const char * dc ,
const char * user ,
2008-09-24 13:05:37 +04:00
const char * domain ,
2008-07-30 23:38:21 +04:00
const char * pass ,
bool use_kerberos ,
struct cli_state * * cli )
{
int flags = 0 ;
if ( use_kerberos ) {
flags | = CLI_FULL_CONNECTION_USE_KERBEROS ;
}
if ( use_kerberos & & pass ) {
flags | = CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS ;
}
return cli_full_connection ( cli , NULL ,
dc ,
NULL , 0 ,
" IPC$ " , " IPC " ,
user ,
2008-09-24 13:05:37 +04:00
domain ,
2008-07-30 23:38:21 +04:00
pass ,
flags ,
2015-12-16 12:03:52 +03:00
SMB_SIGNING_IPC_DEFAULT ) ;
2008-07-30 23:38:21 +04:00
}
2008-01-07 21:07:38 +03:00
/****************************************************************
2008-04-15 00:56:12 +04:00
Lookup domain dc ' s info
2008-01-07 21:07:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-15 00:56:12 +04:00
static NTSTATUS libnet_join_lookup_dc_rpc ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
struct cli_state * * cli )
2007-12-11 23:31:44 +03:00
{
struct rpc_pipe_client * pipe_hnd = NULL ;
2009-03-19 00:49:41 +03:00
struct policy_handle lsa_pol ;
2011-01-18 16:55:48 +03:00
NTSTATUS status , result ;
2008-02-08 03:57:55 +03:00
union lsa_PolicyInformation * info = NULL ;
2011-01-18 16:55:48 +03:00
struct dcerpc_binding_handle * b ;
2007-12-11 23:31:44 +03:00
2008-07-30 23:38:21 +04:00
status = libnet_join_connect_dc_ipc ( r - > in . dc_name ,
r - > in . admin_account ,
2008-09-24 13:05:37 +04:00
r - > in . admin_domain ,
2008-07-30 23:38:21 +04:00
r - > in . admin_password ,
r - > in . use_kerberos ,
cli ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2013-05-24 15:29:28 +04:00
status = cli_rpc_pipe_open_noauth ( * cli , & ndr_table_lsarpc ,
2008-07-20 13:04:31 +04:00
& pipe_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 21:44:34 +03:00
DEBUG ( 0 , ( " Error connecting to LSA pipe. Error was %s \n " ,
nt_errstr ( status ) ) ) ;
2007-12-11 23:31:44 +03:00
goto done ;
}
2011-01-18 16:55:48 +03:00
b = pipe_hnd - > binding_handle ;
2008-02-29 03:25:45 +03:00
status = rpccli_lsa_open_policy ( pipe_hnd , mem_ctx , true ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED , & lsa_pol ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-18 16:55:48 +03:00
status = dcerpc_lsa_QueryInfoPolicy2 ( b , mem_ctx ,
2008-02-08 03:57:55 +03:00
& lsa_pol ,
LSA_POLICY_INFO_DNS ,
2011-01-18 16:55:48 +03:00
& info ,
& result ) ;
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( result ) ) {
2008-01-11 16:41:34 +03:00
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 ;
2008-05-16 14:16:04 +04:00
r - > out . forest_name = info - > dns . dns_forest . string ;
2010-08-26 19:21:39 +04:00
r - > out . domain_sid = dom_sid_dup ( mem_ctx , info - > dns . sid ) ;
2008-06-04 20:05:15 +04:00
NT_STATUS_HAVE_NO_MEMORY ( r - > out . domain_sid ) ;
2008-01-11 16:41:34 +03:00
}
2007-12-18 12:31:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-18 16:55:48 +03:00
status = dcerpc_lsa_QueryInfoPolicy ( b , mem_ctx ,
2008-02-08 12:21:25 +03:00
& lsa_pol ,
LSA_POLICY_INFO_ACCOUNT_DOMAIN ,
2011-01-18 16:55:48 +03:00
& info ,
& result ) ;
2007-12-18 12:31:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-18 16:55:48 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2008-02-08 12:21:25 +03:00
r - > out . netbios_domain_name = info - > account_domain . name . string ;
2010-08-26 19:21:39 +04:00
r - > out . domain_sid = dom_sid_dup ( mem_ctx , info - > account_domain . sid ) ;
2008-06-04 20:05:15 +04:00
NT_STATUS_HAVE_NO_MEMORY ( r - > out . domain_sid ) ;
2007-12-18 12:31:12 +03:00
}
2011-01-18 16:55:48 +03:00
dcerpc_lsa_Close ( b , mem_ctx , & lsa_pol , & result ) ;
2008-04-20 15:51:46 +04:00
TALLOC_FREE ( pipe_hnd ) ;
2007-12-11 23:31:44 +03:00
2008-04-15 00:56:12 +04:00
done :
return status ;
}
2008-11-06 14:26:24 +03:00
/****************************************************************
Do the domain join unsecure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS libnet_join_joindomain_rpc_unsecure ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
struct cli_state * cli )
{
2013-09-05 22:57:02 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct rpc_pipe_client * netlogon_pipe = NULL ;
struct netlogon_creds_cli_context * netlogon_creds = NULL ;
struct samr_Password current_nt_hash ;
const char * account_name = NULL ;
2008-11-06 14:26:24 +03:00
NTSTATUS status ;
2013-05-24 15:29:28 +04:00
status = cli_rpc_pipe_open_noauth ( cli , & ndr_table_netlogon ,
2013-09-05 22:57:02 +04:00
& netlogon_pipe ) ;
2008-11-06 14:26:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-09-05 22:57:02 +04:00
TALLOC_FREE ( frame ) ;
2008-11-06 14:26:24 +03:00
return status ;
}
if ( ! r - > in . machine_password ) {
2013-02-01 16:14:05 +04:00
r - > in . machine_password = generate_random_password ( mem_ctx ,
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ,
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ) ;
2013-09-05 22:57:02 +04:00
if ( r - > in . machine_password = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
2008-11-06 14:26:24 +03:00
}
/* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */
2013-09-05 22:57:02 +04:00
E_md4hash ( r - > in . admin_password , current_nt_hash . hash ) ;
2008-11-06 14:26:24 +03:00
2013-09-05 22:57:02 +04:00
account_name = talloc_asprintf ( frame , " %s$ " ,
r - > in . machine_name ) ;
if ( account_name = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
status = rpccli_create_netlogon_creds ( netlogon_pipe - > desthost ,
r - > in . domain_name ,
account_name ,
r - > in . secure_channel_type ,
r - > in . msg_ctx ,
frame ,
& netlogon_creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2008-11-06 14:26:24 +03:00
2014-09-05 08:59:00 +04:00
status = rpccli_setup_netlogon_creds ( cli , NCACN_NP ,
2013-09-05 22:57:02 +04:00
netlogon_creds ,
true , /* force_reauth */
current_nt_hash ,
NULL ) ; /* previous_nt_hash */
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
status = netlogon_creds_cli_ServerPasswordSet ( netlogon_creds ,
netlogon_pipe - > binding_handle ,
r - > in . machine_password ,
NULL ) ; /* new_version */
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
2008-11-06 14:26:24 +03:00
}
2008-04-15 00:56:12 +04:00
/****************************************************************
Do the domain join
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS libnet_join_joindomain_rpc ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r ,
struct cli_state * cli )
{
struct rpc_pipe_client * pipe_hnd = NULL ;
2009-03-19 00:49:41 +03:00
struct policy_handle sam_pol , domain_pol , user_pol ;
2011-01-17 17:19:18 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL , result ;
2008-04-15 00:56:12 +04:00
char * acct_name ;
struct lsa_String lsa_acct_name ;
uint32_t user_rid ;
uint32_t acct_flags = ACB_WSTRUST ;
struct samr_Ids user_rids ;
struct samr_Ids name_types ;
union samr_UserInfo user_info ;
2011-01-17 17:19:18 +03:00
struct dcerpc_binding_handle * b = NULL ;
2013-03-05 14:44:03 +04:00
unsigned int old_timeout = 0 ;
2008-04-15 00:56:12 +04:00
2012-08-01 12:30:06 +04:00
DATA_BLOB session_key = data_blob_null ;
2008-07-30 21:52:56 +04:00
struct samr_CryptPassword crypt_pwd ;
struct samr_CryptPasswordEx crypt_pwd_ex ;
2008-04-15 00:56:12 +04:00
ZERO_STRUCT ( sam_pol ) ;
ZERO_STRUCT ( domain_pol ) ;
ZERO_STRUCT ( user_pol ) ;
2009-02-03 22:03:42 +03:00
switch ( r - > in . secure_channel_type ) {
case SEC_CHAN_WKSTA :
acct_flags = ACB_WSTRUST ;
break ;
case SEC_CHAN_BDC :
acct_flags = ACB_SVRTRUST ;
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
2008-04-15 00:56:12 +04:00
if ( ! r - > in . machine_password ) {
2013-02-01 16:14:05 +04:00
r - > in . machine_password = generate_random_password ( mem_ctx ,
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ,
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH ) ;
2008-04-15 00:56:12 +04:00
NT_STATUS_HAVE_NO_MEMORY ( r - > in . machine_password ) ;
}
2008-02-28 21:44:34 +03:00
/* Open the domain */
2013-05-24 15:29:28 +04:00
status = cli_rpc_pipe_open_noauth ( cli , & ndr_table_samr ,
2008-07-20 13:04:31 +04:00
& pipe_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 21:44:34 +03:00
DEBUG ( 0 , ( " Error connecting to SAM pipe. Error was %s \n " ,
nt_errstr ( status ) ) ) ;
2007-12-11 23:31:44 +03:00
goto done ;
}
2011-01-17 17:19:18 +03:00
b = pipe_hnd - > binding_handle ;
2012-08-01 12:30:06 +04:00
status = cli_get_session_key ( mem_ctx , pipe_hnd , & session_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Error getting session_key of SAM pipe. Error was %s \n " ,
nt_errstr ( status ) ) ) ;
goto done ;
}
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_Connect2 ( b , mem_ctx ,
2008-04-19 23:56:43 +04:00
pipe_hnd - > desthost ,
2009-02-03 16:41:49 +03:00
SAMR_ACCESS_ENUM_DOMAINS
2009-04-16 02:40:00 +04:00
| SAMR_ACCESS_LOOKUP_DOMAIN ,
2011-01-17 17:19:18 +03:00
& sam_pol ,
& result ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_OpenDomain ( b , mem_ctx ,
2008-02-01 13:12:05 +03:00
& sam_pol ,
2009-02-03 16:41:49 +03:00
SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
| SAMR_DOMAIN_ACCESS_CREATE_USER
| SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT ,
2008-02-01 13:12:05 +03:00
r - > out . domain_sid ,
2011-01-17 17:19:18 +03:00
& domain_pol ,
& result ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2008-02-28 21:44:34 +03:00
/* Create domain user */
2008-01-11 16:42:48 +03:00
acct_name = talloc_asprintf ( mem_ctx , " %s$ " , r - > in . machine_name ) ;
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( acct_name ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
2007-12-11 23:31:44 +03:00
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-02-29 03:25:45 +03:00
uint32_t access_desired =
2008-01-25 03:00:51 +03:00
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 ;
2008-02-29 03:25:45 +03:00
DEBUG ( 10 , ( " Creating account with desired access mask: %d \n " ,
access_desired ) ) ;
2008-02-28 21:44:34 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_CreateUser2 ( b , mem_ctx ,
2008-02-01 16:21:54 +03:00
& domain_pol ,
& lsa_acct_name ,
2009-02-03 22:03:42 +03:00
acct_flags ,
2008-02-29 03:25:45 +03:00
access_desired ,
2008-02-01 16:21:54 +03:00
& user_pol ,
& access_granted ,
2011-01-17 17:19:18 +03:00
& user_rid ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
status = result ;
2008-02-28 21:44:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_USER_EXISTS ) ) {
DEBUG ( 10 , ( " Creation of workstation account failed: %s \n " ,
nt_errstr ( status ) ) ) ;
/* If NT_STATUS_ACCESS_DENIED then we have a valid
username / password combo but the user does not have
administrator access . */
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" User specified does not have "
" administrator privileges " ) ;
}
2008-04-15 00:56:12 +04:00
goto done ;
2008-02-28 21:44:34 +03:00
}
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-02-28 21:44:34 +03:00
/* We *must* do this.... don't ask... */
2008-01-05 01:11:53 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
2008-01-05 01:11:53 +03:00
}
2007-12-11 23:31:44 +03:00
}
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_LookupNames ( b , mem_ctx ,
2008-02-08 16:48:55 +03:00
& domain_pol ,
1 ,
& lsa_acct_name ,
& user_rids ,
2011-01-17 17:19:18 +03:00
& name_types ,
& result ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2013-11-08 09:40:55 +04:00
if ( user_rids . count ! = 1 ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
goto done ;
}
if ( name_types . count ! = 1 ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2008-02-08 16:48:55 +03:00
if ( name_types . ids [ 0 ] ! = SID_NAME_USER ) {
2008-02-28 21:44:34 +03:00
DEBUG ( 0 , ( " %s is not a user account (type=%d) \n " ,
acct_name , name_types . ids [ 0 ] ) ) ;
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-28 21:44:34 +03:00
/* Open handle on user */
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_OpenUser ( b , mem_ctx ,
2008-02-01 13:57:53 +03:00
& domain_pol ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED ,
2008-02-01 13:57:53 +03:00
user_rid ,
2011-01-17 17:19:18 +03:00
& user_pol ,
& result ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2008-02-28 21:44:34 +03:00
/* Fill in the additional account flags now */
2008-02-29 03:25:45 +03:00
acct_flags | = ACB_PWNOEXP ;
2008-01-11 20:49:20 +03:00
2008-11-29 02:12:26 +03:00
/* Set account flags on machine account */
ZERO_STRUCT ( user_info . info16 ) ;
user_info . info16 . acct_flags = acct_flags ;
2007-12-11 23:31:44 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_SetUserInfo ( b , mem_ctx ,
2008-02-12 02:51:51 +03:00
& user_pol ,
2008-11-29 02:12:26 +03:00
16 ,
2011-01-17 17:19:18 +03:00
& user_info ,
& result ) ;
2008-11-29 02:12:26 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_DeleteUser ( b , mem_ctx ,
& user_pol ,
& result ) ;
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to set account flags for machine account (%s) \n " ,
nt_errstr ( status ) ) ;
goto done ;
}
2008-11-29 02:12:26 +03:00
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
dcerpc_samr_DeleteUser ( b , mem_ctx ,
& user_pol ,
& result ) ;
2008-11-29 02:12:26 +03:00
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to set account flags for machine account (%s) \n " ,
nt_errstr ( status ) ) ;
goto done ;
}
/* Set password on machine account - first try level 26 */
2013-03-05 14:44:03 +04:00
/*
* increase the timeout as password filter modules on the DC
* might delay the operation for a significant amount of time
*/
old_timeout = rpccli_set_timeout ( pipe_hnd , 600000 ) ;
2008-11-29 02:12:26 +03:00
init_samr_CryptPasswordEx ( r - > in . machine_password ,
2012-08-01 12:30:06 +04:00
& session_key ,
2008-11-29 02:12:26 +03:00
& crypt_pwd_ex ) ;
2008-12-06 02:28:34 +03:00
user_info . info26 . password = crypt_pwd_ex ;
user_info . info26 . password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON ;
2008-11-29 02:12:26 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_SetUserInfo2 ( b , mem_ctx ,
2008-11-29 02:12:26 +03:00
& user_pol ,
26 ,
2011-01-17 17:19:18 +03:00
& user_info ,
& result ) ;
2008-11-29 02:12:26 +03:00
2011-04-24 02:00:40 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE ) ) {
2008-02-29 03:27:52 +03:00
/* retry with level 24 */
2008-07-30 21:52:56 +04:00
init_samr_CryptPassword ( r - > in . machine_password ,
2012-08-01 12:30:06 +04:00
& session_key ,
2008-07-30 21:52:56 +04:00
& crypt_pwd ) ;
2008-12-06 02:28:34 +03:00
user_info . info24 . password = crypt_pwd ;
user_info . info24 . password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON ;
2008-02-29 03:27:52 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_SetUserInfo2 ( b , mem_ctx ,
2008-02-29 03:27:52 +03:00
& user_pol ,
24 ,
2011-01-17 17:19:18 +03:00
& user_info ,
& result ) ;
2008-02-29 03:27:52 +03:00
}
2013-03-05 14:44:03 +04:00
old_timeout = rpccli_set_timeout ( pipe_hnd , old_timeout ) ;
2007-12-11 23:31:44 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-04-14 16:42:19 +04:00
2011-01-17 17:19:18 +03:00
dcerpc_samr_DeleteUser ( b , mem_ctx ,
& user_pol ,
& result ) ;
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to set password for machine account (%s) \n " ,
nt_errstr ( status ) ) ;
goto done ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
dcerpc_samr_DeleteUser ( b , mem_ctx ,
& user_pol ,
& result ) ;
2008-04-14 16:42:19 +04:00
2008-02-28 21:44:34 +03:00
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to set password for machine account (%s) \n " ,
nt_errstr ( status ) ) ;
2007-12-11 23:31:44 +03:00
goto done ;
}
2007-12-18 12:16:40 +03:00
status = NT_STATUS_OK ;
2008-04-15 00:56:12 +04:00
2007-12-11 23:31:44 +03:00
done :
2008-04-15 00:56:12 +04:00
if ( ! pipe_hnd ) {
return status ;
}
2012-08-01 12:30:06 +04:00
data_blob_clear_free ( & session_key ) ;
2008-04-15 00:56:12 +04:00
if ( is_valid_policy_hnd ( & sam_pol ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & sam_pol , & result ) ;
2008-04-15 00:56:12 +04:00
}
if ( is_valid_policy_hnd ( & domain_pol ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & domain_pol , & result ) ;
2008-04-15 00:56:12 +04:00
}
if ( is_valid_policy_hnd ( & user_pol ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
2007-12-11 23:31:44 +03:00
}
2008-04-20 15:51:46 +04:00
TALLOC_FREE ( pipe_hnd ) ;
2007-12-11 23:31:44 +03:00
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
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-09-02 21:32:23 +04:00
NTSTATUS libnet_join_ok ( struct messaging_context * msg_ctx ,
const char * netbios_domain_name ,
2013-02-27 08:22:05 +04:00
const char * dc_name ,
const bool use_kerberos )
2008-02-28 13:17:29 +03:00
{
2013-09-02 21:32:23 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-02-28 13:17:29 +03:00
struct cli_state * cli = NULL ;
struct rpc_pipe_client * netlogon_pipe = NULL ;
2015-02-09 13:29:49 +03:00
struct cli_credentials * cli_creds = NULL ;
2013-09-02 21:32:23 +04:00
struct netlogon_creds_cli_context * netlogon_creds = NULL ;
struct netlogon_creds_CredentialState * creds = NULL ;
uint32_t netlogon_flags = 0 ;
2008-02-28 13:17:29 +03:00
NTSTATUS status ;
2013-09-02 21:32:23 +04:00
const char * machine_account = NULL ;
2015-02-09 13:29:49 +03:00
const char * machine_domain = NULL ;
const char * machine_password = NULL ;
2013-02-27 08:22:05 +04:00
int flags = 0 ;
2008-02-28 13:17:29 +03:00
if ( ! dc_name ) {
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ! secrets_init ( ) ) {
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
2015-02-09 13:29:49 +03:00
status = pdb_get_trust_credentials ( netbios_domain_name , NULL ,
frame , & cli_creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
2015-02-09 13:29:49 +03:00
return status ;
2008-02-28 13:17:29 +03:00
}
2015-02-09 13:29:49 +03:00
/* we don't want any old password */
cli_credentials_set_old_password ( cli_creds , NULL , CRED_SPECIFIED ) ;
2008-02-28 13:17:29 +03:00
2013-02-27 08:22:05 +04:00
if ( use_kerberos ) {
flags | = CLI_FULL_CONNECTION_USE_KERBEROS ;
}
2015-02-09 13:29:49 +03:00
machine_account = cli_credentials_get_username ( cli_creds ) ;
machine_domain = cli_credentials_get_domain ( cli_creds ) ;
machine_password = cli_credentials_get_password ( cli_creds ) ;
2008-02-28 13:17:29 +03:00
status = cli_full_connection ( & cli , NULL ,
dc_name ,
NULL , 0 ,
" IPC$ " , " IPC " ,
machine_account ,
2015-02-09 13:29:49 +03:00
machine_domain ,
2008-02-28 13:17:29 +03:00
machine_password ,
2013-02-27 08:22:05 +04:00
flags ,
2015-12-16 12:03:52 +03:00
SMB_SIGNING_IPC_DEFAULT ) ;
2013-09-02 21:32:23 +04:00
2008-02-28 13:17:29 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
status = cli_full_connection ( & cli , NULL ,
dc_name ,
NULL , 0 ,
" IPC$ " , " IPC " ,
" " ,
NULL ,
" " ,
0 ,
2015-12-16 12:03:52 +03:00
SMB_SIGNING_IPC_DEFAULT ) ;
2008-02-28 13:17:29 +03:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return status ;
}
2015-02-09 13:29:49 +03:00
status = rpccli_create_netlogon_creds_with_creds ( cli_creds ,
dc_name ,
msg_ctx ,
frame ,
& netlogon_creds ) ;
2008-07-20 18:33:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-09-02 21:32:23 +04:00
cli_shutdown ( cli ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
2008-02-28 13:17:29 +03:00
2015-02-09 13:29:49 +03:00
status = rpccli_setup_netlogon_creds_with_creds ( cli , NCACN_NP ,
netlogon_creds ,
true , /* force_reauth */
cli_creds ) ;
2013-09-02 21:32:23 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " connect_to_domain_password_server: "
" unable to open the domain client session to "
" machine %s. Flags[0x%08X] Error was : %s. \n " ,
dc_name , ( unsigned ) netlogon_flags ,
nt_errstr ( status ) ) ) ;
2008-02-28 13:17:29 +03:00
cli_shutdown ( cli ) ;
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return status ;
}
2013-09-02 21:32:23 +04:00
status = netlogon_creds_cli_get ( netlogon_creds ,
talloc_tos ( ) ,
& creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 13:17:29 +03:00
cli_shutdown ( cli ) ;
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
netlogon_flags = creds - > negotiate_flags ;
TALLOC_FREE ( creds ) ;
if ( ! ( netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC ) ) {
cli_shutdown ( cli ) ;
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return NT_STATUS_OK ;
}
2015-02-09 13:29:49 +03:00
status = cli_rpc_pipe_open_schannel_with_creds (
2013-05-24 15:17:24 +04:00
cli , & ndr_table_netlogon , NCACN_NP ,
2015-02-09 13:29:49 +03:00
cli_creds ,
2013-09-02 21:32:23 +04:00
netlogon_creds , & netlogon_pipe ) ;
2008-02-28 13:17:29 +03:00
2013-09-02 21:32:23 +04:00
TALLOC_FREE ( netlogon_pipe ) ;
2008-02-28 13:17:29 +03:00
2008-07-20 13:04:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 13:17:29 +03:00
DEBUG ( 0 , ( " libnet_join_ok: failed to open schannel session "
" on netlogon pipe to server %s for domain %s. "
" Error was %s \n " ,
2012-05-19 19:31:50 +04:00
smbXcli_conn_remote_name ( cli - > conn ) ,
2011-07-22 18:28:27 +04:00
netbios_domain_name , nt_errstr ( status ) ) ) ;
2013-09-02 21:32:23 +04:00
cli_shutdown ( cli ) ;
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return status ;
}
2013-09-02 21:32:23 +04:00
cli_shutdown ( cli ) ;
TALLOC_FREE ( frame ) ;
2008-02-28 13:17:29 +03:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR libnet_join_post_verify ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
NTSTATUS status ;
2013-09-02 21:32:23 +04:00
status = libnet_join_ok ( r - > in . msg_ctx ,
r - > out . netbios_domain_name ,
2013-02-27 08:22:05 +04:00
r - > in . dc_name ,
r - > in . use_kerberos ) ;
2008-02-28 13:17:29 +03:00
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 ;
2009-03-19 00:49:41 +03:00
struct policy_handle sam_pol , domain_pol , user_pol ;
2011-01-17 17:19:18 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL , result ;
2007-12-19 13:02:39 +03:00
char * acct_name ;
2008-02-29 03:25:45 +03:00
uint32_t 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 ;
2011-05-13 02:19:13 +04:00
struct dcerpc_binding_handle * b = NULL ;
2007-12-19 13:02:39 +03:00
2008-06-04 04:43:41 +04:00
ZERO_STRUCT ( sam_pol ) ;
ZERO_STRUCT ( domain_pol ) ;
ZERO_STRUCT ( user_pol ) ;
2008-07-30 23:38:21 +04:00
status = libnet_join_connect_dc_ipc ( r - > in . dc_name ,
r - > in . admin_account ,
2008-09-24 13:05:37 +04:00
r - > in . admin_domain ,
2008-07-30 23:38:21 +04:00
r - > in . admin_password ,
r - > in . use_kerberos ,
& cli ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-02-28 21:44:34 +03:00
/* Open the domain */
2013-05-24 15:29:28 +04:00
status = cli_rpc_pipe_open_noauth ( cli , & ndr_table_samr ,
2008-07-20 13:04:31 +04:00
& pipe_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 21:44:34 +03:00
DEBUG ( 0 , ( " Error connecting to SAM pipe. Error was %s \n " ,
nt_errstr ( status ) ) ) ;
2007-12-19 13:02:39 +03:00
goto done ;
}
2011-01-17 17:19:18 +03:00
b = pipe_hnd - > binding_handle ;
status = dcerpc_samr_Connect2 ( b , mem_ctx ,
2008-04-19 23:56:43 +04:00
pipe_hnd - > desthost ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED ,
2011-01-17 17:19:18 +03:00
& sam_pol ,
& result ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-19 13:02:39 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_OpenDomain ( b , mem_ctx ,
2008-02-01 13:12:05 +03:00
& sam_pol ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED ,
2008-02-01 13:12:05 +03:00
r - > in . domain_sid ,
2011-01-17 17:19:18 +03:00
& domain_pol ,
& result ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-19 13:02:39 +03:00
2008-02-28 21:44:34 +03:00
/* Create domain user */
2008-01-11 16:42:48 +03:00
acct_name = talloc_asprintf ( mem_ctx , " %s$ " , r - > in . machine_name ) ;
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( acct_name ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
2007-12-19 13:02:39 +03:00
2008-02-08 16:48:55 +03:00
init_lsa_String ( & lsa_acct_name , acct_name ) ;
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_LookupNames ( b , mem_ctx ,
2008-02-08 16:48:55 +03:00
& domain_pol ,
1 ,
& lsa_acct_name ,
& user_rids ,
2011-01-17 17:19:18 +03:00
& name_types ,
& result ) ;
2008-02-08 16:48:55 +03:00
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2013-11-08 09:40:55 +04:00
if ( user_rids . count ! = 1 ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
goto done ;
}
if ( name_types . count ! = 1 ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
goto done ;
}
2007-12-19 13:02:39 +03:00
2008-02-08 16:48:55 +03:00
if ( name_types . ids [ 0 ] ! = SID_NAME_USER ) {
2008-02-28 21:44:34 +03:00
DEBUG ( 0 , ( " %s is not a user account (type=%d) \n " , acct_name ,
name_types . ids [ 0 ] ) ) ;
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-28 21:44:34 +03:00
/* Open handle on user */
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_OpenUser ( b , mem_ctx ,
2008-02-01 13:57:53 +03:00
& domain_pol ,
2009-04-15 03:12:13 +04:00
SEC_FLAG_MAXIMUM_ALLOWED ,
2008-02-01 13:57:53 +03:00
user_rid ,
2011-01-17 17:19:18 +03:00
& user_pol ,
& result ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2011-01-17 17:19:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
goto done ;
}
2007-12-19 13:02:39 +03:00
2008-02-28 21:44:34 +03:00
/* Get user info */
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_QueryUserInfo ( b , mem_ctx ,
2008-02-12 20:21:52 +03:00
& user_pol ,
16 ,
2011-01-17 17:19:18 +03:00
& info ,
& result ) ;
2007-12-19 13:02:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
goto done ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
2007-12-19 13:02:39 +03:00
goto done ;
}
2008-02-28 21:44:34 +03:00
/* now disable and setuser info */
2008-02-12 02:51:51 +03:00
info - > info16 . acct_flags | = ACB_DISABLED ;
2007-12-19 13:02:39 +03:00
2011-01-17 17:19:18 +03:00
status = dcerpc_samr_SetUserInfo ( b , mem_ctx ,
2008-02-12 02:51:51 +03:00
& user_pol ,
16 ,
2011-01-17 17:19:18 +03:00
info ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
goto done ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
status = result ;
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
goto done ;
}
status = result ;
dcerpc_samr_Close ( b , mem_ctx , & user_pol , & result ) ;
2007-12-19 13:02:39 +03:00
done :
2011-05-13 02:19:13 +04:00
if ( pipe_hnd & & b ) {
2008-06-04 04:43:41 +04:00
if ( is_valid_policy_hnd ( & domain_pol ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & domain_pol , & result ) ;
2008-06-04 04:43:41 +04:00
}
if ( is_valid_policy_hnd ( & sam_pol ) ) {
2011-01-17 17:19:18 +03:00
dcerpc_samr_Close ( b , mem_ctx , & sam_pol , & result ) ;
2008-06-04 04:43:41 +04:00
}
2008-04-20 15:51:46 +04:00
TALLOC_FREE ( pipe_hnd ) ;
2008-01-04 13:21:53 +03:00
}
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
{
2011-05-13 02:15:41 +04:00
WERROR werr = WERR_OK ;
2011-04-07 19:19:03 +04:00
sbcErr err ;
2008-03-17 20:01:33 +03:00
struct smbconf_ctx * ctx ;
2008-01-13 03:40:05 +03:00
2011-04-07 19:19:03 +04:00
err = smbconf_init_reg ( r , & ctx , NULL ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
2008-01-13 03:40:05 +03:00
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 ) ) {
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " security " , " user " ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2007-12-14 19:37:24 +03:00
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " workgroup " ,
r - > in . domain_name ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2008-06-04 03:32:15 +04:00
smbconf_delete_global_parameter ( ctx , " realm " ) ;
2008-01-13 03:40:05 +03:00
goto done ;
2007-12-14 19:37:24 +03:00
}
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " security " , " domain " ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " workgroup " ,
r - > out . netbios_domain_name ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2008-01-11 16:41:34 +03:00
if ( r - > out . domain_is_ad ) {
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " security " , " ads " ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2007-12-11 23:31:44 +03:00
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " realm " ,
r - > out . dns_domain_name ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2007-12-11 23:31:44 +03:00
}
2008-02-28 13:00:50 +03:00
done :
2008-03-21 03:04:57 +03:00
smbconf_shutdown ( 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 ;
2011-04-07 19:19:03 +04:00
sbcErr err ;
2008-03-17 20:01:33 +03:00
struct smbconf_ctx * ctx ;
2008-01-13 03:40:05 +03:00
2011-04-07 19:19:03 +04:00
err = smbconf_init_reg ( r , & ctx , NULL ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
2008-01-13 03:40:05 +03:00
goto done ;
}
2007-12-19 13:02:39 +03:00
if ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
2011-04-11 15:23:26 +04:00
err = smbconf_set_global_parameter ( ctx , " security " , " user " ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2008-04-15 00:57:37 +04:00
2011-04-11 16:20:32 +04:00
err = smbconf_delete_global_parameter ( ctx , " workgroup " ) ;
if ( ! SBC_ERROR_IS_OK ( err ) ) {
werr = WERR_NO_SUCH_SERVICE ;
goto done ;
}
2008-04-15 00:57:37 +04:00
2008-03-17 20:01:33 +03:00
smbconf_delete_global_parameter ( ctx , " realm " ) ;
2007-12-19 13:02:39 +03:00
}
2008-02-28 13:00:50 +03:00
done :
2008-03-21 03:04:57 +03:00
smbconf_shutdown ( 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 ;
}
2011-07-27 18:31:02 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2008-06-05 20:58:27 +04:00
2007-12-19 13:02:39 +03:00
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 ;
}
2011-07-27 18:31:02 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2008-06-05 20:58:27 +04:00
2007-12-11 23:31:44 +03:00
r - > out . modified_config = true ;
r - > out . result = werr ;
return werr ;
}
2008-01-07 20:58:04 +03:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-28 16:13:27 +03:00
static bool libnet_parse_domain_dc ( TALLOC_CTX * mem_ctx ,
const char * domain_str ,
const char * * domain_p ,
const char * * dc_p )
{
char * domain = NULL ;
char * dc = NULL ;
const char * p = NULL ;
if ( ! domain_str | | ! domain_p | | ! dc_p ) {
return false ;
}
p = strchr_m ( domain_str , ' \\ ' ) ;
if ( p ! = NULL ) {
domain = talloc_strndup ( mem_ctx , domain_str ,
PTR_DIFF ( p , domain_str ) ) ;
dc = talloc_strdup ( mem_ctx , p + 1 ) ;
if ( ! dc ) {
return false ;
}
} else {
domain = talloc_strdup ( mem_ctx , domain_str ) ;
dc = NULL ;
}
if ( ! domain ) {
return false ;
}
* domain_p = domain ;
if ( ! * dc_p & & dc ) {
* dc_p = dc ;
}
return true ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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-11-06 13:40:03 +03:00
if ( strlen ( r - > in . machine_name ) > 15 ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Our netbios name can be at most 15 chars long, "
" \" %s \" is %u chars long \n " ,
r - > in . machine_name ,
( unsigned int ) strlen ( r - > in . machine_name ) ) ;
return WERR_INVALID_PARAM ;
}
2008-03-28 16:13:27 +03:00
if ( ! libnet_parse_domain_dc ( mem_ctx , r - > in . domain_name ,
& r - > in . domain_name ,
& r - > in . dc_name ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Failed to parse domain name " ) ;
return WERR_INVALID_PARAM ;
}
2008-09-24 13:05:37 +04:00
if ( ! r - > in . admin_domain ) {
char * admin_domain = NULL ;
char * admin_account = NULL ;
2016-09-20 20:51:15 +03:00
bool ok ;
ok = split_domain_user ( mem_ctx ,
r - > in . admin_account ,
& admin_domain ,
& admin_account ) ;
if ( ! ok ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2016-09-20 20:51:15 +03:00
}
if ( admin_domain ! = NULL ) {
r - > in . admin_domain = admin_domain ;
} else {
r - > in . admin_domain = r - > in . domain_name ;
}
2008-09-24 13:05:37 +04:00
r - > in . admin_account = admin_account ;
}
2008-01-15 12:51:40 +03:00
if ( ! secrets_init ( ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Unable to open secrets database " ) ;
return WERR_CAN_NOT_COMPLETE ;
}
return WERR_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-24 07:50:21 +04:00
static void libnet_join_add_dom_rids_to_builtins ( struct dom_sid * domain_sid )
{
NTSTATUS status ;
/* Try adding dom admins to builtin\admins. Only log failures. */
status = create_builtin_administrators ( domain_sid ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PROTOCOL_UNREACHABLE ) ) {
DEBUG ( 10 , ( " Unable to auto-add domain administrators to "
" BUILTIN \\ Administrators during join because "
2011-09-14 16:20:50 +04:00
" winbindd must be running. \n " ) ) ;
2008-07-24 07:50:21 +04:00
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " Failed to auto-add domain administrators to "
" BUILTIN \\ Administrators during join: %s \n " ,
nt_errstr ( status ) ) ) ;
}
/* Try adding dom users to builtin\users. Only log failures. */
status = create_builtin_users ( domain_sid ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PROTOCOL_UNREACHABLE ) ) {
DEBUG ( 10 , ( " Unable to auto-add domain users to BUILTIN \\ users "
2011-09-14 16:20:50 +04:00
" during join because winbindd must be running. \n " ) ) ;
2008-07-24 07:50:21 +04:00
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " Failed to auto-add domain administrators to "
" BUILTIN \\ Administrators during join: %s \n " ,
nt_errstr ( status ) ) ) ;
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-15 12:51:40 +03:00
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 ;
}
2008-08-29 19:55:28 +04:00
if ( ! ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) ) {
return WERR_OK ;
}
2008-10-27 21:40:23 +03:00
saf_join_store ( r - > out . netbios_domain_name , r - > in . dc_name ) ;
if ( r - > out . dns_domain_name ) {
saf_join_store ( r - > out . dns_domain_name , r - > in . dc_name ) ;
}
2008-08-29 19:43:12 +04:00
2011-02-11 13:14:57 +03:00
# ifdef HAVE_ADS
2008-11-06 14:26:24 +03:00
if ( r - > out . domain_is_ad & &
! ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE ) ) {
2008-08-29 19:55:28 +04:00
ADS_STATUS ads_status ;
2008-08-29 19:43:12 +04:00
2008-08-29 19:55:28 +04:00
ads_status = libnet_join_post_processing_ads ( mem_ctx , r ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
2015-12-03 17:24:20 +03:00
return WERR_GEN_FAILURE ;
2008-08-29 19:43:12 +04:00
}
2008-01-15 12:51:40 +03:00
}
2011-02-11 13:14:57 +03:00
# endif /* HAVE_ADS */
2008-01-15 12:51:40 +03:00
2008-07-24 07:50:21 +04:00
libnet_join_add_dom_rids_to_builtins ( r - > out . domain_sid ) ;
2008-01-15 12:51:40 +03:00
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 ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2007-12-11 23:31:44 +03:00
}
2008-01-07 20:58:04 +03:00
talloc_set_destructor ( ctx , libnet_destroy_JoinCtx ) ;
2011-06-09 09:31:03 +04:00
ctx - > in . machine_name = talloc_strdup ( mem_ctx , lp_netbios_name ( ) ) ;
2008-01-07 20:58:04 +03:00
W_ERROR_HAVE_NO_MEMORY ( ctx - > in . machine_name ) ;
2008-03-04 21:04:54 +03:00
ctx - > in . secure_channel_type = SEC_CHAN_WKSTA ;
2016-03-11 18:04:52 +03:00
ctx - > in . desired_encryption_types = ENC_CRC32 |
ENC_RSA_MD5 |
ENC_RC4_HMAC_MD5 ;
# ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
ctx - > in . desired_encryption_types | = ENC_HMAC_SHA1_96_AES128 ;
# endif
# ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
ctx - > in . desired_encryption_types | = ENC_HMAC_SHA1_96_AES256 ;
# endif
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 ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2007-12-19 13:02:39 +03:00
}
2008-01-07 20:58:04 +03:00
talloc_set_destructor ( ctx , libnet_destroy_UnjoinCtx ) ;
2011-06-09 09:31:03 +04:00
ctx - > in . machine_name = talloc_strdup ( mem_ctx , lp_netbios_name ( ) ) ;
2008-01-07 20:58:04 +03:00
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
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-15 01:07:55 +04:00
static WERROR libnet_join_check_config ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
{
2008-11-06 15:37:03 +03:00
bool valid_security = false ;
bool valid_workgroup = false ;
bool valid_realm = false ;
2016-06-16 00:03:32 +03:00
bool ignored_realm = false ;
2008-11-06 15:37:03 +03:00
2008-04-15 01:07:55 +04:00
/* check if configuration is already set correctly */
2008-11-06 15:37:03 +03:00
valid_workgroup = strequal ( lp_workgroup ( ) , r - > out . netbios_domain_name ) ;
2008-04-15 01:07:55 +04:00
switch ( r - > out . domain_is_ad ) {
case false :
2013-12-11 06:39:38 +04:00
valid_security = ( lp_security ( ) = = SEC_DOMAIN )
| | ( lp_server_role ( ) = = ROLE_DOMAIN_PDC )
| | ( lp_server_role ( ) = = ROLE_DOMAIN_BDC ) ;
2008-11-06 15:37:03 +03:00
if ( valid_workgroup & & valid_security ) {
2008-04-15 01:07:55 +04:00
/* nothing to be done */
return WERR_OK ;
}
break ;
case true :
2008-11-06 15:37:03 +03:00
valid_realm = strequal ( lp_realm ( ) , r - > out . dns_domain_name ) ;
switch ( lp_security ( ) ) {
case SEC_DOMAIN :
2016-06-16 00:03:32 +03:00
if ( ! valid_realm & & lp_winbind_rpc_only ( ) ) {
valid_realm = true ;
ignored_realm = true ;
}
2016-06-23 15:18:35 +03:00
/* FALL THROUGH */
2008-11-06 15:37:03 +03:00
case SEC_ADS :
valid_security = true ;
}
if ( valid_workgroup & & valid_realm & & valid_security ) {
2016-06-16 00:03:32 +03:00
if ( ignored_realm & & ! r - > in . modify_config )
{
libnet_join_set_error_string ( mem_ctx , r ,
" Warning: ignoring realm when "
" joining AD domain with "
" 'security=domain' and "
" 'winbind rpc only = yes'. "
" (realm set to '%s', "
" should be '%s'). " , lp_realm ( ) ,
r - > out . dns_domain_name ) ;
}
2008-04-15 01:07:55 +04:00
/* nothing to be done */
return WERR_OK ;
}
break ;
}
/* check if we are supposed to manipulate configuration */
if ( ! r - > in . modify_config ) {
2008-11-06 15:37:03 +03:00
char * wrong_conf = talloc_strdup ( mem_ctx , " " ) ;
if ( ! valid_workgroup ) {
wrong_conf = talloc_asprintf_append ( wrong_conf ,
" \" workgroup \" set to '%s', should be '%s' " ,
lp_workgroup ( ) , r - > out . netbios_domain_name ) ;
W_ERROR_HAVE_NO_MEMORY ( wrong_conf ) ;
}
if ( ! valid_realm ) {
wrong_conf = talloc_asprintf_append ( wrong_conf ,
" \" realm \" set to '%s', should be '%s' " ,
lp_realm ( ) , r - > out . dns_domain_name ) ;
W_ERROR_HAVE_NO_MEMORY ( wrong_conf ) ;
}
if ( ! valid_security ) {
2008-11-21 17:56:30 +03:00
const char * sec = NULL ;
2008-11-06 15:37:03 +03:00
switch ( lp_security ( ) ) {
case SEC_USER : sec = " user " ; break ;
case SEC_DOMAIN : sec = " domain " ; break ;
case SEC_ADS : sec = " ads " ; break ;
}
wrong_conf = talloc_asprintf_append ( wrong_conf ,
" \" security \" set to '%s', should be %s " ,
sec , r - > out . domain_is_ad ?
" either 'domain' or 'ads' " : " 'domain' " ) ;
W_ERROR_HAVE_NO_MEMORY ( wrong_conf ) ;
}
2008-04-15 01:07:55 +04:00
libnet_join_set_error_string ( mem_ctx , r ,
2008-11-06 15:37:03 +03:00
" Invalid configuration (%s) and configuration modification "
" was not requested " , wrong_conf ) ;
2008-04-15 01:07:55 +04:00
return WERR_CAN_NOT_COMPLETE ;
}
/* check if we are able to manipulate configuration */
if ( ! lp_config_backend_is_registry ( ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" Configuration manipulation requested but not "
" supported by backend " ) ;
return WERR_NOT_SUPPORTED ;
}
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-04-15 00:56:12 +04:00
WERROR werr ;
struct cli_state * cli = NULL ;
2011-02-11 13:14:57 +03:00
# ifdef HAVE_ADS
2008-01-07 21:07:38 +03:00
ADS_STATUS ads_status ;
2011-02-11 13:14:57 +03:00
# endif /* HAVE_ADS */
2016-03-03 10:18:58 +03:00
const char * pre_connect_realm = NULL ;
const char * numeric_dcip = NULL ;
const char * sitename = NULL ;
/* Before contacting a DC, we can securely know
* the realm only if the user specifies it .
*/
if ( r - > in . use_kerberos & &
r - > in . domain_name_type = = JoinDomNameTypeDNS ) {
pre_connect_realm = r - > in . domain_name ;
}
2008-01-07 21:07:38 +03:00
2008-01-12 04:22:44 +03:00
if ( ! r - > in . dc_name ) {
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * info ;
2008-05-08 16:23:20 +04:00
const char * dc ;
2015-06-28 14:36:22 +03:00
uint32_t name_type_flags = 0 ;
if ( r - > in . domain_name_type = = JoinDomNameTypeDNS ) {
name_type_flags = DS_IS_DNS_NAME ;
} else if ( r - > in . domain_name_type = = JoinDomNameTypeNBT ) {
name_type_flags = DS_IS_FLAT_NAME ;
}
2008-01-12 04:22:44 +03:00
status = dsgetdcname ( mem_ctx ,
2008-05-08 20:32:22 +04:00
r - > in . msg_ctx ,
2008-01-12 04:22:44 +03:00
r - > in . domain_name ,
NULL ,
NULL ,
2008-11-21 10:22:38 +03:00
DS_FORCE_REDISCOVERY |
2008-01-12 04:22:44 +03:00
DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
2015-06-28 14:36:22 +03:00
DS_RETURN_DNS_NAME |
name_type_flags ,
2008-01-12 04:22:44 +03:00
& info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
2016-08-18 18:26:38 +03:00
" failed to find DC for domain %s - %s " ,
2008-01-16 12:48:11 +03:00
r - > in . domain_name ,
get_friendly_nt_error_msg ( status ) ) ;
2009-09-18 01:46:52 +04:00
return WERR_DCNOTFOUND ;
2008-01-12 04:22:44 +03:00
}
2008-05-08 16:23:20 +04:00
dc = strip_hostname ( info - > dc_unc ) ;
r - > in . dc_name = talloc_strdup ( mem_ctx , dc ) ;
2008-01-12 04:22:44 +03:00
W_ERROR_HAVE_NO_MEMORY ( r - > in . dc_name ) ;
2016-03-03 10:18:58 +03:00
if ( info - > dc_address = = NULL | | info - > dc_address [ 0 ] ! = ' \\ ' | |
info - > dc_address [ 1 ] ! = ' \\ ' ) {
DBG_ERR ( " ill-formed DC address '%s' \n " ,
info - > dc_address ) ;
return WERR_DCNOTFOUND ;
}
numeric_dcip = info - > dc_address + 2 ;
sitename = info - > dc_site_name ;
/* info goes out of scope but the memory stays
allocated on the talloc context */
}
if ( pre_connect_realm ! = NULL ) {
struct sockaddr_storage ss = { 0 } ;
if ( numeric_dcip ! = NULL ) {
if ( ! interpret_string_addr ( & ss , numeric_dcip ,
AI_NUMERICHOST ) ) {
DBG_ERR (
" cannot parse IP address '%s' of DC '%s' \n " ,
numeric_dcip , r - > in . dc_name ) ;
return WERR_DCNOTFOUND ;
}
} else {
if ( ! interpret_string_addr ( & ss , r - > in . dc_name , 0 ) ) {
DBG_WARNING (
" cannot resolve IP address of DC '%s' \n " ,
r - > in . dc_name ) ;
return WERR_DCNOTFOUND ;
}
}
/* The domain parameter is only used as modifier
* to krb5 . conf file name . . JOIN is is not a valid
* NetBIOS name so it cannot clash with another domain
* - - Uri .
*/
create_local_private_krb5_conf_for_domain (
pre_connect_realm , " .JOIN " , sitename , & ss ) ;
2008-01-12 04:22:44 +03:00
}
2008-04-22 03:54:49 +04:00
status = libnet_join_lookup_dc_rpc ( mem_ctx , r , & cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to lookup DC info for domain '%s' over rpc: %s " ,
r - > in . domain_name , get_friendly_nt_error_msg ( status ) ) ;
return ntstatus_to_werror ( status ) ;
}
werr = libnet_join_check_config ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
2011-02-11 13:14:57 +03:00
# ifdef HAVE_ADS
2011-02-26 20:12:49 +03:00
2016-06-16 01:15:00 +03:00
if ( r - > out . domain_is_ad ) {
create_local_private_krb5_conf_for_domain (
r - > out . dns_domain_name , r - > out . netbios_domain_name ,
sitename , smbXcli_conn_remote_sockaddr ( cli - > conn ) ) ;
}
2011-02-26 20:12:49 +03:00
2016-03-10 20:03:47 +03:00
if ( r - > out . domain_is_ad & &
2008-11-06 14:26:24 +03:00
! ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE ) ) {
2008-01-12 04:22:44 +03:00
2016-03-10 20:03:47 +03:00
const char * initial_account_ou = r - > in . account_ou ;
/*
* we want to create the msDS - SupportedEncryptionTypes attribute
* as early as possible so always try an LDAP create as the user
* first . We copy r - > in . account_ou because it may be changed
* during the machine pre - creation .
*/
2016-03-02 20:07:53 +03:00
ads_status = libnet_join_connect_ads_user ( mem_ctx , r ) ;
2008-01-07 21:07:38 +03:00
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 ) ;
2016-03-10 20:03:47 +03:00
if ( ADS_ERR_OK ( ads_status ) ) {
/*
* LDAP object create succeeded , now go to the rpc
* password set routines
*/
r - > in . join_flags & = ~ WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ;
goto rpc_join ;
}
if ( initial_account_ou ! = NULL ) {
2008-01-07 21:07:38 +03:00
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
}
2016-03-10 20:03:47 +03:00
DEBUG ( 5 , ( " failed to precreate account in ou %s: %s " ,
r - > in . account_ou , ads_errstr ( ads_status ) ) ) ;
2008-01-07 21:07:38 +03:00
}
2011-02-11 13:14:57 +03:00
# endif /* HAVE_ADS */
2008-01-12 04:20:33 +03:00
2016-03-10 20:03:47 +03:00
rpc_join :
2008-11-06 14:26:24 +03:00
if ( ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE ) & &
( r - > in . join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED ) ) {
status = libnet_join_joindomain_rpc_unsecure ( mem_ctx , r , cli ) ;
} else {
status = libnet_join_joindomain_rpc ( mem_ctx , r , cli ) ;
}
2008-04-15 00:56:12 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_join_set_error_string ( mem_ctx , r ,
" failed to join domain '%s' over rpc: %s " ,
r - > in . domain_name , 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 ;
}
2008-04-15 00:56:12 +04:00
werr = ntstatus_to_werror ( status ) ;
goto done ;
2008-01-07 21:07:38 +03:00
}
if ( ! libnet_join_joindomain_store_secrets ( mem_ctx , r ) ) {
2008-04-15 00:56:12 +04:00
werr = WERR_SETUP_NOT_JOINED ;
goto done ;
2008-01-07 21:07:38 +03:00
}
2008-04-15 00:56:12 +04:00
werr = WERR_OK ;
done :
if ( cli ) {
cli_shutdown ( cli ) ;
}
return werr ;
2008-01-07 21:07:38 +03:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-18 18:29:05 +04:00
static WERROR libnet_join_rollback ( TALLOC_CTX * mem_ctx ,
struct libnet_JoinCtx * r )
2008-06-05 21:00:05 +04:00
{
WERROR werr ;
struct libnet_UnjoinCtx * u = NULL ;
werr = libnet_init_UnjoinCtx ( mem_ctx , & u ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
u - > in . debug = r - > in . debug ;
u - > in . dc_name = r - > in . dc_name ;
u - > in . domain_name = r - > in . domain_name ;
u - > in . admin_account = r - > in . admin_account ;
u - > in . admin_password = r - > in . admin_password ;
u - > in . modify_config = r - > in . modify_config ;
2013-02-27 08:22:05 +04:00
u - > in . use_kerberos = r - > in . use_kerberos ;
2008-06-05 21:00:05 +04:00
u - > in . unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ;
werr = libnet_Unjoin ( mem_ctx , u ) ;
TALLOC_FREE ( u ) ;
return werr ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
}
2011-02-26 20:12:32 +03:00
ZERO_STRUCT ( r - > out ) ;
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-06-05 20:58:27 +04:00
}
2008-02-28 13:17:29 +03:00
2008-06-05 20:58:27 +04:00
werr = libnet_join_post_processing ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
goto done ;
}
if ( r - > in . join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE ) {
2008-02-28 13:17:29 +03:00
werr = libnet_join_post_verify ( mem_ctx , r ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-06-05 21:00:05 +04:00
libnet_join_rollback ( mem_ctx , r ) ;
2008-02-28 13:17:29 +03:00
}
2007-12-14 19:37:24 +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 ;
}
2010-08-26 19:21:39 +04:00
r - > in . domain_sid = dom_sid_dup ( mem_ctx , & sid ) ;
2008-01-16 12:56:40 +03:00
W_ERROR_HAVE_NO_MEMORY ( r - > in . domain_sid ) ;
}
2009-06-19 21:46:07 +04:00
if ( ! ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ) & &
! r - > in . delete_machine_account ) {
libnet_join_unjoindomain_remove_secrets ( mem_ctx , r ) ;
return WERR_OK ;
}
2008-01-15 12:58:27 +03:00
if ( ! r - > in . dc_name ) {
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * info ;
2008-05-08 16:23:20 +04:00
const char * dc ;
2008-01-15 12:58:27 +03:00
status = dsgetdcname ( mem_ctx ,
2008-05-08 20:32:22 +04:00
r - > in . msg_ctx ,
2008-01-15 12:58:27 +03:00
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 ,
2016-08-18 18:26:38 +03:00
" failed to find DC for domain %s - %s " ,
2008-01-16 12:48:11 +03:00
r - > in . domain_name ,
get_friendly_nt_error_msg ( status ) ) ;
2009-09-18 01:46:52 +04:00
return WERR_DCNOTFOUND ;
2008-01-15 12:58:27 +03:00
}
2008-05-08 16:23:20 +04:00
dc = strip_hostname ( info - > dc_unc ) ;
r - > in . dc_name = talloc_strdup ( mem_ctx , dc ) ;
2008-01-15 12:58:27 +03:00
W_ERROR_HAVE_NO_MEMORY ( r - > in . dc_name ) ;
}
2011-02-11 13:14:57 +03:00
# ifdef HAVE_ADS
2009-06-19 21:46:07 +04:00
/* for net ads leave, try to delete the account. If it works,
no sense in disabling . If it fails , we can still try to
disable it . jmcd */
2011-02-26 14:36:19 +03:00
2009-06-19 21:46:07 +04:00
if ( r - > in . delete_machine_account ) {
2008-01-07 21:11:26 +03:00
ADS_STATUS ads_status ;
2009-06-26 23:24:57 +04:00
ads_status = libnet_unjoin_connect_ads ( mem_ctx , r ) ;
if ( ADS_ERR_OK ( ads_status ) ) {
/* dirty hack */
r - > out . dns_domain_name =
talloc_strdup ( mem_ctx ,
r - > in . ads - > server . realm ) ;
ads_status =
libnet_unjoin_remove_machine_acct ( mem_ctx , r ) ;
}
2008-01-07 21:11:26 +03:00
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 ;
W_ERROR_HAVE_NO_MEMORY ( r - > out . dns_domain_name ) ;
2009-06-19 21:46:07 +04:00
libnet_join_unjoindomain_remove_secrets ( mem_ctx , r ) ;
return WERR_OK ;
2008-01-07 21:11:26 +03:00
}
}
2011-02-11 13:14:57 +03:00
# endif /* HAVE_ADS */
2008-01-12 04:10:17 +03:00
2009-06-19 21:46:07 +04:00
/* The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag really means
" disable " . */
if ( r - > in . unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ) {
status = libnet_join_unjoindomain_rpc ( mem_ctx , r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" failed to disable machine account via rpc: %s " ,
get_friendly_nt_error_msg ( status ) ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NO_SUCH_USER ) ) {
return WERR_SETUP_NOT_JOINED ;
}
return ntstatus_to_werror ( status ) ;
}
2011-02-26 14:36:19 +03:00
2009-06-19 21:46:07 +04:00
r - > out . disabled_machine_account = true ;
}
/* If disable succeeded or was not requested at all, we
should be getting rid of our end of things */
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-03-28 16:13:27 +03:00
if ( ! libnet_parse_domain_dc ( mem_ctx , r - > in . domain_name ,
& r - > in . domain_name ,
& r - > in . dc_name ) ) {
libnet_unjoin_set_error_string ( mem_ctx , r ,
" Failed to parse domain name " ) ;
return WERR_INVALID_PARAM ;
}
2008-02-28 19:02:14 +03:00
if ( IS_DC ) {
return WERR_SETUP_DOMAIN_CONTROLLER ;
}
2008-09-24 13:05:37 +04:00
if ( ! r - > in . admin_domain ) {
char * admin_domain = NULL ;
char * admin_account = NULL ;
2016-09-20 20:51:15 +03:00
bool ok ;
ok = split_domain_user ( mem_ctx ,
r - > in . admin_account ,
& admin_domain ,
& admin_account ) ;
if ( ! ok ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2016-09-20 20:51:15 +03:00
}
if ( admin_domain ! = NULL ) {
r - > in . admin_domain = admin_domain ;
} else {
r - > in . admin_domain = r - > in . domain_name ;
}
2008-09-24 13:05:37 +04:00
r - > in . admin_account = admin_account ;
}
2008-01-15 12:51:40 +03:00
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 ;
}