2010-10-01 23:59:22 +04:00
/*
Unix SMB / CIFS implementation .
DNS server handler for update requests
Copyright ( C ) 2010 Kai Blin < kai @ samba . org >
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 "libcli/util/ntstatus.h"
# include "librpc/ndr/libndr.h"
# include "librpc/gen_ndr/ndr_dns.h"
# include "librpc/gen_ndr/ndr_dnsp.h"
# include <ldb.h>
2011-12-16 17:25:57 +04:00
# include "param/param.h"
2012-08-03 19:59:17 +04:00
# include "param/loadparm.h"
2010-10-01 23:59:22 +04:00
# include "dsdb/samdb/samdb.h"
# include "dsdb/common/util.h"
2020-11-20 17:27:17 +03:00
# include "samba/service_task.h"
2010-10-01 23:59:22 +04:00
# include "dns_server/dns_server.h"
2012-09-07 00:40:56 +04:00
# include "auth/auth.h"
2010-10-01 23:59:22 +04:00
2013-01-14 04:14:29 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_DNS
2011-12-16 16:45:22 +04:00
static WERROR dns_rr_to_dnsp ( TALLOC_CTX * mem_ctx ,
const struct dns_res_rec * rrec ,
2018-06-07 07:51:37 +03:00
struct dnsp_DnssrvRpcRecord * r ,
bool name_is_static ) ;
2011-12-16 16:45:22 +04:00
static WERROR check_one_prerequisite ( struct dns_server * dns ,
TALLOC_CTX * mem_ctx ,
const struct dns_name_question * zone ,
const struct dns_res_rec * pr ,
bool * final_result )
2010-10-12 01:40:18 +04:00
{
2011-12-16 16:45:22 +04:00
bool match ;
WERROR werror ;
struct ldb_dn * dn ;
2010-10-12 01:40:18 +04:00
uint16_t i ;
2011-12-16 16:45:22 +04:00
bool found = false ;
struct dnsp_DnssrvRpcRecord * rec = NULL ;
struct dnsp_DnssrvRpcRecord * ans ;
2023-08-02 11:37:18 +03:00
uint16_t a_count ;
2010-10-12 01:40:18 +04:00
2011-12-16 16:45:22 +04:00
size_t host_part_len = 0 ;
2010-10-12 01:40:18 +04:00
2011-12-16 16:45:22 +04:00
* final_result = true ;
if ( pr - > ttl ! = 0 ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
match = dns_name_match ( zone - > name , pr - > name , & host_part_len ) ;
if ( ! match ) {
return DNS_ERR ( NOTZONE ) ;
}
2010-10-12 01:40:18 +04:00
2011-12-16 16:45:22 +04:00
werror = dns_name2dn ( dns , mem_ctx , pr - > name , & dn ) ;
W_ERROR_NOT_OK_RETURN ( werror ) ;
if ( pr - > rr_class = = DNS_QCLASS_ANY ) {
if ( pr - > length ! = 0 ) {
2010-10-12 01:40:18 +04:00
return DNS_ERR ( FORMAT_ERROR ) ;
}
2011-12-16 16:45:22 +04:00
if ( pr - > rr_type = = DNS_QTYPE_ALL ) {
/*
*/
2023-08-02 11:37:18 +03:00
werror = dns_lookup_records ( dns , mem_ctx , dn , & ans , & a_count ) ;
2014-07-31 10:19:50 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_DNS_ERROR_NAME_DOES_NOT_EXIST ) ) {
return DNS_ERR ( NAME_ERROR ) ;
}
2011-12-16 16:45:22 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2023-08-02 11:37:18 +03:00
if ( a_count = = 0 ) {
2010-10-12 01:40:18 +04:00
return DNS_ERR ( NAME_ERROR ) ;
2011-12-16 16:45:22 +04:00
}
} else {
/*
*/
2023-08-02 11:37:18 +03:00
werror = dns_lookup_records ( dns , mem_ctx , dn , & ans , & a_count ) ;
2014-07-31 10:19:50 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_DNS_ERROR_NAME_DOES_NOT_EXIST ) ) {
return DNS_ERR ( NXRRSET ) ;
}
2011-12-16 16:45:22 +04:00
if ( W_ERROR_EQUAL ( werror , DNS_ERR ( NAME_ERROR ) ) ) {
2010-10-12 01:40:18 +04:00
return DNS_ERR ( NXRRSET ) ;
}
2011-12-16 16:45:22 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2023-08-02 11:37:18 +03:00
for ( i = 0 ; i < a_count ; i + + ) {
2014-10-29 16:18:38 +03:00
if ( ans [ i ] . wType = = ( enum dns_record_type ) pr - > rr_type ) {
2011-12-16 16:45:22 +04:00
found = true ;
break ;
}
2010-10-12 01:40:18 +04:00
}
2011-12-16 16:45:22 +04:00
if ( ! found ) {
return DNS_ERR ( NXRRSET ) ;
}
}
/*
* RFC2136 3.2 .5 doesn ' t actually mention the need to return
* OK here , but otherwise we ' d always return a FORMAT_ERROR
* later on . This also matches Microsoft DNS behavior .
*/
return WERR_OK ;
}
if ( pr - > rr_class = = DNS_QCLASS_NONE ) {
if ( pr - > length ! = 0 ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( pr - > rr_type = = DNS_QTYPE_ALL ) {
/*
*/
2023-08-02 11:37:18 +03:00
werror = dns_lookup_records ( dns , mem_ctx , dn , & ans , & a_count ) ;
2011-12-16 16:45:22 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_OK ) ) {
2010-10-12 01:40:18 +04:00
return DNS_ERR ( YXDOMAIN ) ;
2011-12-16 16:45:22 +04:00
}
} else {
/*
*/
2023-08-02 11:37:18 +03:00
werror = dns_lookup_records ( dns , mem_ctx , dn , & ans , & a_count ) ;
2014-07-31 10:19:50 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_DNS_ERROR_NAME_DOES_NOT_EXIST ) ) {
werror = WERR_OK ;
}
2011-12-16 16:45:22 +04:00
if ( W_ERROR_EQUAL ( werror , DNS_ERR ( NAME_ERROR ) ) ) {
werror = WERR_OK ;
}
2023-08-02 11:37:18 +03:00
for ( i = 0 ; i < a_count ; i + + ) {
2014-10-29 16:18:38 +03:00
if ( ans [ i ] . wType = = ( enum dns_record_type ) pr - > rr_type ) {
2011-12-16 16:45:22 +04:00
found = true ;
break ;
}
}
if ( found ) {
2010-10-12 01:40:18 +04:00
return DNS_ERR ( YXRRSET ) ;
}
}
2011-12-16 16:45:22 +04:00
/*
* RFC2136 3.2 .5 doesn ' t actually mention the need to return
* OK here , but otherwise we ' d always return a FORMAT_ERROR
* later on . This also matches Microsoft DNS behavior .
*/
return WERR_OK ;
}
if ( pr - > rr_class ! = zone - > question_class ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
* final_result = false ;
2023-08-02 11:37:18 +03:00
werror = dns_lookup_records ( dns , mem_ctx , dn , & ans , & a_count ) ;
2014-07-31 10:19:50 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_DNS_ERROR_NAME_DOES_NOT_EXIST ) ) {
return DNS_ERR ( NXRRSET ) ;
}
2011-12-16 16:45:22 +04:00
if ( W_ERROR_EQUAL ( werror , DNS_ERR ( NAME_ERROR ) ) ) {
return DNS_ERR ( NXRRSET ) ;
}
W_ERROR_NOT_OK_RETURN ( werror ) ;
rec = talloc_zero ( mem_ctx , struct dnsp_DnssrvRpcRecord ) ;
W_ERROR_HAVE_NO_MEMORY ( rec ) ;
2023-08-02 11:37:18 +03:00
werror = dns_rr_to_dnsp ( rec , pr , rec , dns_name_is_static ( ans , a_count ) ) ;
2011-12-16 16:45:22 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2023-08-02 11:37:18 +03:00
for ( i = 0 ; i < a_count ; i + + ) {
2021-05-29 12:25:29 +03:00
if ( dns_record_match ( rec , & ans [ i ] ) ) {
2011-12-16 16:45:22 +04:00
found = true ;
break ;
}
}
if ( ! found ) {
return DNS_ERR ( NXRRSET ) ;
}
return WERR_OK ;
}
static WERROR check_prerequisites ( struct dns_server * dns ,
TALLOC_CTX * mem_ctx ,
const struct dns_name_question * zone ,
const struct dns_res_rec * prereqs , uint16_t count )
{
uint16_t i ;
WERROR final_error = WERR_OK ;
for ( i = 0 ; i < count ; i + + ) {
bool final ;
WERROR werror ;
werror = check_one_prerequisite ( dns , mem_ctx , zone ,
& prereqs [ i ] , & final ) ;
if ( ! W_ERROR_IS_OK ( werror ) ) {
if ( final ) {
return werror ;
}
if ( W_ERROR_IS_OK ( final_error ) ) {
final_error = werror ;
}
2010-10-12 01:40:18 +04:00
}
}
2011-12-16 16:45:22 +04:00
if ( ! W_ERROR_IS_OK ( final_error ) ) {
return final_error ;
}
2010-10-12 01:40:18 +04:00
return WERR_OK ;
}
2010-10-12 01:39:44 +04:00
2010-10-03 14:21:00 +04:00
static WERROR update_prescan ( const struct dns_name_question * zone ,
const struct dns_res_rec * updates , uint16_t count )
{
const struct dns_res_rec * r ;
uint16_t i ;
size_t host_part_len ;
bool match ;
for ( i = 0 ; i < count ; i + + ) {
r = & updates [ i ] ;
match = dns_name_match ( zone - > name , r - > name , & host_part_len ) ;
if ( ! match ) {
return DNS_ERR ( NOTZONE ) ;
}
if ( zone - > question_class = = r - > rr_class ) {
if ( r - > rr_type = = DNS_QTYPE_ALL ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
2011-12-16 17:07:11 +04:00
if ( r - > rr_type = = DNS_QTYPE_AXFR ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILB ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILA ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
2010-10-03 14:21:00 +04:00
} else if ( r - > rr_class = = DNS_QCLASS_ANY ) {
2011-12-16 17:07:11 +04:00
if ( r - > ttl ! = 0 ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > length ! = 0 ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_AXFR ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILB ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILA ) {
2010-10-03 14:21:00 +04:00
return DNS_ERR ( FORMAT_ERROR ) ;
}
} else if ( r - > rr_class = = DNS_QCLASS_NONE ) {
2011-12-16 17:07:11 +04:00
if ( r - > ttl ! = 0 ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_ALL ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_AXFR ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILB ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
if ( r - > rr_type = = DNS_QTYPE_MAILA ) {
2010-10-03 14:21:00 +04:00
return DNS_ERR ( FORMAT_ERROR ) ;
}
} else {
return DNS_ERR ( FORMAT_ERROR ) ;
}
}
return WERR_OK ;
}
2011-12-16 16:45:22 +04:00
static WERROR dns_rr_to_dnsp ( TALLOC_CTX * mem_ctx ,
const struct dns_res_rec * rrec ,
2018-06-07 07:51:37 +03:00
struct dnsp_DnssrvRpcRecord * r ,
bool name_is_static )
2011-12-16 16:45:22 +04:00
{
2015-08-07 12:36:47 +03:00
enum ndr_err_code ndr_err ;
2012-03-11 02:48:44 +04:00
2011-12-16 16:45:22 +04:00
if ( rrec - > rr_type = = DNS_QTYPE_ALL ) {
return DNS_ERR ( FORMAT_ERROR ) ;
}
ZERO_STRUCTP ( r ) ;
2014-10-29 16:18:38 +03:00
r - > wType = ( enum dns_record_type ) rrec - > rr_type ;
2011-12-16 16:45:22 +04:00
r - > dwTtlSeconds = rrec - > ttl ;
r - > rank = DNS_RANK_ZONE ;
2018-06-07 07:51:37 +03:00
if ( name_is_static ) {
r - > dwTimeStamp = 0 ;
} else {
2021-03-11 05:58:37 +03:00
r - > dwTimeStamp = unix_to_dns_timestamp ( time ( NULL ) ) ;
2018-06-07 07:51:37 +03:00
}
2011-12-16 16:45:22 +04:00
/* If we get QCLASS_ANY, we're done here */
if ( rrec - > rr_class = = DNS_QCLASS_ANY ) {
goto done ;
}
switch ( rrec - > rr_type ) {
case DNS_QTYPE_A :
r - > data . ipv4 = talloc_strdup ( mem_ctx , rrec - > rdata . ipv4_record ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . ipv4 ) ;
break ;
case DNS_QTYPE_AAAA :
r - > data . ipv6 = talloc_strdup ( mem_ctx , rrec - > rdata . ipv6_record ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . ipv6 ) ;
break ;
case DNS_QTYPE_NS :
r - > data . ns = talloc_strdup ( mem_ctx , rrec - > rdata . ns_record ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . ns ) ;
break ;
case DNS_QTYPE_CNAME :
r - > data . cname = talloc_strdup ( mem_ctx , rrec - > rdata . cname_record ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . cname ) ;
break ;
case DNS_QTYPE_SRV :
r - > data . srv . wPriority = rrec - > rdata . srv_record . priority ;
r - > data . srv . wWeight = rrec - > rdata . srv_record . weight ;
r - > data . srv . wPort = rrec - > rdata . srv_record . port ;
r - > data . srv . nameTarget = talloc_strdup ( mem_ctx ,
rrec - > rdata . srv_record . target ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . srv . nameTarget ) ;
break ;
2012-03-30 19:19:48 +04:00
case DNS_QTYPE_PTR :
r - > data . ptr = talloc_strdup ( mem_ctx , rrec - > rdata . ptr_record ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . ptr ) ;
break ;
2011-12-16 16:45:22 +04:00
case DNS_QTYPE_MX :
r - > data . mx . wPriority = rrec - > rdata . mx_record . preference ;
r - > data . mx . nameTarget = talloc_strdup ( mem_ctx ,
rrec - > rdata . mx_record . exchange ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > data . mx . nameTarget ) ;
break ;
case DNS_QTYPE_TXT :
2015-08-07 12:36:47 +03:00
ndr_err = ndr_dnsp_string_list_copy ( mem_ctx ,
& rrec - > rdata . txt_record . txt ,
& r - > data . txt ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2012-03-11 02:48:44 +04:00
}
2011-12-16 16:45:22 +04:00
break ;
default :
DEBUG ( 0 , ( " Got a qytpe of %d \n " , rrec - > rr_type ) ) ;
return DNS_ERR ( NOT_IMPLEMENTED ) ;
}
done :
return WERR_OK ;
}
2011-12-16 17:21:52 +04:00
static WERROR handle_one_update ( struct dns_server * dns ,
TALLOC_CTX * mem_ctx ,
const struct dns_name_question * zone ,
2012-09-07 00:40:56 +04:00
const struct dns_res_rec * update ,
const struct dns_server_tkey * tkey )
2011-12-16 17:21:52 +04:00
{
struct dnsp_DnssrvRpcRecord * recs = NULL ;
uint16_t rcount = 0 ;
struct ldb_dn * dn ;
uint16_t i ;
2014-07-31 11:35:26 +04:00
uint16_t first = 0 ;
2011-12-16 17:21:52 +04:00
WERROR werror ;
2014-07-31 11:35:26 +04:00
bool tombstoned = false ;
2011-12-16 17:21:52 +04:00
bool needs_add = false ;
2018-06-07 07:51:37 +03:00
bool name_is_static ;
2011-12-16 17:21:52 +04:00
2023-06-07 02:50:39 +03:00
DBG_NOTICE ( " Looking at record: \n " ) ;
if ( DEBUGLVL ( DBGLVL_NOTICE ) ) {
2012-03-11 03:25:05 +04:00
NDR_PRINT_DEBUG ( dns_res_rec , discard_const ( update ) ) ;
}
2011-12-16 17:21:52 +04:00
switch ( update - > rr_type ) {
case DNS_QTYPE_A :
case DNS_QTYPE_NS :
case DNS_QTYPE_CNAME :
case DNS_QTYPE_SOA :
case DNS_QTYPE_PTR :
case DNS_QTYPE_MX :
case DNS_QTYPE_AAAA :
case DNS_QTYPE_SRV :
case DNS_QTYPE_TXT :
2020-11-19 14:18:28 +03:00
case DNS_QTYPE_ALL :
2011-12-16 17:21:52 +04:00
break ;
default :
2012-03-11 02:48:44 +04:00
DEBUG ( 0 , ( " Can't handle updates of type %u yet \n " ,
update - > rr_type ) ) ;
2011-12-16 17:21:52 +04:00
return DNS_ERR ( NOT_IMPLEMENTED ) ;
}
werror = dns_name2dn ( dns , mem_ctx , update - > name , & dn ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_name2dn(): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
werror = dns_common_lookup ( dns - > samdb , mem_ctx , dn ,
& recs , & rcount , & tombstoned ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_common_lookup(): %s \n " , win_errstr ( werror ) ) ;
2014-07-31 10:19:50 +04:00
if ( W_ERROR_EQUAL ( werror , WERR_DNS_ERROR_NAME_DOES_NOT_EXIST ) ) {
2011-12-16 17:21:52 +04:00
needs_add = true ;
werror = WERR_OK ;
}
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
if ( tombstoned ) {
/*
* we need to keep the existing tombstone record
2021-03-31 04:23:36 +03:00
* and ignore it .
*
* There * should * only be a single record of type TOMBSTONE ,
* but we don ' t insist .
2014-07-31 11:35:26 +04:00
*/
2021-03-31 04:23:36 +03:00
if ( rcount ! = 1 ) {
DBG_WARNING ( " Tombstoned dnsNode has %u records, "
" expected 1 \n " , rcount ) ;
2023-06-07 02:50:39 +03:00
if ( DEBUGLVL ( DBGLVL_WARNING ) ) {
2021-03-31 04:23:36 +03:00
NDR_PRINT_DEBUG ( dns_res_rec , discard_const ( update ) ) ;
}
}
2014-07-31 11:35:26 +04:00
first = rcount ;
}
2018-06-07 07:51:37 +03:00
name_is_static = dns_name_is_static ( recs , rcount ) ;
2011-12-16 17:21:52 +04:00
if ( update - > rr_class = = zone - > question_class ) {
if ( update - > rr_type = = DNS_QTYPE_CNAME ) {
/*
* If there is a record in the directory
* that ' s not a CNAME , ignore update
*/
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2011-12-16 17:21:52 +04:00
if ( recs [ i ] . wType ! = DNS_TYPE_CNAME ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 5 , ( " Skipping update \n " ) ) ;
2011-12-16 17:21:52 +04:00
return WERR_OK ;
}
}
/*
* There should be no entries besides one CNAME record
* per name , so replace everything with the new CNAME
*/
2014-07-31 11:35:26 +04:00
rcount = first ;
2011-12-16 17:21:52 +04:00
recs = talloc_realloc ( mem_ctx , recs ,
2014-07-31 11:35:26 +04:00
struct dnsp_DnssrvRpcRecord , rcount + 1 ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_HAVE_NO_MEMORY ( recs ) ;
2018-06-07 07:51:37 +03:00
werror = dns_rr_to_dnsp (
recs , update , & recs [ rcount ] , name_is_static ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_rr_to_dnsp(CNAME): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
rcount + = 1 ;
2011-12-16 17:21:52 +04:00
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(CNAME): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
return WERR_OK ;
} else {
/*
* If there is a CNAME record for this name ,
* ignore update
*/
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2011-12-16 17:21:52 +04:00
if ( recs [ i ] . wType = = DNS_TYPE_CNAME ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 5 , ( " Skipping update \n " ) ) ;
2011-12-16 17:21:52 +04:00
return WERR_OK ;
}
}
}
if ( update - > rr_type = = DNS_QTYPE_SOA ) {
bool found = false ;
/*
* If the zone has no SOA record ? ? or update ' s
* serial number is smaller than existing SOA ' s ,
* ignore update
*/
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2011-12-16 17:21:52 +04:00
if ( recs [ i ] . wType = = DNS_TYPE_SOA ) {
uint16_t n , o ;
n = update - > rdata . soa_record . serial ;
o = recs [ i ] . data . soa . serial ;
/*
* TODO : Implement RFC 1982 comparison
* logic for RFC2136
*/
if ( n < = o ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 5 , ( " Skipping update \n " ) ) ;
2011-12-16 17:21:52 +04:00
return WERR_OK ;
}
found = true ;
break ;
}
}
if ( ! found ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 5 , ( " Skipping update \n " ) ) ;
2011-12-16 17:21:52 +04:00
return WERR_OK ;
}
2018-06-07 07:51:37 +03:00
werror = dns_rr_to_dnsp (
mem_ctx , update , & recs [ i ] , name_is_static ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_rr_to_dnsp(SOA): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2021-03-31 04:23:36 +03:00
/*
* There should only be one SOA , which we have already
* found and replaced . We now check for and tombstone
* any others .
*/
2011-12-16 17:21:52 +04:00
for ( i + + ; i < rcount ; i + + ) {
if ( recs [ i ] . wType ! = DNS_TYPE_SOA ) {
continue ;
}
2021-03-31 04:23:36 +03:00
DBG_ERR ( " Duplicate SOA records found. \n " ) ;
2023-06-07 02:50:39 +03:00
if ( DEBUGLVL ( DBGLVL_ERR ) ) {
2021-03-31 04:23:36 +03:00
NDR_PRINT_DEBUG ( dns_res_rec ,
discard_const ( update ) ) ;
}
2014-07-31 11:32:00 +04:00
recs [ i ] = ( struct dnsp_DnssrvRpcRecord ) {
. wType = DNS_TYPE_TOMBSTONE ,
} ;
2011-12-16 17:21:52 +04:00
}
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(SOA): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
return WERR_OK ;
}
2021-04-11 14:38:10 +03:00
/* All but CNAME, SOA */
2011-12-16 17:21:52 +04:00
recs = talloc_realloc ( mem_ctx , recs ,
struct dnsp_DnssrvRpcRecord , rcount + 1 ) ;
W_ERROR_HAVE_NO_MEMORY ( recs ) ;
2018-06-07 07:51:37 +03:00
werror =
dns_rr_to_dnsp ( recs , update , & recs [ rcount ] , name_is_static ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_rr_to_dnsp(GENERIC): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2024-05-30 15:52:22 +03:00
struct dnsp_DnssrvRpcRecord orig_rec = recs [ i ] ;
2021-05-29 12:25:29 +03:00
if ( ! dns_record_match ( & recs [ i ] , & recs [ rcount ] ) ) {
2011-12-16 17:21:52 +04:00
continue ;
}
2018-07-02 04:43:33 +03:00
recs [ i ] . data = recs [ rcount ] . data ;
recs [ i ] . wType = recs [ rcount ] . wType ;
recs [ i ] . dwTtlSeconds = recs [ rcount ] . dwTtlSeconds ;
recs [ i ] . rank = recs [ rcount ] . rank ;
2021-05-26 06:01:36 +03:00
recs [ i ] . dwReserved = 0 ;
recs [ i ] . flags = 0 ;
2011-12-16 17:21:52 +04:00
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(REPLACE): %s \n " , win_errstr ( werror ) ) ;
2024-05-30 15:52:22 +03:00
if ( W_ERROR_EQUAL ( werror , WERR_ACCESS_DENIED ) & &
! needs_add & &
orig_rec . dwTtlSeconds = = recs [ i ] . dwTtlSeconds )
{
DBG_NOTICE ( " dns_replace_records(REPLACE): %s "
" => skip no-op \n " ,
win_errstr ( werror ) ) ;
werror = WERR_OK ;
}
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
return WERR_OK ;
}
2021-04-11 14:38:10 +03:00
/* we did not find a matching record. This is new. */
2011-12-16 17:21:52 +04:00
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount + 1 ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(ADD): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
return WERR_OK ;
} else if ( update - > rr_class = = DNS_QCLASS_ANY ) {
2021-04-11 14:38:10 +03:00
/*
* Mass - deleting records by type , which we do by adding a
* tombstone with zero timestamp . dns_replace_records ( ) will
* work out if the node as a whole needs tombstoning .
*/
2011-12-16 17:21:52 +04:00
if ( update - > rr_type = = DNS_QTYPE_ALL ) {
s4:dnsserver: Rename dns_name_equal() to samba_dns_name_equal()
This function already exists in bind9 but takes different arguments, so when
the DLZ is loaded and this function is called bind crashes:
named[1523]: samba_dlz: allowing update of signer=DESKTOP-8BUKMBK\$\@AFOREST.AD name=118.101.168.192.in-addr.arpa tcpaddr=192.168.101.118 type=PTR key=1264-ms-7.1-2ac9.9ef238e1-9747-11ed-9f95-525400dc6981/159/0
named[1523]: samba_dlz: allowing update of signer=DESKTOP-8BUKMBK\$\@AFOREST.AD name=118.101.168.192.in-addr.arpa tcpaddr=192.168.101.118 type=PTR key=1264-ms-7.1-2ac9.9ef238e1-9747-11ed-9f95-525400dc6981/159/0
named[1523]: client @0x7f26caa90f68 192.168.101.118#58223/key DESKTOP-8BUKMBK\$\@AFOREST.AD: updating zone '101.168.192.in-addr.arpa/NONE': deleting rrset at '118.101.168.192.in-addr.ar
named[1523]: name.c:664: REQUIRE(((name1) != ((void *)0) && ((const isc__magic_t *)(name1))->magic == ((('D') << 24 | ('N') << 16 | ('S') << 8 | ('n'))))) failed, back trace
Backtrace:
#0 0x00007f2716c957ec in __pthread_kill_implementation () from /lib64/libc.so.6
#1 0x00007f2716c42816 in raise () from /lib64/libc.so.6
#2 0x00007f2716c2b81c in abort () from /lib64/libc.so.6
#3 0x000055d4de847995 in assertion_failed (file=<optimized out>, line=<optimized out>,
type=<optimized out>, cond=<optimized out>) at /usr/src/debug/bind-9.18.10/bin/named/main.c:237
#4 0x00007f27176388fc in isc_assertion_failed (file=file@entry=0x7f27173b0df6 "name.c",
line=line@entry=664, type=type@entry=isc_assertiontype_require,
cond=cond@entry=0x7f27173b0268 "((name1) != ((void *)0) && ((const isc__magic_t *)(name1))->magic == ((('D') << 24 | ('N') << 16 | ('S') << 8 | ('n'))))")
at /usr/src/debug/bind-9.18.10/lib/isc/assertions.c:48
#5 0x00007f27172946f9 in dns_name_equal (name1=<optimized out>, name2=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/dns/name.c:664
**** Here bind's dns_name_equal() is called instead of samba's dns_name_equal() ****
#6 0x00007f27077ad6f2 in dns_record_match (rec1=0x7f26f8042d70, rec2=0x7f26f8044d10)
at ../../source4/dns_server/dnsserver_common.c:1346
#7 0x00007f271404732c in b9_record_match (rec1=0x7f26f8042d70, rec2=0x7f26f8044d10)
at ../../source4/dns_server/dlz_bind9.c:1830
#8 0x00007f2714047daa in dlz_subrdataset (name=0x7f2706ff82f0 "118.101.168.192.in-addr.arpa",
rdatastr=0x7f26c9c10000 "118.101.168.192.in-addr.arpa.\t1200\tIN\tPTR\tDESKTOP-8BUKMBK.aforest.ad.",
dbdata=0x7f271003d300, version=0x7f26f8044b20) at ../../source4/dns_server/dlz_bind9.c:2077
#9 0x000055d4de84afb4 in dlopen_dlz_subrdataset (name=0x7f2706ff82f0 "118.101.168.192.in-addr.arpa",
rdatastr=<optimized out>, driverarg=<optimized out>, dbdata=0x7f270430f680, version=<optimized out>)
at /usr/src/debug/bind-9.18.10/bin/named/dlz_dlopen_driver.c:483
#10 0x00007f271738e734 in modrdataset.constprop.0 (db=0x7f2704291740, node=0x7f26c9c006e0,
version=0x7f26f8044b20, rdataset=0x7f2706ff8830,
mod_function=0x55d4de84af80 <dlopen_dlz_subrdataset>, options=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/dns/sdlz.c:1107
#11 0x00007f2717251855 in diff_apply (diff=diff@entry=0x7f2706ff8df0, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20, warn=warn@entry=true) at /usr/src/debug/bind-9.18.10/lib/dns/diff.c:370
#12 0x00007f2717251c8a in dns_diff_apply (diff=diff@entry=0x7f2706ff8df0, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20) at /usr/src/debug/bind-9.18.10/lib/dns/diff.c:465
#13 0x00007f2717d105aa in do_one_tuple (tuple=tuple@entry=0x7f2706ff8e50, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20, diff=diff@entry=0x7f2706ff9400)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:454
#14 0x00007f2717d10fff in update_one_rr (rdata=0x7f2706ff8ee8, ttl=<optimized out>,
name=<optimized out>, op=DNS_DIFFOP_DEL, diff=0x7f2706ff9400, ver=0x7f26f8044b20, db=0x7f2704291740)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:505
#15 delete_if_action (data=<optimized out>, rr=0x7f2706ff8ee0)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:1427
#16 0x00007f2717d10ccd in foreach_rr (db=0x7f2704291740, ver=<optimized out>, name=0x7f26caa61d00,
type=<optimized out>, covers=<optimized out>,
rr_action=rr_action@entry=0x7f2717d10f60 <delete_if_action>, rr_action_data=0x7f2706ff9280)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:736
#17 0x00007f2717d10e76 in delete_if (predicate=predicate@entry=0x7f2717d0fb10 <true_p>,
db=<optimized out>, ver=<optimized out>, name=<optimized out>, type=<optimized out>,
covers=<optimized out>, update_rr=0x7f2706ff94b0, diff=0x7f2706ff9400)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:1454
#18 0x00007f2717d1bccd in update_action (task=<optimized out>, event=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:3299
#19 0x00007f271765eb4c in task_run (task=0x7f27155ccf00)
at /usr/src/debug/bind-9.18.10/lib/isc/task.c:823
#20 isc_task_run (task=0x7f27155ccf00) at /usr/src/debug/bind-9.18.10/lib/isc/task.c:904
#21 0x00007f271762cb12 in isc__nm_async_task (worker=0x7f2716236560, ev0=0x7f26caa07000)
at netmgr/netmgr.c:840
#22 process_netievent (worker=worker@entry=0x7f2716236560, ievent=0x7f26caa07000) at netmgr/netmgr.c:918
#23 0x00007f271762d197 in process_queue (worker=worker@entry=0x7f2716236560,
type=type@entry=NETIEVENT_TASK) at netmgr/netmgr.c:1011
#24 0x00007f271762d3b3 in process_all_queues (worker=0x7f2716236560) at netmgr/netmgr.c:765
#25 async_cb (handle=0x7f27162368c0) at netmgr/netmgr.c:794
#26 0x00007f2717c4cb0d in uv__async_io (loop=0x7f2716236570, w=<optimized out>, events=<optimized out>)
at src/unix/async.c:163
#27 0x00007f2717c6825d in uv__io_poll (loop=0x7f2716236570, timeout=<optimized out>)
at src/unix/epoll.c:374
#28 0x00007f2717c5247a in uv__io_poll (timeout=<optimized out>, loop=0x7f2716236570)
at src/unix/udp.c:122
#29 uv_run (loop=loop@entry=0x7f2716236570, mode=mode@entry=UV_RUN_DEFAULT) at src/unix/core.c:406
#30 0x00007f271762d834 in nm_thread (worker0=0x7f2716236560) at netmgr/netmgr.c:696
#31 0x00007f27176627f5 in isc__trampoline_run (arg=0x55d4dfe3ad70)
at /usr/src/debug/bind-9.18.10/lib/isc/trampoline.c:189
#32 0x00007f2716c9398d in start_thread () from /lib64/libc.so.6
#33 0x00007f2716d19344 in clone () from /lib64/libc.so.6
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14030
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Samuel Cabrero <scabrero@samba.org>
Autobuild-Date(master): Thu Jan 19 10:20:27 UTC 2023 on atb-devel-224
2023-01-18 19:25:29 +03:00
if ( samba_dns_name_equal ( update - > name , zone - > name ) ) {
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2011-12-16 17:21:52 +04:00
if ( recs [ i ] . wType = = DNS_TYPE_SOA ) {
continue ;
}
if ( recs [ i ] . wType = = DNS_TYPE_NS ) {
continue ;
}
2014-07-31 11:32:00 +04:00
recs [ i ] = ( struct dnsp_DnssrvRpcRecord ) {
. wType = DNS_TYPE_TOMBSTONE ,
} ;
2011-12-16 17:21:52 +04:00
}
} else {
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2014-07-31 11:32:00 +04:00
recs [ i ] = ( struct dnsp_DnssrvRpcRecord ) {
. wType = DNS_TYPE_TOMBSTONE ,
} ;
2011-12-16 17:21:52 +04:00
}
}
s4:dnsserver: Rename dns_name_equal() to samba_dns_name_equal()
This function already exists in bind9 but takes different arguments, so when
the DLZ is loaded and this function is called bind crashes:
named[1523]: samba_dlz: allowing update of signer=DESKTOP-8BUKMBK\$\@AFOREST.AD name=118.101.168.192.in-addr.arpa tcpaddr=192.168.101.118 type=PTR key=1264-ms-7.1-2ac9.9ef238e1-9747-11ed-9f95-525400dc6981/159/0
named[1523]: samba_dlz: allowing update of signer=DESKTOP-8BUKMBK\$\@AFOREST.AD name=118.101.168.192.in-addr.arpa tcpaddr=192.168.101.118 type=PTR key=1264-ms-7.1-2ac9.9ef238e1-9747-11ed-9f95-525400dc6981/159/0
named[1523]: client @0x7f26caa90f68 192.168.101.118#58223/key DESKTOP-8BUKMBK\$\@AFOREST.AD: updating zone '101.168.192.in-addr.arpa/NONE': deleting rrset at '118.101.168.192.in-addr.ar
named[1523]: name.c:664: REQUIRE(((name1) != ((void *)0) && ((const isc__magic_t *)(name1))->magic == ((('D') << 24 | ('N') << 16 | ('S') << 8 | ('n'))))) failed, back trace
Backtrace:
#0 0x00007f2716c957ec in __pthread_kill_implementation () from /lib64/libc.so.6
#1 0x00007f2716c42816 in raise () from /lib64/libc.so.6
#2 0x00007f2716c2b81c in abort () from /lib64/libc.so.6
#3 0x000055d4de847995 in assertion_failed (file=<optimized out>, line=<optimized out>,
type=<optimized out>, cond=<optimized out>) at /usr/src/debug/bind-9.18.10/bin/named/main.c:237
#4 0x00007f27176388fc in isc_assertion_failed (file=file@entry=0x7f27173b0df6 "name.c",
line=line@entry=664, type=type@entry=isc_assertiontype_require,
cond=cond@entry=0x7f27173b0268 "((name1) != ((void *)0) && ((const isc__magic_t *)(name1))->magic == ((('D') << 24 | ('N') << 16 | ('S') << 8 | ('n'))))")
at /usr/src/debug/bind-9.18.10/lib/isc/assertions.c:48
#5 0x00007f27172946f9 in dns_name_equal (name1=<optimized out>, name2=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/dns/name.c:664
**** Here bind's dns_name_equal() is called instead of samba's dns_name_equal() ****
#6 0x00007f27077ad6f2 in dns_record_match (rec1=0x7f26f8042d70, rec2=0x7f26f8044d10)
at ../../source4/dns_server/dnsserver_common.c:1346
#7 0x00007f271404732c in b9_record_match (rec1=0x7f26f8042d70, rec2=0x7f26f8044d10)
at ../../source4/dns_server/dlz_bind9.c:1830
#8 0x00007f2714047daa in dlz_subrdataset (name=0x7f2706ff82f0 "118.101.168.192.in-addr.arpa",
rdatastr=0x7f26c9c10000 "118.101.168.192.in-addr.arpa.\t1200\tIN\tPTR\tDESKTOP-8BUKMBK.aforest.ad.",
dbdata=0x7f271003d300, version=0x7f26f8044b20) at ../../source4/dns_server/dlz_bind9.c:2077
#9 0x000055d4de84afb4 in dlopen_dlz_subrdataset (name=0x7f2706ff82f0 "118.101.168.192.in-addr.arpa",
rdatastr=<optimized out>, driverarg=<optimized out>, dbdata=0x7f270430f680, version=<optimized out>)
at /usr/src/debug/bind-9.18.10/bin/named/dlz_dlopen_driver.c:483
#10 0x00007f271738e734 in modrdataset.constprop.0 (db=0x7f2704291740, node=0x7f26c9c006e0,
version=0x7f26f8044b20, rdataset=0x7f2706ff8830,
mod_function=0x55d4de84af80 <dlopen_dlz_subrdataset>, options=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/dns/sdlz.c:1107
#11 0x00007f2717251855 in diff_apply (diff=diff@entry=0x7f2706ff8df0, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20, warn=warn@entry=true) at /usr/src/debug/bind-9.18.10/lib/dns/diff.c:370
#12 0x00007f2717251c8a in dns_diff_apply (diff=diff@entry=0x7f2706ff8df0, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20) at /usr/src/debug/bind-9.18.10/lib/dns/diff.c:465
#13 0x00007f2717d105aa in do_one_tuple (tuple=tuple@entry=0x7f2706ff8e50, db=db@entry=0x7f2704291740,
ver=ver@entry=0x7f26f8044b20, diff=diff@entry=0x7f2706ff9400)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:454
#14 0x00007f2717d10fff in update_one_rr (rdata=0x7f2706ff8ee8, ttl=<optimized out>,
name=<optimized out>, op=DNS_DIFFOP_DEL, diff=0x7f2706ff9400, ver=0x7f26f8044b20, db=0x7f2704291740)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:505
#15 delete_if_action (data=<optimized out>, rr=0x7f2706ff8ee0)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:1427
#16 0x00007f2717d10ccd in foreach_rr (db=0x7f2704291740, ver=<optimized out>, name=0x7f26caa61d00,
type=<optimized out>, covers=<optimized out>,
rr_action=rr_action@entry=0x7f2717d10f60 <delete_if_action>, rr_action_data=0x7f2706ff9280)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:736
#17 0x00007f2717d10e76 in delete_if (predicate=predicate@entry=0x7f2717d0fb10 <true_p>,
db=<optimized out>, ver=<optimized out>, name=<optimized out>, type=<optimized out>,
covers=<optimized out>, update_rr=0x7f2706ff94b0, diff=0x7f2706ff9400)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:1454
#18 0x00007f2717d1bccd in update_action (task=<optimized out>, event=<optimized out>)
at /usr/src/debug/bind-9.18.10/lib/ns/update.c:3299
#19 0x00007f271765eb4c in task_run (task=0x7f27155ccf00)
at /usr/src/debug/bind-9.18.10/lib/isc/task.c:823
#20 isc_task_run (task=0x7f27155ccf00) at /usr/src/debug/bind-9.18.10/lib/isc/task.c:904
#21 0x00007f271762cb12 in isc__nm_async_task (worker=0x7f2716236560, ev0=0x7f26caa07000)
at netmgr/netmgr.c:840
#22 process_netievent (worker=worker@entry=0x7f2716236560, ievent=0x7f26caa07000) at netmgr/netmgr.c:918
#23 0x00007f271762d197 in process_queue (worker=worker@entry=0x7f2716236560,
type=type@entry=NETIEVENT_TASK) at netmgr/netmgr.c:1011
#24 0x00007f271762d3b3 in process_all_queues (worker=0x7f2716236560) at netmgr/netmgr.c:765
#25 async_cb (handle=0x7f27162368c0) at netmgr/netmgr.c:794
#26 0x00007f2717c4cb0d in uv__async_io (loop=0x7f2716236570, w=<optimized out>, events=<optimized out>)
at src/unix/async.c:163
#27 0x00007f2717c6825d in uv__io_poll (loop=0x7f2716236570, timeout=<optimized out>)
at src/unix/epoll.c:374
#28 0x00007f2717c5247a in uv__io_poll (timeout=<optimized out>, loop=0x7f2716236570)
at src/unix/udp.c:122
#29 uv_run (loop=loop@entry=0x7f2716236570, mode=mode@entry=UV_RUN_DEFAULT) at src/unix/core.c:406
#30 0x00007f271762d834 in nm_thread (worker0=0x7f2716236560) at netmgr/netmgr.c:696
#31 0x00007f27176627f5 in isc__trampoline_run (arg=0x55d4dfe3ad70)
at /usr/src/debug/bind-9.18.10/lib/isc/trampoline.c:189
#32 0x00007f2716c9398d in start_thread () from /lib64/libc.so.6
#33 0x00007f2716d19344 in clone () from /lib64/libc.so.6
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14030
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Samuel Cabrero <scabrero@samba.org>
Autobuild-Date(master): Thu Jan 19 10:20:27 UTC 2023 on atb-devel-224
2023-01-18 19:25:29 +03:00
} else if ( samba_dns_name_equal ( update - > name , zone - > name ) ) {
2011-12-16 17:21:52 +04:00
if ( update - > rr_type = = DNS_QTYPE_SOA ) {
return WERR_OK ;
}
if ( update - > rr_type = = DNS_QTYPE_NS ) {
return WERR_OK ;
}
}
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2014-10-29 16:18:38 +03:00
if ( recs [ i ] . wType = = ( enum dns_record_type ) update - > rr_type ) {
2014-07-31 11:32:00 +04:00
recs [ i ] = ( struct dnsp_DnssrvRpcRecord ) {
. wType = DNS_TYPE_TOMBSTONE ,
} ;
2011-12-16 17:21:52 +04:00
}
}
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(DELETE-ANY): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
return WERR_OK ;
} else if ( update - > rr_class = = DNS_QCLASS_NONE ) {
2021-04-11 14:38:10 +03:00
/* deleting individual records */
2011-12-16 17:21:52 +04:00
struct dnsp_DnssrvRpcRecord * del_rec ;
if ( update - > rr_type = = DNS_QTYPE_SOA ) {
return WERR_OK ;
}
if ( update - > rr_type = = DNS_QTYPE_NS ) {
bool found = false ;
struct dnsp_DnssrvRpcRecord * ns_rec = talloc ( mem_ctx ,
struct dnsp_DnssrvRpcRecord ) ;
W_ERROR_HAVE_NO_MEMORY ( ns_rec ) ;
2018-06-07 07:51:37 +03:00
werror = dns_rr_to_dnsp (
ns_rec , update , ns_rec , name_is_static ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_rr_to_dnsp(NS): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2021-05-29 12:25:29 +03:00
if ( dns_record_match ( ns_rec , & recs [ i ] ) ) {
2011-12-16 17:21:52 +04:00
found = true ;
break ;
}
}
if ( found ) {
return WERR_OK ;
}
}
del_rec = talloc ( mem_ctx , struct dnsp_DnssrvRpcRecord ) ;
W_ERROR_HAVE_NO_MEMORY ( del_rec ) ;
2018-06-07 07:51:37 +03:00
werror =
dns_rr_to_dnsp ( del_rec , update , del_rec , name_is_static ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_rr_to_dnsp(DELETE-NONE): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2014-07-31 11:35:26 +04:00
for ( i = first ; i < rcount ; i + + ) {
2021-05-29 12:25:29 +03:00
if ( dns_record_match ( del_rec , & recs [ i ] ) ) {
2014-07-31 11:32:00 +04:00
recs [ i ] = ( struct dnsp_DnssrvRpcRecord ) {
. wType = DNS_TYPE_TOMBSTONE ,
} ;
2011-12-16 17:21:52 +04:00
}
}
2012-03-11 03:25:57 +04:00
werror = dns_replace_records ( dns , mem_ctx , dn ,
needs_add , recs , rcount ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_replace_records(DELETE-NONE): %s \n " , win_errstr ( werror ) ) ;
2012-03-11 03:25:57 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2011-12-16 17:21:52 +04:00
}
return WERR_OK ;
}
static WERROR handle_updates ( struct dns_server * dns ,
TALLOC_CTX * mem_ctx ,
const struct dns_name_question * zone ,
const struct dns_res_rec * prereqs , uint16_t pcount ,
2012-09-07 00:40:56 +04:00
struct dns_res_rec * updates , uint16_t upd_count ,
struct dns_server_tkey * tkey )
2011-12-16 17:21:52 +04:00
{
struct ldb_dn * zone_dn = NULL ;
WERROR werror = WERR_OK ;
int ret ;
uint16_t ri ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2012-09-11 14:59:51 +04:00
if ( tkey ! = NULL ) {
2018-05-31 06:12:46 +03:00
ret = ldb_set_opaque (
dns - > samdb ,
DSDB_SESSION_INFO ,
tkey - > session_info ) ;
2012-09-11 14:59:51 +04:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 1 , ( " unable to set session info \n " ) ) ;
werror = DNS_ERR ( SERVER_FAILURE ) ;
goto failed ;
}
}
2011-12-16 17:21:52 +04:00
werror = dns_name2dn ( dns , tmp_ctx , zone - > name , & zone_dn ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " dns_name2dn(): %s \n " , win_errstr ( werror ) ) ;
2012-09-11 14:59:51 +04:00
W_ERROR_NOT_OK_GOTO ( werror , failed ) ;
2011-12-16 17:21:52 +04:00
ret = ldb_transaction_start ( dns - > samdb ) ;
if ( ret ! = LDB_SUCCESS ) {
2012-09-11 14:59:51 +04:00
werror = DNS_ERR ( SERVER_FAILURE ) ;
goto failed ;
2011-12-16 17:21:52 +04:00
}
werror = check_prerequisites ( dns , tmp_ctx , zone , prereqs , pcount ) ;
W_ERROR_NOT_OK_GOTO ( werror , failed ) ;
2016-11-11 10:48:04 +03:00
DBG_DEBUG ( " dns update count is %u \n " , upd_count ) ;
2011-12-16 17:21:52 +04:00
for ( ri = 0 ; ri < upd_count ; ri + + ) {
werror = handle_one_update ( dns , tmp_ctx , zone ,
2012-09-07 00:40:56 +04:00
& updates [ ri ] , tkey ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " handle_one_update(%u): %s \n " ,
ri , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_GOTO ( werror , failed ) ;
}
failed :
2023-10-06 01:15:38 +03:00
if ( W_ERROR_IS_OK ( werror ) ) {
2023-10-06 01:16:37 +03:00
ret = ldb_transaction_commit ( dns - > samdb ) ;
if ( ret ! = LDB_SUCCESS ) {
werror = DNS_ERR ( SERVER_FAILURE ) ;
}
2023-10-06 01:15:38 +03:00
} else {
ldb_transaction_cancel ( dns - > samdb ) ;
}
2012-09-11 14:59:51 +04:00
if ( tkey ! = NULL ) {
2018-05-31 06:12:46 +03:00
ldb_set_opaque (
dns - > samdb ,
DSDB_SESSION_INFO ,
system_session ( dns - > task - > lp_ctx ) ) ;
2012-09-11 14:59:51 +04:00
}
2011-12-16 17:21:52 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return werror ;
}
2012-09-07 00:40:56 +04:00
static WERROR dns_update_allowed ( struct dns_server * dns ,
2014-10-14 11:30:43 +04:00
const struct dns_request_state * state ,
2012-09-07 00:40:56 +04:00
struct dns_server_tkey * * tkey )
{
if ( lpcfg_allow_dns_updates ( dns - > task - > lp_ctx ) = = DNS_UPDATE_ON ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 2 , ( " All updates allowed. \n " ) ) ;
2012-09-07 00:40:56 +04:00
return WERR_OK ;
}
if ( lpcfg_allow_dns_updates ( dns - > task - > lp_ctx ) = = DNS_UPDATE_OFF ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 2 , ( " Updates disabled. \n " ) ) ;
2012-09-07 00:40:56 +04:00
return DNS_ERR ( REFUSED ) ;
}
if ( state - > authenticated = = false ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 2 , ( " Update not allowed for unsigned packet. \n " ) ) ;
2012-09-07 00:40:56 +04:00
return DNS_ERR ( REFUSED ) ;
}
* tkey = dns_find_tkey ( dns - > tkeys , state - > key_name ) ;
if ( * tkey = = NULL ) {
DEBUG ( 0 , ( " Authenticated, but key not found. Something is wrong. \n " ) ) ;
return DNS_ERR ( REFUSED ) ;
}
return WERR_OK ;
}
2010-10-12 01:39:44 +04:00
WERROR dns_server_process_update ( struct dns_server * dns ,
2014-10-14 11:30:43 +04:00
const struct dns_request_state * state ,
2010-10-12 01:39:44 +04:00
TALLOC_CTX * mem_ctx ,
2014-10-14 11:30:43 +04:00
const struct dns_name_packet * in ,
2011-12-16 16:45:22 +04:00
struct dns_res_rec * * prereqs , uint16_t * prereq_count ,
2011-12-09 03:58:32 +04:00
struct dns_res_rec * * updates , uint16_t * update_count ,
struct dns_res_rec * * additional , uint16_t * arcount )
2010-10-01 23:59:22 +04:00
{
struct dns_name_question * zone ;
const struct dns_server_zone * z ;
size_t host_part_len = 0 ;
2010-10-03 02:40:32 +04:00
WERROR werror = DNS_ERR ( NOT_IMPLEMENTED ) ;
2012-09-07 00:40:56 +04:00
struct dns_server_tkey * tkey = NULL ;
2010-10-01 23:59:22 +04:00
if ( in - > qdcount ! = 1 ) {
2010-10-12 01:39:44 +04:00
return DNS_ERR ( FORMAT_ERROR ) ;
2010-10-01 23:59:22 +04:00
}
2011-12-09 03:59:34 +04:00
zone = & in - > questions [ 0 ] ;
2010-10-01 23:59:22 +04:00
2011-12-09 04:26:39 +04:00
if ( zone - > question_class ! = DNS_QCLASS_IN & &
zone - > question_class ! = DNS_QCLASS_ANY ) {
return DNS_ERR ( NOT_IMPLEMENTED ) ;
}
2010-10-01 23:59:22 +04:00
if ( zone - > question_type ! = DNS_QTYPE_SOA ) {
2010-10-12 01:39:44 +04:00
return DNS_ERR ( FORMAT_ERROR ) ;
2010-10-01 23:59:22 +04:00
}
2012-03-11 03:25:05 +04:00
DEBUG ( 2 , ( " Got a dns update request. \n " ) ) ;
2010-10-01 23:59:22 +04:00
for ( z = dns - > zones ; z ! = NULL ; z = z - > next ) {
bool match ;
match = dns_name_match ( z - > name , zone - > name , & host_part_len ) ;
if ( match ) {
break ;
}
}
if ( z = = NULL ) {
2012-09-07 00:53:32 +04:00
DEBUG ( 1 , ( " We're not authoritative for this zone \n " ) ) ;
2010-10-12 01:39:44 +04:00
return DNS_ERR ( NOTAUTH ) ;
2010-10-01 23:59:22 +04:00
}
if ( host_part_len ! = 0 ) {
2010-10-12 01:40:18 +04:00
/* TODO: We need to delegate this one */
2012-09-11 00:16:54 +04:00
DEBUG ( 1 , ( " Would have to delegate zone '%s'. \n " , zone - > name ) ) ;
2010-10-12 01:39:44 +04:00
return DNS_ERR ( NOT_IMPLEMENTED ) ;
2010-10-01 23:59:22 +04:00
}
2011-12-16 16:45:22 +04:00
* prereq_count = in - > ancount ;
* prereqs = in - > answers ;
werror = check_prerequisites ( dns , mem_ctx , in - > questions , * prereqs ,
* prereq_count ) ;
2010-10-12 01:40:18 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2012-09-07 00:40:56 +04:00
werror = dns_update_allowed ( dns , state , & tkey ) ;
if ( ! W_ERROR_IS_OK ( werror ) ) {
return werror ;
2012-09-05 03:27:00 +04:00
}
2010-10-03 02:40:32 +04:00
2011-12-16 17:07:11 +04:00
* update_count = in - > nscount ;
* updates = in - > nsrecs ;
2010-10-03 14:21:00 +04:00
werror = update_prescan ( in - > questions , * updates , * update_count ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " update_prescan(): %s \n " , win_errstr ( werror ) ) ;
2010-10-03 14:21:00 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2011-12-16 17:21:52 +04:00
werror = handle_updates ( dns , mem_ctx , in - > questions , * prereqs ,
2012-09-07 00:40:56 +04:00
* prereq_count , * updates , * update_count , tkey ) ;
2022-07-14 13:00:51 +03:00
DBG_DEBUG ( " handle_updates(): %s \n " , win_errstr ( werror ) ) ;
2011-12-16 17:21:52 +04:00
W_ERROR_NOT_OK_RETURN ( werror ) ;
2010-10-12 01:40:18 +04:00
return werror ;
2010-10-01 23:59:22 +04:00
}