2009-11-30 12:11:27 +03:00
/*
Unix SMB / CIFS implementation .
KCC service periodic handling
Copyright ( C ) Crístian Deives
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "lib/events/events.h"
# include "dsdb/samdb/samdb.h"
# include "auth/auth.h"
2020-11-20 17:27:17 +03:00
# include "samba/service.h"
2009-11-30 12:11:27 +03:00
# include "lib/messaging/irpc.h"
# include "dsdb/kcc/kcc_service.h"
2010-09-22 22:15:56 +04:00
# include "dsdb/kcc/kcc_connection.h"
2011-02-10 06:12:51 +03:00
# include <ldb_errors.h>
2009-11-30 12:11:27 +03:00
# include "../lib/util/dlinklist.h"
# include "librpc/gen_ndr/ndr_misc.h"
# include "librpc/gen_ndr/ndr_drsuapi.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
# include "param/param.h"
2009-11-30 12:12:24 +03:00
static int kccsrv_add_connection ( struct kccsrv_service * s ,
struct kcc_connection * conn )
2009-11-30 12:11:27 +03:00
{
struct ldb_message * msg ;
TALLOC_CTX * tmp_ctx ;
struct ldb_dn * new_dn , * server_dn ;
struct GUID guid ;
2009-11-30 12:12:24 +03:00
/* struct ldb_val schedule_val; */
2009-11-30 12:11:27 +03:00
int ret ;
bool ok ;
tmp_ctx = talloc_new ( s ) ;
2012-08-14 09:58:59 +04:00
if ( ! tmp_ctx ) {
DEBUG ( 0 , ( " failed to talloc \n " ) ) ;
ret = LDB_ERR_OPERATIONS_ERROR ;
goto done ;
}
2012-08-14 10:08:47 +04:00
new_dn = samdb_ntds_settings_dn ( s - > samdb , tmp_ctx ) ;
2009-11-30 12:11:27 +03:00
if ( ! new_dn ) {
DEBUG ( 0 , ( " failed to find NTDS settings \n " ) ) ;
2009-11-30 12:12:24 +03:00
ret = LDB_ERR_OPERATIONS_ERROR ;
goto done ;
}
new_dn = ldb_dn_copy ( tmp_ctx , new_dn ) ;
if ( ! new_dn ) {
DEBUG ( 0 , ( " failed to copy NTDS settings \n " ) ) ;
ret = LDB_ERR_OPERATIONS_ERROR ;
2009-11-30 12:11:27 +03:00
goto done ;
}
guid = GUID_random ( ) ;
ok = ldb_dn_add_child_fmt ( new_dn , " CN=%s " , GUID_string ( tmp_ctx , & guid ) ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " failed to create nTDSConnection DN \n " ) ) ;
2009-11-30 12:12:24 +03:00
ret = LDB_ERR_INVALID_DN_SYNTAX ;
2009-11-30 12:11:27 +03:00
goto done ;
}
2013-06-10 06:22:40 +04:00
ret = dsdb_find_dn_by_guid ( s - > samdb , tmp_ctx , & conn - > dsa_guid , 0 , & server_dn ) ;
2009-11-30 12:11:27 +03:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " failed to find fromServer DN '%s' \n " ,
2009-11-30 12:12:24 +03:00
GUID_string ( tmp_ctx , & conn - > dsa_guid ) ) ) ;
2009-11-30 12:11:27 +03:00
goto done ;
}
2009-11-30 12:12:24 +03:00
/*schedule_val = data_blob_const(r1->schedule, sizeof(r1->schedule));*/
2009-11-30 12:11:27 +03:00
msg = ldb_msg_new ( tmp_ctx ) ;
msg - > dn = new_dn ;
ldb_msg_add_string ( msg , " objectClass " , " nTDSConnection " ) ;
ldb_msg_add_string ( msg , " showInAdvancedViewOnly " , " TRUE " ) ;
ldb_msg_add_string ( msg , " enabledConnection " , " TRUE " ) ;
2009-11-30 12:12:24 +03:00
ldb_msg_add_linearized_dn ( msg , " fromServer " , server_dn ) ;
/* ldb_msg_add_value(msg, "schedule", &schedule_val, NULL); */
2011-07-06 06:22:31 +04:00
samdb_msg_add_uint ( s - > samdb , msg , msg ,
" options " , NTDSCONN_OPT_IS_GENERATED ) ;
2009-11-30 12:11:27 +03:00
ret = ldb_add ( s - > samdb , msg ) ;
if ( ret = = LDB_SUCCESS ) {
DEBUG ( 2 , ( " added nTDSConnection object '%s' \n " ,
ldb_dn_get_linearized ( new_dn ) ) ) ;
} else {
DEBUG ( 0 , ( " failed to add an nTDSConnection object: %s \n " ,
ldb_strerror ( ret ) ) ) ;
}
done :
talloc_free ( tmp_ctx ) ;
2009-11-30 12:12:24 +03:00
return ret ;
2009-11-30 12:11:27 +03:00
}
2009-11-30 12:12:24 +03:00
static int kccsrv_delete_connection ( struct kccsrv_service * s ,
struct kcc_connection * conn )
{
TALLOC_CTX * tmp_ctx ;
struct ldb_dn * dn ;
int ret ;
tmp_ctx = talloc_new ( s ) ;
2013-06-10 06:22:40 +04:00
ret = dsdb_find_dn_by_guid ( s - > samdb , tmp_ctx , & conn - > obj_guid , 0 , & dn ) ;
2009-11-30 12:12:24 +03:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " failed to find nTDSConnection's DN: %s \n " ,
ldb_strerror ( ret ) ) ) ;
goto done ;
}
ret = ldb_delete ( s - > samdb , dn ) ;
if ( ret = = LDB_SUCCESS ) {
DEBUG ( 2 , ( " deleted nTDSConnection object '%s' \n " ,
ldb_dn_get_linearized ( dn ) ) ) ;
} else {
DEBUG ( 0 , ( " failed to delete an nTDSConnection object: %s \n " ,
ldb_strerror ( ret ) ) ) ;
}
done :
talloc_free ( tmp_ctx ) ;
return ret ;
}
void kccsrv_apply_connections ( struct kccsrv_service * s ,
struct kcc_connection_list * ntds_list ,
struct kcc_connection_list * dsa_list )
{
2010-03-16 10:49:22 +03:00
unsigned int i , j , deleted = 0 , added = 0 ;
int ret ;
2009-11-30 12:12:24 +03:00
2011-07-06 06:22:31 +04:00
/* XXX
*
* This routine is not respecting connections that the
* administrator can specifically create ( NTDSCONN_OPT_IS_GENERATED
* bit will not be set )
*/
2009-12-21 12:57:21 +03:00
for ( i = 0 ; ntds_list & & i < ntds_list - > count ; i + + ) {
2009-11-30 12:12:24 +03:00
struct kcc_connection * ntds = & ntds_list - > servers [ i ] ;
for ( j = 0 ; j < dsa_list - > count ; j + + ) {
struct kcc_connection * dsa = & dsa_list - > servers [ j ] ;
if ( GUID_equal ( & ntds - > dsa_guid , & dsa - > dsa_guid ) ) {
break ;
}
}
if ( j = = dsa_list - > count ) {
ret = kccsrv_delete_connection ( s , ntds ) ;
if ( ret = = LDB_SUCCESS ) {
deleted + + ;
}
}
}
DEBUG ( 4 , ( " %d connections have been deleted \n " , deleted ) ) ;
for ( i = 0 ; i < dsa_list - > count ; i + + ) {
struct kcc_connection * dsa = & dsa_list - > servers [ i ] ;
2009-12-21 12:57:21 +03:00
for ( j = 0 ; ntds_list & & j < ntds_list - > count ; j + + ) {
2009-11-30 12:12:24 +03:00
struct kcc_connection * ntds = & ntds_list - > servers [ j ] ;
if ( GUID_equal ( & dsa - > dsa_guid , & ntds - > dsa_guid ) ) {
break ;
}
}
2009-12-21 12:57:21 +03:00
if ( ntds_list = = NULL | | j = = ntds_list - > count ) {
2009-11-30 12:12:24 +03:00
ret = kccsrv_add_connection ( s , dsa ) ;
if ( ret = = LDB_SUCCESS ) {
added + + ;
}
}
}
DEBUG ( 4 , ( " %d connections have been added \n " , added ) ) ;
}
struct kcc_connection_list * kccsrv_find_connections ( struct kccsrv_service * s ,
TALLOC_CTX * mem_ctx )
2009-11-30 12:11:27 +03:00
{
2010-03-16 10:49:22 +03:00
unsigned int i ;
int ret ;
2009-11-30 12:12:24 +03:00
struct ldb_dn * base_dn ;
struct ldb_result * res ;
const char * attrs [ ] = { " objectGUID " , " fromServer " , NULL } ;
struct kcc_connection_list * list ;
2012-08-14 09:56:04 +04:00
TALLOC_CTX * tmp_ctx ;
2010-03-07 08:09:24 +03:00
2012-08-14 09:56:04 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
DEBUG ( 0 , ( " failed to talloc \n " ) ) ;
return NULL ;
}
2012-08-14 10:08:47 +04:00
base_dn = samdb_ntds_settings_dn ( s - > samdb , tmp_ctx ) ;
2009-11-30 12:12:24 +03:00
if ( ! base_dn ) {
DEBUG ( 0 , ( " failed to find our own NTDS settings DN \n " ) ) ;
2012-08-14 09:56:04 +04:00
talloc_free ( tmp_ctx ) ;
2009-11-30 12:12:24 +03:00
return NULL ;
}
2009-11-30 12:11:27 +03:00
2012-08-14 09:56:04 +04:00
ret = ldb_search ( s - > samdb , tmp_ctx , & res , base_dn , LDB_SCOPE_ONELEVEL ,
2009-11-30 12:12:24 +03:00
attrs , " objectClass=nTDSConnection " ) ;
2009-11-30 12:11:27 +03:00
if ( ret ! = LDB_SUCCESS ) {
2009-11-30 12:12:24 +03:00
DEBUG ( 0 , ( " failed nTDSConnection search: %s \n " ,
ldb_strerror ( ret ) ) ) ;
2012-08-14 09:56:04 +04:00
talloc_free ( tmp_ctx ) ;
2009-11-30 12:11:27 +03:00
return NULL ;
}
2012-08-14 09:56:04 +04:00
list = talloc ( tmp_ctx , struct kcc_connection_list ) ;
2009-11-30 12:12:24 +03:00
if ( ! list ) {
DEBUG ( 0 , ( " out of memory " ) ) ;
return NULL ;
}
2012-08-14 09:56:04 +04:00
list - > servers = talloc_array ( list , struct kcc_connection ,
2009-11-30 12:12:24 +03:00
res - > count ) ;
if ( ! list - > servers ) {
DEBUG ( 0 , ( " out of memory " ) ) ;
2012-08-14 09:56:04 +04:00
talloc_free ( tmp_ctx ) ;
2009-11-30 12:12:24 +03:00
return NULL ;
}
list - > count = 0 ;
2009-11-30 12:11:27 +03:00
for ( i = 0 ; i < res - > count ; i + + ) {
2009-11-30 12:12:24 +03:00
struct ldb_dn * server_dn ;
list - > servers [ i ] . obj_guid = samdb_result_guid ( res - > msgs [ i ] ,
" objectGUID " ) ;
server_dn = samdb_result_dn ( s - > samdb , mem_ctx , res - > msgs [ i ] ,
" fromServer " , NULL ) ;
ret = dsdb_find_guid_by_dn ( s - > samdb , server_dn ,
& list - > servers [ i ] . dsa_guid ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-08-07 15:32:52 +04:00
DEBUG ( 0 , ( " Failed to find connection server's GUID by "
" DN=%s: %s \n " ,
2009-11-30 12:12:24 +03:00
ldb_dn_get_linearized ( server_dn ) ,
ldb_strerror ( ret ) ) ) ;
continue ;
}
list - > count + + ;
2009-11-30 12:11:27 +03:00
}
2009-11-30 12:12:24 +03:00
DEBUG ( 4 , ( " found %d existing nTDSConnection objects \n " , list - > count ) ) ;
2012-08-14 09:56:04 +04:00
talloc_steal ( mem_ctx , list ) ;
talloc_free ( tmp_ctx ) ;
2009-11-30 12:12:24 +03:00
return list ;
2009-11-30 12:11:27 +03:00
}