Changeset 988 for vendor/current/source4/dns_server
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source4/dns_server
- Files:
-
- 4 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/dns_server/TODO
r740 r988 4 4 Just so we don't forget the required features for an AD-compatible DNS server: 5 5 6 - Forwarding to other nameservers if we don't know the domain 7 - Additional record handling (especially in SOA records, but we'll want off of 8 this stuff) 9 - TSIG-GSSAPI handling 10 - Symmetric Bind-style key handling (not strictly needed for AD, but needed for 6 - Symmetric Bind-style TKEY handling (not strictly needed for AD, but needed for 11 7 integration to other name servers / tools) 12 - Command line tools that unix admins are used to 13 - Zone transfer support (XFER, IFER) 8 (- Command line tools that unix admins are used to) 9 - Zone transfer support (XFER, IFER) (look at AD for permission settings) 14 10 - Caching 15 - Tests, tests, tests (probably based on python's dns implementation) 11 - dynamic zone reloading 12 - Tests, tests, tests -
vendor/current/source4/dns_server/dlz_bind9.c
r740 r988 26 26 #include "dsdb/samdb/samdb.h" 27 27 #include "dsdb/common/util.h" 28 #include "auth/auth.h" 28 29 #include "auth/session.h" 29 30 #include "auth/gensec/gensec.h" 31 #include "librpc/gen_ndr/security.h" 32 #include "auth/credentials/credentials.h" 33 #include "system/kerberos.h" 34 #include "auth/kerberos/kerberos.h" 30 35 #include "gen_ndr/ndr_dnsp.h" 31 #include "lib/cmdline/popt_common.h" 32 #include "lib/cmdline/popt_credentials.h" 33 #include "ldb_module.h" 36 #include "gen_ndr/server_id.h" 37 #include "messaging/messaging.h" 38 #include <popt.h> 39 #include "lib/util/dlinklist.h" 34 40 #include "dlz_minimal.h" 41 #include "dns_server/dnsserver_common.h" 42 43 struct b9_options { 44 const char *url; 45 const char *debug; 46 }; 47 48 struct b9_zone { 49 char *name; 50 struct b9_zone *prev, *next; 51 }; 35 52 36 53 struct dlz_bind9_data { 54 struct b9_options options; 37 55 struct ldb_context *samdb; 38 56 struct tevent_context *ev_ctx; … … 40 58 int *transaction_token; 41 59 uint32_t soa_serial; 60 struct b9_zone *zonelist; 61 62 /* Used for dynamic update */ 63 struct smb_krb5_context *smb_krb5_ctx; 64 struct auth4_context *auth_context; 65 struct auth_session_info *session_info; 66 char *update_name; 42 67 43 68 /* helper functions from the dlz_dlopen driver */ 44 void (*log)(int level, const char *fmt, ...); 45 isc_result_t (*putrr)(dns_sdlzlookup_t *handle, const char *type, 46 dns_ttl_t ttl, const char *data); 47 isc_result_t (*putnamedrr)(dns_sdlzlookup_t *handle, const char *name, 48 const char *type, dns_ttl_t ttl, const char *data); 49 isc_result_t (*writeable_zone)(dns_view_t *view, const char *zone_name); 69 log_t *log; 70 dns_sdlz_putrr_t *putrr; 71 dns_sdlz_putnamedrr_t *putnamedrr; 72 dns_dlz_writeablezone_t *writeable_zone; 50 73 }; 51 74 75 static struct dlz_bind9_data *dlz_bind9_state = NULL; 76 static int dlz_bind9_state_ref_count = 0; 52 77 53 78 static const char *zone_prefixes[] = { 54 79 "CN=MicrosoftDNS,DC=DomainDnsZones", 55 80 "CN=MicrosoftDNS,DC=ForestDnsZones", 81 "CN=MicrosoftDNS,CN=System", 56 82 NULL 57 83 }; … … 82 108 state->writeable_zone = ptr; 83 109 } 110 } 111 112 /* 113 * Add a trailing '.' if it's missing 114 */ 115 static const char *b9_format_fqdn(TALLOC_CTX *mem_ctx, const char *str) 116 { 117 size_t len; 118 const char *tmp; 119 120 if (str == NULL || str[0] == '\0') { 121 return str; 122 } 123 124 len = strlen(str); 125 if (str[len-1] != '.') { 126 tmp = talloc_asprintf(mem_ctx, "%s.", str); 127 } else { 128 tmp = str; 129 } 130 return tmp; 84 131 } 85 132 … … 92 139 const char **type, const char **data) 93 140 { 141 uint32_t i; 142 char *tmp; 143 const char *fqdn; 144 94 145 switch (rec->wType) { 95 146 case DNS_TYPE_A: … … 105 156 case DNS_TYPE_CNAME: 106 157 *type = "cname"; 107 *data = rec->data.cname;158 *data = b9_format_fqdn(mem_ctx, rec->data.cname); 108 159 break; 109 160 110 161 case DNS_TYPE_TXT: 111 162 *type = "txt"; 112 *data = rec->data.txt; 163 tmp = talloc_asprintf(mem_ctx, "\"%s\"", rec->data.txt.str[0]); 164 for (i=1; i<rec->data.txt.count; i++) { 165 tmp = talloc_asprintf_append(tmp, " \"%s\"", rec->data.txt.str[i]); 166 } 167 *data = tmp; 113 168 break; 114 169 115 170 case DNS_TYPE_PTR: 116 171 *type = "ptr"; 117 *data = rec->data.ptr;172 *data = b9_format_fqdn(mem_ctx, rec->data.ptr); 118 173 break; 119 174 120 175 case DNS_TYPE_SRV: 121 176 *type = "srv"; 177 fqdn = b9_format_fqdn(mem_ctx, rec->data.srv.nameTarget); 178 if (fqdn == NULL) { 179 return false; 180 } 122 181 *data = talloc_asprintf(mem_ctx, "%u %u %u %s", 123 182 rec->data.srv.wPriority, 124 183 rec->data.srv.wWeight, 125 184 rec->data.srv.wPort, 126 rec->data.srv.nameTarget);185 fqdn); 127 186 break; 128 187 129 188 case DNS_TYPE_MX: 130 189 *type = "mx"; 190 fqdn = b9_format_fqdn(mem_ctx, rec->data.mx.nameTarget); 191 if (fqdn == NULL) { 192 return false; 193 } 131 194 *data = talloc_asprintf(mem_ctx, "%u %s", 132 rec->data.mx.wPriority, 133 rec->data.mx.nameTarget); 195 rec->data.mx.wPriority, fqdn); 134 196 break; 135 197 … … 143 205 case DNS_TYPE_NS: 144 206 *type = "ns"; 145 *data = rec->data.ns;207 *data = b9_format_fqdn(mem_ctx, rec->data.ns); 146 208 break; 147 209 … … 154 216 * force clients to send updates to the right local DC 155 217 */ 156 mname = talloc_asprintf(mem_ctx, "%s.%s", 157 lpcfg_netbios_name(state->lp), lpcfg_dnsdomain(state->lp)); 218 mname = talloc_asprintf(mem_ctx, "%s.%s.", 219 lpcfg_netbios_name(state->lp), 220 lpcfg_dnsdomain(state->lp)); 158 221 if (mname == NULL) { 159 222 return false; … … 164 227 } 165 228 229 fqdn = b9_format_fqdn(mem_ctx, rec->data.soa.rname); 230 if (fqdn == NULL) { 231 return false; 232 } 233 166 234 state->soa_serial = rec->data.soa.serial; 167 235 168 236 *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u", 169 mname, 170 rec->data.soa.rname, 237 mname, fqdn, 171 238 rec->data.soa.serial, 172 239 rec->data.soa.refresh, … … 178 245 179 246 default: 180 state->log(ISC_LOG_ERROR, "samba b9_putrr: unhandled record type %u",247 state->log(ISC_LOG_ERROR, "samba_dlz b9_format: unhandled record type %u", 181 248 rec->wType); 182 249 return false; … … 253 320 { 254 321 char *full_name, *dclass, *type; 255 char *str, * saveptr=NULL;322 char *str, *tmp, *saveptr=NULL; 256 323 int i; 257 324 … … 294 361 295 362 case DNS_TYPE_TXT: 296 DNS_PARSE_STR(rec->data.txt, NULL, "\t", saveptr); 363 rec->data.txt.count = 0; 364 rec->data.txt.str = talloc_array(rec, const char *, rec->data.txt.count); 365 tmp = strtok_r(NULL, "\t", &saveptr); 366 while (tmp) { 367 rec->data.txt.str = talloc_realloc(rec, rec->data.txt.str, const char *, 368 rec->data.txt.count+1); 369 if (tmp[0] == '"') { 370 /* Strip quotes */ 371 rec->data.txt.str[rec->data.txt.count] = talloc_strndup(rec, &tmp[1], strlen(tmp)-2); 372 } else { 373 rec->data.txt.str[rec->data.txt.count] = talloc_strdup(rec, tmp); 374 } 375 rec->data.txt.count++; 376 tmp = strtok_r(NULL, " ", &saveptr); 377 } 297 378 break; 298 379 … … 333 414 334 415 default: 335 state->log(ISC_LOG_ERROR, "samba b9_parse: unhandled record type %u",416 state->log(ISC_LOG_ERROR, "samba_dlz b9_parse: unhandled record type %u", 336 417 rec->wType); 337 418 return false; … … 340 421 /* we should be at the end of the buffer now */ 341 422 if (strtok_r(NULL, "\t ", &saveptr) != NULL) { 342 state->log(ISC_LOG_ERROR, "samba b9_parse: expected data at end of string for '%s'"); 423 state->log(ISC_LOG_ERROR, "samba_dlz b9_parse: unexpected data at end of string for '%s'", 424 rdatastr); 343 425 return false; 344 426 } … … 348 430 349 431 /* 350 send a resource reco nd to bind9432 send a resource record to bind9 351 433 */ 352 434 static isc_result_t b9_putrr(struct dlz_bind9_data *state, … … 388 470 389 471 /* 390 send a named resource reco nd to bind9472 send a named resource record to bind9 391 473 */ 392 474 static isc_result_t b9_putnamedrr(struct dlz_bind9_data *state, … … 415 497 } 416 498 417 struct b9_options {418 const char *url;419 };420 421 499 /* 422 500 parse options 423 501 */ 424 502 static isc_result_t parse_options(struct dlz_bind9_data *state, 425 unsigned int argc, c har *argv[],503 unsigned int argc, const char **argv, 426 504 struct b9_options *options) 427 505 { … … 429 507 poptContext pc; 430 508 struct poptOption long_options[] = { 431 { "url", 'H', POPT_ARG_STRING, &options->url, 0, "database URL", "URL" }, 509 { "url", 'H', POPT_ARG_STRING, &options->url, 0, "database URL", "URL" }, 510 { "debug", 'd', POPT_ARG_STRING, &options->debug, 0, "debug level", "DEBUG" }, 432 511 { NULL } 433 512 }; 434 struct poptOption **popt_options; 435 int ret; 436 437 fault_setup_disable(); 438 439 popt_options = ldb_module_popt_options(state->samdb); 440 (*popt_options) = long_options; 441 442 ret = ldb_modules_hook(state->samdb, LDB_MODULE_HOOK_CMDLINE_OPTIONS); 443 if (ret != LDB_SUCCESS) { 444 state->log(ISC_LOG_ERROR, "dlz samba: failed cmdline hook"); 445 return ISC_R_FAILURE; 446 } 447 448 pc = poptGetContext("dlz_bind9", argc, (const char **)argv, *popt_options, 449 POPT_CONTEXT_KEEP_FIRST); 450 513 514 pc = poptGetContext("dlz_bind9", argc, argv, long_options, 515 POPT_CONTEXT_KEEP_FIRST); 451 516 while ((opt = poptGetNextOpt(pc)) != -1) { 452 517 switch (opt) { 453 518 default: 454 state->log(ISC_LOG_ERROR, "dlz samba: Invalid option %s: %s",519 state->log(ISC_LOG_ERROR, "dlz_bind9: Invalid option %s: %s", 455 520 poptBadOption(pc, 0), poptStrerror(opt)); 456 521 return ISC_R_FAILURE; … … 458 523 } 459 524 460 ret = ldb_modules_hook(state->samdb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT);461 if (ret != LDB_SUCCESS) {462 state->log(ISC_LOG_ERROR, "dlz samba: failed cmdline preconnect");463 return ISC_R_FAILURE;464 }465 466 525 return ISC_R_SUCCESS; 467 526 } … … 469 528 470 529 /* 530 * Create session info from PAC 531 * This is called as auth_context->generate_session_info_pac() 532 */ 533 static NTSTATUS b9_generate_session_info_pac(struct auth4_context *auth_context, 534 TALLOC_CTX *mem_ctx, 535 struct smb_krb5_context *smb_krb5_context, 536 DATA_BLOB *pac_blob, 537 const char *principal_name, 538 const struct tsocket_address *remote_addr, 539 uint32_t session_info_flags, 540 struct auth_session_info **session_info) 541 { 542 NTSTATUS status; 543 struct auth_user_info_dc *user_info_dc; 544 TALLOC_CTX *tmp_ctx; 545 546 tmp_ctx = talloc_new(mem_ctx); 547 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); 548 549 status = kerberos_pac_blob_to_user_info_dc(tmp_ctx, 550 *pac_blob, 551 smb_krb5_context->krb5_context, 552 &user_info_dc, 553 NULL, 554 NULL); 555 if (!NT_STATUS_IS_OK(status)) { 556 talloc_free(tmp_ctx); 557 return status; 558 } 559 560 if (user_info_dc->info->authenticated) { 561 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED; 562 } 563 564 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES; 565 566 status = auth_generate_session_info(mem_ctx, NULL, NULL, user_info_dc, 567 session_info_flags, session_info); 568 if (!NT_STATUS_IS_OK(status)) { 569 talloc_free(tmp_ctx); 570 return status; 571 } 572 573 talloc_free(tmp_ctx); 574 return status; 575 } 576 577 /* Callback for the DEBUG() system, to catch the remaining messages */ 578 static void b9_debug(void *private_ptr, int msg_level, const char *msg) 579 { 580 static const int isc_log_map[] = { 581 ISC_LOG_CRITICAL, /* 0 */ 582 ISC_LOG_ERROR, /* 1 */ 583 ISC_LOG_WARNING, /* 2 */ 584 ISC_LOG_NOTICE /* 3 */ 585 }; 586 struct dlz_bind9_data *state = private_ptr; 587 int isc_log_level; 588 589 if (msg_level >= ARRAY_SIZE(isc_log_map) || msg_level < 0) { 590 isc_log_level = ISC_LOG_INFO; 591 } else { 592 isc_log_level = isc_log_map[msg_level]; 593 } 594 state->log(isc_log_level, "samba_dlz: %s", msg); 595 } 596 597 static int dlz_state_debug_unregister(struct dlz_bind9_data *state) 598 { 599 /* Stop logging (to the bind9 logs) */ 600 debug_set_callback(NULL, NULL); 601 return 0; 602 } 603 604 /* 471 605 called to initialise the driver 472 606 */ 473 607 _PUBLIC_ isc_result_t dlz_create(const char *dlzname, 474 unsigned int argc, c har *argv[],608 unsigned int argc, const char **argv, 475 609 void **dbdata, ...) 476 610 { … … 479 613 va_list ap; 480 614 isc_result_t result; 481 TALLOC_CTX *tmp_ctx;482 int ret;483 615 struct ldb_dn *dn; 484 struct b9_options options; 485 486 ZERO_STRUCT(options); 616 NTSTATUS nt_status; 617 618 if (dlz_bind9_state != NULL) { 619 *dbdata = dlz_bind9_state; 620 dlz_bind9_state_ref_count++; 621 return ISC_R_SUCCESS; 622 } 487 623 488 624 state = talloc_zero(NULL, struct dlz_bind9_data); … … 491 627 } 492 628 493 t mp_ctx = talloc_new(state);629 talloc_set_destructor(state, dlz_state_debug_unregister); 494 630 495 631 /* fill in the helper functions */ … … 500 636 va_end(ap); 501 637 638 /* Do not install samba signal handlers */ 639 fault_setup_disable(); 640 641 /* Start logging (to the bind9 logs) */ 642 debug_set_callback(state, b9_debug); 643 502 644 state->ev_ctx = s4_event_context_init(state); 503 645 if (state->ev_ctx == NULL) { … … 506 648 } 507 649 508 state->samdb = ldb_init(state, state->ev_ctx); 509 if (state->samdb == NULL) { 510 state->log(ISC_LOG_ERROR, "samba_dlz: Failed to create ldb"); 511 result = ISC_R_FAILURE; 512 goto failed; 513 } 514 515 result = parse_options(state, argc, argv, &options); 650 result = parse_options(state, argc, argv, &state->options); 516 651 if (result != ISC_R_SUCCESS) { 517 652 goto failed; … … 524 659 } 525 660 526 if (options.url == NULL) { 527 options.url = talloc_asprintf(tmp_ctx, "ldapi://%s", 528 private_path(tmp_ctx, state->lp, "ldap_priv/ldapi")); 529 if (options.url == NULL) { 661 if (state->options.debug) { 662 lpcfg_do_global_parameter(state->lp, "log level", state->options.debug); 663 } else { 664 lpcfg_do_global_parameter(state->lp, "log level", "0"); 665 } 666 667 if (smb_krb5_init_context(state, state->lp, &state->smb_krb5_ctx) != 0) { 668 result = ISC_R_NOMEMORY; 669 goto failed; 670 } 671 672 nt_status = gensec_init(); 673 if (!NT_STATUS_IS_OK(nt_status)) { 674 result = ISC_R_NOMEMORY; 675 goto failed; 676 } 677 678 state->auth_context = talloc_zero(state, struct auth4_context); 679 if (state->auth_context == NULL) { 680 result = ISC_R_NOMEMORY; 681 goto failed; 682 } 683 684 if (state->options.url == NULL) { 685 state->options.url = lpcfg_private_path(state, state->lp, "dns/sam.ldb"); 686 if (state->options.url == NULL) { 530 687 result = ISC_R_NOMEMORY; 531 688 goto failed; … … 533 690 } 534 691 535 ret = ldb_connect(state->samdb, options.url, 0, NULL); 536 if (ret == -1) { 537 state->log(ISC_LOG_ERROR, "samba_dlz: Failed to connect to %s - %s", 538 options.url, ldb_errstring(state->samdb)); 539 result = ISC_R_FAILURE; 540 goto failed; 541 } 542 543 ret = ldb_modules_hook(state->samdb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT); 544 if (ret != LDB_SUCCESS) { 545 state->log(ISC_LOG_ERROR, "samba_dlz: Failed postconnect for %s - %s", 546 options.url, ldb_errstring(state->samdb)); 692 state->samdb = samdb_connect_url(state, state->ev_ctx, state->lp, 693 system_session(state->lp), 0, state->options.url); 694 if (state->samdb == NULL) { 695 state->log(ISC_LOG_ERROR, "samba_dlz: Failed to connect to %s", 696 state->options.url); 547 697 result = ISC_R_FAILURE; 548 698 goto failed; … … 552 702 if (dn == NULL) { 553 703 state->log(ISC_LOG_ERROR, "samba_dlz: Unable to get basedn for %s - %s", 554 options.url, ldb_errstring(state->samdb));704 state->options.url, ldb_errstring(state->samdb)); 555 705 result = ISC_R_FAILURE; 556 706 goto failed; … … 560 710 ldb_dn_get_linearized(dn)); 561 711 712 state->auth_context->event_ctx = state->ev_ctx; 713 state->auth_context->lp_ctx = state->lp; 714 state->auth_context->sam_ctx = state->samdb; 715 state->auth_context->generate_session_info_pac = b9_generate_session_info_pac; 716 562 717 *dbdata = state; 563 564 talloc_free(tmp_ctx); 718 dlz_bind9_state = state; 719 dlz_bind9_state_ref_count++; 720 565 721 return ISC_R_SUCCESS; 566 722 … … 577 733 struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); 578 734 state->log(ISC_LOG_INFO, "samba_dlz: shutting down"); 579 talloc_free(state); 735 736 dlz_bind9_state_ref_count--; 737 if (dlz_bind9_state_ref_count == 0) { 738 talloc_unlink(state, state->samdb); 739 talloc_free(state); 740 dlz_bind9_state = NULL; 741 } 580 742 } 581 743 … … 665 827 see if we handle a given zone 666 828 */ 829 #if DLZ_DLOPEN_VERSION < 3 667 830 _PUBLIC_ isc_result_t dlz_findzonedb(void *dbdata, const char *name) 831 #else 832 _PUBLIC_ isc_result_t dlz_findzonedb(void *dbdata, const char *name, 833 dns_clientinfomethods_t *methods, 834 dns_clientinfo_t *clientinfo) 835 #endif 668 836 { 669 837 struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); … … 681 849 { 682 850 TALLOC_CTX *tmp_ctx = talloc_new(state); 683 const char *attrs[] = { "dnsRecord", NULL };684 int ret = LDB_SUCCESS, i;685 struct ldb_result *res;686 struct ldb_message_element *el;687 851 struct ldb_dn *dn; 852 WERROR werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; 853 struct dnsp_DnssrvRpcRecord *records = NULL; 854 uint16_t num_records = 0, i; 688 855 689 856 for (i=0; zone_prefixes[i]; i++) { … … 699 866 } 700 867 701 ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,702 attrs, "objectClass=dnsNode");703 if ( ret == LDB_SUCCESS) {868 werr = dns_common_lookup(state->samdb, tmp_ctx, dn, 869 &records, &num_records, NULL); 870 if (W_ERROR_IS_OK(werr)) { 704 871 break; 705 872 } 706 873 } 707 if ( ret != LDB_SUCCESS) {874 if (!W_ERROR_IS_OK(werr)) { 708 875 talloc_free(tmp_ctx); 709 876 return ISC_R_NOTFOUND; 710 877 } 711 878 712 el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); 713 if (el == NULL || el->num_values == 0) { 714 talloc_free(tmp_ctx); 715 return ISC_R_NOTFOUND; 716 } 717 718 for (i=0; i<el->num_values; i++) { 719 struct dnsp_DnssrvRpcRecord rec; 720 enum ndr_err_code ndr_err; 879 for (i=0; i < num_records; i++) { 721 880 isc_result_t result; 722 881 723 ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, 724 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 725 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 726 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", 727 ldb_dn_get_linearized(dn)); 728 talloc_free(tmp_ctx); 729 return ISC_R_FAILURE; 730 } 731 732 result = b9_putrr(state, lookup, &rec, types); 882 result = b9_putrr(state, lookup, &records[i], types); 733 883 if (result != ISC_R_SUCCESS) { 734 884 talloc_free(tmp_ctx); … … 744 894 lookup one record 745 895 */ 896 #if DLZ_DLOPEN_VERSION == 1 746 897 _PUBLIC_ isc_result_t dlz_lookup(const char *zone, const char *name, 747 898 void *dbdata, dns_sdlzlookup_t *lookup) 899 #else 900 _PUBLIC_ isc_result_t dlz_lookup(const char *zone, const char *name, 901 void *dbdata, dns_sdlzlookup_t *lookup, 902 dns_clientinfomethods_t *methods, 903 dns_clientinfo_t *clientinfo) 904 #endif 748 905 { 749 906 struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); … … 758 915 { 759 916 /* just say yes for all our zones for now */ 760 return dlz_findzonedb(dbdata, name); 917 struct dlz_bind9_data *state = talloc_get_type( 918 dbdata, struct dlz_bind9_data); 919 return b9_find_zone_dn(state, name, NULL, NULL); 761 920 } 762 921 … … 802 961 const char *rdn, *name; 803 962 const struct ldb_val *v; 963 WERROR werr; 964 struct dnsp_DnssrvRpcRecord *recs = NULL; 965 uint16_t num_recs = 0; 804 966 805 967 el = ldb_msg_find_element(res->msgs[i], "dnsRecord"); … … 830 992 name = talloc_asprintf(el_ctx, "%s.%s", rdn, zone); 831 993 } 994 name = b9_format_fqdn(el_ctx, name); 832 995 if (name == NULL) { 833 996 talloc_free(tmp_ctx); … … 835 998 } 836 999 837 for (j=0; j<el->num_values; j++) { 838 struct dnsp_DnssrvRpcRecord rec; 839 enum ndr_err_code ndr_err; 1000 werr = dns_common_extract(el, el_ctx, &recs, &num_recs); 1001 if (!W_ERROR_IS_OK(werr)) { 1002 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", 1003 ldb_dn_get_linearized(dn), win_errstr(werr)); 1004 talloc_free(el_ctx); 1005 continue; 1006 } 1007 1008 for (j=0; j < num_recs; j++) { 840 1009 isc_result_t result; 841 1010 842 ndr_err = ndr_pull_struct_blob(&el->values[j], el_ctx, &rec, 843 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 844 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 845 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", 846 ldb_dn_get_linearized(dn)); 847 continue; 848 } 849 850 result = b9_putnamedrr(state, allnodes, name, &rec); 1011 result = b9_putnamedrr(state, allnodes, name, &recs[j]); 851 1012 if (result != ISC_R_SUCCESS) { 852 1013 continue; 853 1014 } 854 1015 } 1016 1017 talloc_free(el_ctx); 855 1018 } 856 1019 … … 930 1093 static bool b9_has_soa(struct dlz_bind9_data *state, struct ldb_dn *dn, const char *zone) 931 1094 { 932 const char *attrs[] = { "dnsRecord", NULL };933 struct ldb_result *res;934 struct ldb_message_element *el;935 1095 TALLOC_CTX *tmp_ctx = talloc_new(state); 936 int ret, i; 1096 WERROR werr; 1097 struct dnsp_DnssrvRpcRecord *records = NULL; 1098 uint16_t num_records = 0, i; 937 1099 938 1100 if (!ldb_dn_add_child_fmt(dn, "DC=@,DC=%s", zone)) { … … 941 1103 } 942 1104 943 ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,944 attrs, "objectClass=dnsNode");945 if ( ret != LDB_SUCCESS) {1105 werr = dns_common_lookup(state->samdb, tmp_ctx, dn, 1106 &records, &num_records, NULL); 1107 if (!W_ERROR_IS_OK(werr)) { 946 1108 talloc_free(tmp_ctx); 947 1109 return false; 948 1110 } 949 1111 950 el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); 951 if (el == NULL) { 952 talloc_free(tmp_ctx); 953 return false; 954 } 955 for (i=0; i<el->num_values; i++) { 956 struct dnsp_DnssrvRpcRecord rec; 957 enum ndr_err_code ndr_err; 958 959 ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, 960 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 961 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 962 continue; 963 } 964 if (rec.wType == DNS_TYPE_SOA) { 1112 for (i=0; i < num_records; i++) { 1113 if (records[i].wType == DNS_TYPE_SOA) { 965 1114 talloc_free(tmp_ctx); 966 1115 return true; … … 972 1121 } 973 1122 1123 static bool b9_zone_add(struct dlz_bind9_data *state, const char *name) 1124 { 1125 struct b9_zone *zone; 1126 1127 zone = talloc_zero(state, struct b9_zone); 1128 if (zone == NULL) { 1129 return false; 1130 } 1131 1132 zone->name = talloc_strdup(zone, name); 1133 if (zone->name == NULL) { 1134 talloc_free(zone); 1135 return false; 1136 } 1137 1138 DLIST_ADD(state->zonelist, zone); 1139 return true; 1140 } 1141 1142 static bool b9_zone_exists(struct dlz_bind9_data *state, const char *name) 1143 { 1144 struct b9_zone *zone = state->zonelist; 1145 bool found = false; 1146 1147 while (zone != NULL) { 1148 if (strcasecmp(name, zone->name) == 0) { 1149 found = true; 1150 break; 1151 } 1152 zone = zone->next; 1153 } 1154 1155 return found; 1156 } 1157 1158 974 1159 /* 975 1160 configure a writeable zone 976 1161 */ 1162 #if DLZ_DLOPEN_VERSION < 3 977 1163 _PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, void *dbdata) 1164 #else 1165 _PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, 1166 void *dbdata) 1167 #endif 978 1168 { 979 1169 struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); … … 1015 1205 isc_result_t result; 1016 1206 const char *zone = ldb_msg_find_attr_as_string(res->msgs[j], "name", NULL); 1207 struct ldb_dn *zone_dn; 1208 1017 1209 if (zone == NULL) { 1018 1210 continue; 1019 1211 } 1020 if (!b9_has_soa(state, dn, zone)) { 1212 /* Ignore zones that are not handled in BIND */ 1213 if ((strcmp(zone, "RootDNSServers") == 0) || 1214 (strcmp(zone, "..TrustAnchors") == 0)) { 1021 1215 continue; 1022 1216 } 1217 zone_dn = ldb_dn_copy(tmp_ctx, dn); 1218 if (zone_dn == NULL) { 1219 talloc_free(tmp_ctx); 1220 return ISC_R_NOMEMORY; 1221 } 1222 1223 if (!b9_has_soa(state, zone_dn, zone)) { 1224 continue; 1225 } 1226 1227 if (b9_zone_exists(state, zone)) { 1228 state->log(ISC_LOG_WARNING, "samba_dlz: Ignoring duplicate zone '%s' from '%s'", 1229 zone, ldb_dn_get_linearized(zone_dn)); 1230 continue; 1231 } 1232 1233 if (!b9_zone_add(state, zone)) { 1234 talloc_free(tmp_ctx); 1235 return ISC_R_NOMEMORY; 1236 } 1237 1238 #if DLZ_DLOPEN_VERSION < 3 1023 1239 result = state->writeable_zone(view, zone); 1240 #else 1241 result = state->writeable_zone(view, dlzdb, zone); 1242 #endif 1024 1243 if (result != ISC_R_SUCCESS) { 1025 1244 state->log(ISC_LOG_ERROR, "samba_dlz: Failed to configure zone '%s'", … … 1044 1263 { 1045 1264 struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data); 1046 1047 state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s keydatalen=%u", 1048 signer, name, tcpaddr, type, key, keydatalen); 1049 return true; 1050 } 1051 1052 1053 /* 1054 add a new record 1055 */ 1056 static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name, 1057 struct ldb_dn *dn, 1058 struct dnsp_DnssrvRpcRecord *rec) 1059 { 1060 struct ldb_message *msg; 1061 enum ndr_err_code ndr_err; 1062 struct ldb_val v; 1265 TALLOC_CTX *tmp_ctx; 1266 DATA_BLOB ap_req; 1267 struct cli_credentials *server_credentials; 1268 char *keytab_name; 1063 1269 int ret; 1064 1065 msg = ldb_msg_new(rec); 1066 if (msg == NULL) { 1067 return ISC_R_NOMEMORY; 1068 } 1069 msg->dn = dn; 1070 ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); 1071 if (ret != LDB_SUCCESS) { 1072 return ISC_R_FAILURE; 1073 } 1074 1075 ndr_err = ndr_push_struct_blob(&v, rec, rec, (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); 1076 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1077 return ISC_R_FAILURE; 1078 } 1079 ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL); 1080 if (ret != LDB_SUCCESS) { 1081 return ISC_R_FAILURE; 1082 } 1083 1084 ret = ldb_add(state->samdb, msg); 1085 if (ret != LDB_SUCCESS) { 1086 return ISC_R_FAILURE; 1087 } 1088 1089 return ISC_R_SUCCESS; 1270 int ldb_ret; 1271 NTSTATUS nt_status; 1272 struct gensec_security *gensec_ctx; 1273 struct auth_session_info *session_info; 1274 struct ldb_dn *dn; 1275 isc_result_t result; 1276 struct ldb_result *res; 1277 const char * attrs[] = { NULL }; 1278 uint32_t access_mask; 1279 1280 /* Remove cached credentials, if any */ 1281 if (state->session_info) { 1282 talloc_free(state->session_info); 1283 state->session_info = NULL; 1284 } 1285 if (state->update_name) { 1286 talloc_free(state->update_name); 1287 state->update_name = NULL; 1288 } 1289 1290 tmp_ctx = talloc_new(NULL); 1291 if (tmp_ctx == NULL) { 1292 state->log(ISC_LOG_ERROR, "samba_dlz: no memory"); 1293 return ISC_FALSE; 1294 } 1295 1296 ap_req = data_blob_const(keydata, keydatalen); 1297 server_credentials = cli_credentials_init(tmp_ctx); 1298 if (!server_credentials) { 1299 state->log(ISC_LOG_ERROR, "samba_dlz: failed to init server credentials"); 1300 talloc_free(tmp_ctx); 1301 return ISC_FALSE; 1302 } 1303 1304 cli_credentials_set_krb5_context(server_credentials, state->smb_krb5_ctx); 1305 cli_credentials_set_conf(server_credentials, state->lp); 1306 1307 keytab_name = talloc_asprintf(tmp_ctx, "FILE:%s/dns.keytab", 1308 lpcfg_private_dir(state->lp)); 1309 ret = cli_credentials_set_keytab_name(server_credentials, state->lp, keytab_name, 1310 CRED_SPECIFIED); 1311 if (ret != 0) { 1312 state->log(ISC_LOG_ERROR, "samba_dlz: failed to obtain server credentials from %s", 1313 keytab_name); 1314 talloc_free(tmp_ctx); 1315 return ISC_FALSE; 1316 } 1317 talloc_free(keytab_name); 1318 1319 nt_status = gensec_server_start(tmp_ctx, 1320 lpcfg_gensec_settings(tmp_ctx, state->lp), 1321 state->auth_context, &gensec_ctx); 1322 if (!NT_STATUS_IS_OK(nt_status)) { 1323 state->log(ISC_LOG_ERROR, "samba_dlz: failed to start gensec server"); 1324 talloc_free(tmp_ctx); 1325 return ISC_FALSE; 1326 } 1327 1328 gensec_set_credentials(gensec_ctx, server_credentials); 1329 1330 nt_status = gensec_start_mech_by_name(gensec_ctx, "spnego"); 1331 if (!NT_STATUS_IS_OK(nt_status)) { 1332 state->log(ISC_LOG_ERROR, "samba_dlz: failed to start spnego"); 1333 talloc_free(tmp_ctx); 1334 return ISC_FALSE; 1335 } 1336 1337 nt_status = gensec_update_ev(gensec_ctx, tmp_ctx, state->ev_ctx, ap_req, &ap_req); 1338 if (!NT_STATUS_IS_OK(nt_status)) { 1339 state->log(ISC_LOG_ERROR, "samba_dlz: spnego update failed"); 1340 talloc_free(tmp_ctx); 1341 return ISC_FALSE; 1342 } 1343 1344 nt_status = gensec_session_info(gensec_ctx, tmp_ctx, &session_info); 1345 if (!NT_STATUS_IS_OK(nt_status)) { 1346 state->log(ISC_LOG_ERROR, "samba_dlz: failed to create session info"); 1347 talloc_free(tmp_ctx); 1348 return ISC_FALSE; 1349 } 1350 1351 /* Get the DN from name */ 1352 result = b9_find_name_dn(state, name, tmp_ctx, &dn); 1353 if (result != ISC_R_SUCCESS) { 1354 state->log(ISC_LOG_ERROR, "samba_dlz: failed to find name %s", name); 1355 talloc_free(tmp_ctx); 1356 return ISC_FALSE; 1357 } 1358 1359 /* make sure the dn exists, or find parent dn in case new object is being added */ 1360 ldb_ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, 1361 attrs, "objectClass=dnsNode"); 1362 if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) { 1363 ldb_dn_remove_child_components(dn, 1); 1364 access_mask = SEC_ADS_CREATE_CHILD; 1365 talloc_free(res); 1366 } else if (ldb_ret == LDB_SUCCESS) { 1367 access_mask = SEC_STD_REQUIRED | SEC_ADS_SELF_WRITE; 1368 talloc_free(res); 1369 } else { 1370 talloc_free(tmp_ctx); 1371 return ISC_FALSE; 1372 } 1373 1374 /* Do ACL check */ 1375 ldb_ret = dsdb_check_access_on_dn(state->samdb, tmp_ctx, dn, 1376 session_info->security_token, 1377 access_mask, NULL); 1378 if (ldb_ret != LDB_SUCCESS) { 1379 state->log(ISC_LOG_INFO, 1380 "samba_dlz: disallowing update of signer=%s name=%s type=%s error=%s", 1381 signer, name, type, ldb_strerror(ldb_ret)); 1382 talloc_free(tmp_ctx); 1383 return ISC_FALSE; 1384 } 1385 1386 /* Cache session_info, so it can be used in the actual add/delete operation */ 1387 state->update_name = talloc_strdup(state, name); 1388 if (state->update_name == NULL) { 1389 state->log(ISC_LOG_ERROR, "samba_dlz: memory allocation error"); 1390 talloc_free(tmp_ctx); 1391 return ISC_FALSE; 1392 } 1393 state->session_info = talloc_steal(state, session_info); 1394 1395 state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s", 1396 signer, name, tcpaddr, type, key); 1397 1398 talloc_free(tmp_ctx); 1399 return ISC_TRUE; 1090 1400 } 1091 1401 … … 1112 1422 struct dnsp_DnssrvRpcRecord *rec1, struct dnsp_DnssrvRpcRecord *rec2) 1113 1423 { 1424 bool status; 1425 int i; 1426 struct in6_addr rec1_in_addr6; 1427 struct in6_addr rec2_in_addr6; 1428 1114 1429 if (rec1->wType != rec2->wType) { 1115 1430 return false; … … 1124 1439 case DNS_TYPE_A: 1125 1440 return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0; 1126 case DNS_TYPE_AAAA: 1127 return strcmp(rec1->data.ipv6, rec2->data.ipv6) == 0; 1441 case DNS_TYPE_AAAA: { 1442 int ret; 1443 1444 ret = inet_pton(AF_INET6, rec1->data.ipv6, &rec1_in_addr6); 1445 if (ret != 1) { 1446 return false; 1447 } 1448 ret = inet_pton(AF_INET6, rec2->data.ipv6, &rec2_in_addr6); 1449 if (ret != 1) { 1450 return false; 1451 } 1452 1453 return memcmp(&rec1_in_addr6, &rec2_in_addr6, sizeof(rec1_in_addr6)) == 0; 1454 } 1128 1455 case DNS_TYPE_CNAME: 1129 1456 return dns_name_equal(rec1->data.cname, rec2->data.cname); 1130 1457 case DNS_TYPE_TXT: 1131 return strcmp(rec1->data.txt, rec2->data.txt) == 0; 1458 status = (rec1->data.txt.count == rec2->data.txt.count); 1459 if (!status) return status; 1460 for (i=0; i<rec1->data.txt.count; i++) { 1461 status &= (strcmp(rec1->data.txt.str[i], rec2->data.txt.str[i]) == 0); 1462 } 1463 return status; 1132 1464 case DNS_TYPE_PTR: 1133 return strcmp(rec1->data.ptr, rec2->data.ptr) == 0;1465 return dns_name_equal(rec1->data.ptr, rec2->data.ptr); 1134 1466 case DNS_TYPE_NS: 1135 1467 return dns_name_equal(rec1->data.ns, rec2->data.ns); … … 1158 1490 rec1->data.soa.minimum == rec2->data.soa.minimum; 1159 1491 default: 1160 state->log(ISC_LOG_ERROR, "samba b9_putrr: unhandled record type %u",1492 state->log(ISC_LOG_ERROR, "samba_dlz b9_record_match: unhandled record type %u", 1161 1493 rec1->wType); 1162 1494 break; … … 1166 1498 } 1167 1499 1500 /* 1501 * Update session_info on samdb using the cached credentials 1502 */ 1503 static bool b9_set_session_info(struct dlz_bind9_data *state, const char *name) 1504 { 1505 int ret; 1506 1507 if (state->update_name == NULL || state->session_info == NULL) { 1508 state->log(ISC_LOG_ERROR, "samba_dlz: invalid credentials"); 1509 return false; 1510 } 1511 1512 /* Do not use client credentials, if we're not updating the client specified name */ 1513 if (strcmp(state->update_name, name) != 0) { 1514 return true; 1515 } 1516 1517 ret = ldb_set_opaque(state->samdb, "sessionInfo", state->session_info); 1518 if (ret != LDB_SUCCESS) { 1519 state->log(ISC_LOG_ERROR, "samba_dlz: unable to set session info"); 1520 return false; 1521 } 1522 1523 return true; 1524 } 1525 1526 /* 1527 * Reset session_info on samdb as system session 1528 */ 1529 static void b9_reset_session_info(struct dlz_bind9_data *state) 1530 { 1531 ldb_set_opaque(state->samdb, "sessionInfo", system_session(state->lp)); 1532 } 1168 1533 1169 1534 /* … … 1176 1541 struct ldb_dn *dn; 1177 1542 isc_result_t result; 1178 struct ldb_result *res; 1179 const char *attrs[] = { "dnsRecord", NULL }; 1180 int ret, i; 1181 struct ldb_message_element *el; 1182 enum ndr_err_code ndr_err; 1543 bool tombstoned = false; 1544 bool needs_add = false; 1545 struct dnsp_DnssrvRpcRecord *recs = NULL; 1546 uint16_t num_recs = 0; 1547 uint16_t first = 0; 1548 uint16_t i; 1183 1549 NTTIME t; 1550 WERROR werr; 1184 1551 1185 1552 if (state->transaction_token != (void*)version) { … … 1198 1565 1199 1566 rec->rank = DNS_RANK_ZONE; 1200 rec->dwSerial = state->soa_serial;1201 1567 rec->dwTimeStamp = (uint32_t)t; 1202 1568 … … 1215 1581 1216 1582 /* get any existing records */ 1217 ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); 1218 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1219 result = b9_add_record(state, name, dn, rec); 1583 werr = dns_common_lookup(state->samdb, rec, dn, 1584 &recs, &num_recs, &tombstoned); 1585 if (W_ERROR_EQUAL(werr, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 1586 needs_add = true; 1587 werr = WERR_OK; 1588 } 1589 if (!W_ERROR_IS_OK(werr)) { 1590 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", 1591 ldb_dn_get_linearized(dn), win_errstr(werr)); 1220 1592 talloc_free(rec); 1221 if (result == ISC_R_SUCCESS) { 1222 state->log(ISC_LOG_ERROR, "samba_dlz: added %s %s", name, rdatastr); 1223 } 1224 return result; 1593 return ISC_R_FAILURE; 1594 } 1595 1596 if (tombstoned) { 1597 /* 1598 * we need to keep the existing tombstone record 1599 * and ignore it 1600 */ 1601 first = num_recs; 1225 1602 } 1226 1603 … … 1228 1605 * replace a record or add to it 1229 1606 */ 1230 el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); 1231 if (el == NULL) { 1232 state->log(ISC_LOG_ERROR, "samba_dlz: no dnsRecord attribute for %s", 1233 ldb_dn_get_linearized(dn)); 1607 for (i=first; i < num_recs; i++) { 1608 if (b9_record_match(state, rec, &recs[i])) { 1609 break; 1610 } 1611 } 1612 if (i == UINT16_MAX) { 1613 state->log(ISC_LOG_ERROR, "samba_dlz: failed to already %u dnsRecord values for %s", 1614 i, ldb_dn_get_linearized(dn)); 1234 1615 talloc_free(rec); 1235 1616 return ISC_R_FAILURE; 1236 1617 } 1237 1618 1238 for (i=0; i<el->num_values; i++) { 1239 struct dnsp_DnssrvRpcRecord rec2; 1240 1241 ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, 1242 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 1243 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1244 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", 1245 ldb_dn_get_linearized(dn)); 1246 talloc_free(rec); 1247 return ISC_R_FAILURE; 1248 } 1249 1250 if (b9_record_match(state, rec, &rec2)) { 1251 break; 1252 } 1253 } 1254 if (i == el->num_values) { 1619 if (i == num_recs) { 1255 1620 /* adding a new value */ 1256 el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1); 1257 if (el->values == NULL) { 1621 recs = talloc_realloc(rec, recs, 1622 struct dnsp_DnssrvRpcRecord, 1623 num_recs + 1); 1624 if (recs == NULL) { 1258 1625 talloc_free(rec); 1259 1626 return ISC_R_NOMEMORY; 1260 1627 } 1261 el->num_values++; 1262 } 1263 1264 ndr_err = ndr_push_struct_blob(&el->values[i], rec, rec, 1265 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); 1266 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1267 state->log(ISC_LOG_ERROR, "samba_dlz: failed to push dnsRecord for %s", 1268 ldb_dn_get_linearized(dn)); 1628 num_recs++; 1629 } 1630 1631 recs[i] = *rec; 1632 1633 if (!b9_set_session_info(state, name)) { 1269 1634 talloc_free(rec); 1270 1635 return ISC_R_FAILURE; … … 1272 1637 1273 1638 /* modify the record */ 1274 el->flags = LDB_FLAG_MOD_REPLACE; 1275 ret = ldb_modify(state->samdb, res->msgs[0]); 1276 if (ret != LDB_SUCCESS) { 1277 state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", 1278 ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); 1639 werr = dns_common_replace(state->samdb, rec, dn, 1640 needs_add, 1641 state->soa_serial, 1642 recs, num_recs); 1643 b9_reset_session_info(state); 1644 if (!W_ERROR_IS_OK(werr)) { 1645 state->log(ISC_LOG_ERROR, "samba_dlz: failed to %s %s - %s", 1646 needs_add ? "add" : "modify", 1647 ldb_dn_get_linearized(dn), win_errstr(werr)); 1279 1648 talloc_free(rec); 1280 1649 return ISC_R_FAILURE; … … 1296 1665 struct ldb_dn *dn; 1297 1666 isc_result_t result; 1298 struct ldb_result *res; 1299 const char *attrs[] = { "dnsRecord", NULL }; 1300 int ret, i; 1301 struct ldb_message_element *el; 1302 enum ndr_err_code ndr_err; 1667 struct dnsp_DnssrvRpcRecord *recs = NULL; 1668 uint16_t num_recs = 0; 1669 uint16_t i; 1670 WERROR werr; 1303 1671 1304 1672 if (state->transaction_token != (void*)version) { 1305 state->log(ISC_LOG_ INFO, "samba_dlz: bad transaction version");1673 state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); 1306 1674 return ISC_R_FAILURE; 1307 1675 } … … 1313 1681 1314 1682 if (!b9_parse(state, rdatastr, rec)) { 1315 state->log(ISC_LOG_ INFO, "samba_dlz: failed to parse rdataset '%s'", rdatastr);1683 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse rdataset '%s'", rdatastr); 1316 1684 talloc_free(rec); 1317 1685 return ISC_R_FAILURE; … … 1326 1694 1327 1695 /* get the existing records */ 1328 ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); 1329 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1696 werr = dns_common_lookup(state->samdb, rec, dn, 1697 &recs, &num_recs, NULL); 1698 if (!W_ERROR_IS_OK(werr)) { 1330 1699 talloc_free(rec); 1331 1700 return ISC_R_NOTFOUND; 1332 1701 } 1333 1702 1334 /* there are existing records. We need to see if any match 1335 */ 1336 el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); 1337 if (el == NULL || el->num_values == 0) { 1338 state->log(ISC_LOG_ERROR, "samba_dlz: no dnsRecord attribute for %s", 1339 ldb_dn_get_linearized(dn)); 1340 talloc_free(rec); 1341 return ISC_R_FAILURE; 1342 } 1343 1344 for (i=0; i<el->num_values; i++) { 1345 struct dnsp_DnssrvRpcRecord rec2; 1346 1347 ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, 1348 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 1349 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1350 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", 1351 ldb_dn_get_linearized(dn)); 1352 talloc_free(rec); 1353 return ISC_R_FAILURE; 1354 } 1355 1356 if (b9_record_match(state, rec, &rec2)) { 1703 for (i=0; i < num_recs; i++) { 1704 if (b9_record_match(state, rec, &recs[i])) { 1705 recs[i] = (struct dnsp_DnssrvRpcRecord) { 1706 .wType = DNS_TYPE_TOMBSTONE, 1707 }; 1357 1708 break; 1358 1709 } 1359 1710 } 1360 if (i == el->num_values) {1711 if (i == num_recs) { 1361 1712 talloc_free(rec); 1362 1713 return ISC_R_NOTFOUND; 1363 1714 } 1364 1715 1365 if (i < el->num_values-1) { 1366 memmove(&el->values[i], &el->values[i+1], sizeof(el->values[0])*((el->num_values-1)-i)); 1367 } 1368 el->num_values--; 1369 1370 if (el->num_values == 0) { 1371 /* delete the record */ 1372 ret = ldb_delete(state->samdb, dn); 1373 } else { 1374 /* modify the record */ 1375 el->flags = LDB_FLAG_MOD_REPLACE; 1376 ret = ldb_modify(state->samdb, res->msgs[0]); 1377 } 1378 if (ret != LDB_SUCCESS) { 1716 if (!b9_set_session_info(state, name)) { 1717 talloc_free(rec); 1718 return ISC_R_FAILURE; 1719 } 1720 1721 /* modify the record */ 1722 werr = dns_common_replace(state->samdb, rec, dn, 1723 false,/* needs_add */ 1724 state->soa_serial, 1725 recs, num_recs); 1726 b9_reset_session_info(state); 1727 if (!W_ERROR_IS_OK(werr)) { 1379 1728 state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", 1380 ldb_dn_get_linearized(dn), ldb_errstring(state->samdb));1729 ldb_dn_get_linearized(dn), win_errstr(werr)); 1381 1730 talloc_free(rec); 1382 1731 return ISC_R_FAILURE; … … 1399 1748 struct ldb_dn *dn; 1400 1749 isc_result_t result; 1401 struct ldb_result *res;1402 const char *attrs[] = { "dnsRecord", NULL };1403 int ret, i;1404 struct ldb_message_element *el;1405 enum ndr_err_code ndr_err;1406 1750 enum dns_record_type dns_type; 1407 1751 bool found = false; 1752 struct dnsp_DnssrvRpcRecord *recs = NULL; 1753 uint16_t num_recs = 0; 1754 uint16_t ri = 0; 1755 WERROR werr; 1408 1756 1409 1757 if (state->transaction_token != (void*)version) { 1410 state->log(ISC_LOG_ INFO, "samba_dlz: bad transaction version");1758 state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); 1411 1759 return ISC_R_FAILURE; 1412 1760 } 1413 1761 1414 1762 if (!b9_dns_type(type, &dns_type)) { 1415 state->log(ISC_LOG_ INFO, "samba_dlz: bad dns type %s in delete", type);1763 state->log(ISC_LOG_ERROR, "samba_dlz: bad dns type %s in delete", type); 1416 1764 return ISC_R_FAILURE; 1417 1765 } … … 1427 1775 1428 1776 /* get the existing records */ 1429 ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); 1430 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1777 werr = dns_common_lookup(state->samdb, tmp_ctx, dn, 1778 &recs, &num_recs, NULL); 1779 if (!W_ERROR_IS_OK(werr)) { 1431 1780 talloc_free(tmp_ctx); 1432 1781 return ISC_R_NOTFOUND; 1433 1782 } 1434 1783 1435 /* there are existing records. We need to see if any match the type 1436 */ 1437 el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); 1438 if (el == NULL || el->num_values == 0) { 1439 talloc_free(tmp_ctx); 1440 return ISC_R_NOTFOUND; 1441 } 1442 1443 for (i=0; i<el->num_values; i++) { 1444 struct dnsp_DnssrvRpcRecord rec2; 1445 1446 ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec2, 1447 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 1448 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1449 state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", 1450 ldb_dn_get_linearized(dn)); 1451 talloc_free(tmp_ctx); 1452 return ISC_R_FAILURE; 1453 } 1454 1455 if (dns_type == rec2.wType) { 1456 if (i < el->num_values-1) { 1457 memmove(&el->values[i], &el->values[i+1], 1458 sizeof(el->values[0])*((el->num_values-1)-i)); 1459 } 1460 el->num_values--; 1461 i--; 1462 found = true; 1463 } 1784 for (ri=0; ri < num_recs; ri++) { 1785 if (dns_type != recs[ri].wType) { 1786 continue; 1787 } 1788 1789 found = true; 1790 recs[ri] = (struct dnsp_DnssrvRpcRecord) { 1791 .wType = DNS_TYPE_TOMBSTONE, 1792 }; 1464 1793 } 1465 1794 … … 1469 1798 } 1470 1799 1471 if (el->num_values == 0) { 1472 /* delete the record */ 1473 ret = ldb_delete(state->samdb, dn); 1474 } else { 1475 /* modify the record */ 1476 el->flags = LDB_FLAG_MOD_REPLACE; 1477 ret = ldb_modify(state->samdb, res->msgs[0]); 1478 } 1479 if (ret != LDB_SUCCESS) { 1480 state->log(ISC_LOG_ERROR, "samba_dlz: failed to delete type %s in %s - %s", 1481 type, ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); 1800 if (!b9_set_session_info(state, name)) { 1801 talloc_free(tmp_ctx); 1802 return ISC_R_FAILURE; 1803 } 1804 1805 /* modify the record */ 1806 werr = dns_common_replace(state->samdb, tmp_ctx, dn, 1807 false,/* needs_add */ 1808 state->soa_serial, 1809 recs, num_recs); 1810 b9_reset_session_info(state); 1811 if (!W_ERROR_IS_OK(werr)) { 1812 state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", 1813 ldb_dn_get_linearized(dn), win_errstr(werr)); 1482 1814 talloc_free(tmp_ctx); 1483 1815 return ISC_R_FAILURE; -
vendor/current/source4/dns_server/dlz_minimal.h
r740 r988 17 17 */ 18 18 19 /* 20 This header provides a minimal set of defines and typedefs needed 21 for building an external DLZ module for bind9. When creating a new 22 external DLZ driver, please copy this header into your own source 23 tree. 24 */ 19 /* This header is updated based on BIND 9.10.1 source. 20 * contrib/dlz/modules/include/dlz_minimal.h 21 */ 22 23 #ifndef DLZ_MINIMAL_H 24 #define DLZ_MINIMAL_H 1 25 26 #ifdef BIND_VERSION_9_8 27 #define DLZ_DLOPEN_VERSION 1 28 #elif BIND_VERSION_9_9 29 #define DLZ_DLOPEN_VERSION 2 30 #elif BIND_VERSION_9_10 31 #define DLZ_DLOPEN_VERSION 3 32 #define DLZ_DLOPEN_AGE 0 33 #else 34 #error Unsupported BIND version 35 #endif 36 25 37 typedef unsigned int isc_result_t; 38 #if DLZ_DLOPEN_VERSION == 1 26 39 typedef bool isc_boolean_t; 40 #else 41 typedef int isc_boolean_t; 42 #endif 27 43 typedef uint32_t dns_ttl_t; 28 44 29 #define DLZ_DLOPEN_VERSION 1 30 31 /* return this in flags to dlz_version() if thread safe */ 45 /* return these in flags from dlz_version() */ 32 46 #define DNS_SDLZFLAG_THREADSAFE 0x00000001U 47 #define DNS_SDLZFLAG_RELATIVEOWNER 0x00000002U 48 #define DNS_SDLZFLAG_RELATIVERDATA 0x00000004U 33 49 34 50 /* result codes */ 35 51 #define ISC_R_SUCCESS 0 36 52 #define ISC_R_NOMEMORY 1 53 #define ISC_R_NOPERM 6 54 #define ISC_R_NOSPACE 19 37 55 #define ISC_R_NOTFOUND 23 38 56 #define ISC_R_FAILURE 25 57 #define ISC_R_NOTIMPLEMENTED 27 58 #define ISC_R_NOMORE 29 59 #define ISC_R_INVALIDFILE 30 60 #define ISC_R_UNEXPECTED 34 61 #define ISC_R_FILENOTFOUND 38 62 63 /* boolean values */ 64 #define ISC_TRUE 1 65 #define ISC_FALSE 0 39 66 40 67 /* log levels */ … … 44 71 #define ISC_LOG_ERROR (-4) 45 72 #define ISC_LOG_CRITICAL (-5) 46 47 /* some opaque structures */ 73 #define ISC_LOG_DEBUG(level) (level) 74 75 /* opaque structures */ 48 76 typedef void *dns_sdlzlookup_t; 49 77 typedef void *dns_sdlzallnodes_t; 50 78 typedef void *dns_view_t; 51 52 /* 53 * prototypes for the functions you can include in your driver 54 */ 55 79 typedef void *dns_dlzdb_t; 80 81 #if DLZ_DLOPEN_VERSION > 1 82 /* 83 * Method and type definitions needed for retrieval of client info 84 * from the caller. 85 */ 86 typedef struct isc_sockaddr { 87 union { 88 struct sockaddr sa; 89 struct sockaddr_in sin; 90 struct sockaddr_in6 sin6; 91 struct sockaddr_un sunix; 92 } type; 93 unsigned int length; 94 void * link; 95 } isc_sockaddr_t; 96 97 #define DNS_CLIENTINFO_VERSION 1 98 typedef struct dns_clientinfo { 99 uint16_t version; 100 void *data; 101 } dns_clientinfo_t; 102 103 typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client, 104 isc_sockaddr_t **addrp); 105 106 #define DNS_CLIENTINFOMETHODS_VERSION 1 107 #define DNS_CLIENTINFOMETHODS_AGE 0 108 109 typedef struct dns_clientinfomethods { 110 uint16_t version; 111 uint16_t age; 112 dns_clientinfo_sourceip_t sourceip; 113 } dns_clientinfomethods_t; 114 #endif /* DLZ_DLOPEN_VERSION > 1 */ 115 116 /* 117 * Method definitions for callbacks provided by the dlopen driver 118 */ 119 120 typedef void log_t(int level, const char *fmt, ...); 121 122 typedef isc_result_t dns_sdlz_putrr_t(dns_sdlzlookup_t *lookup, 123 const char *type, 124 dns_ttl_t ttl, 125 const char *data); 126 127 typedef isc_result_t dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes, 128 const char *name, 129 const char *type, 130 dns_ttl_t ttl, 131 const char *data); 132 133 #if DLZ_DLOPEN_VERSION < 3 134 typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view, 135 const char *zone_name); 136 #else /* DLZ_DLOPEN_VERSION >= 3 */ 137 typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view, 138 dns_dlzdb_t *dlzdb, 139 const char *zone_name); 140 #endif /* DLZ_DLOPEN_VERSION */ 141 142 /* 143 * prototypes for the functions you can include in your module 144 */ 56 145 57 146 /* 58 147 * dlz_version() is required for all DLZ external drivers. It should 59 * return DLZ_DLOPEN_VERSION 60 */ 61 int dlz_version(unsigned int *flags); 148 * return DLZ_DLOPEN_VERSION. 'flags' is updated to indicate capabilities 149 * of the module. In particular, if the module is thread-safe then it 150 * sets 'flags' to include DNS_SDLZFLAG_THREADSAFE. Other capability 151 * flags may be added in the future. 152 */ 153 int 154 dlz_version(unsigned int *flags); 62 155 63 156 /* 64 157 * dlz_create() is required for all DLZ external drivers. 65 158 */ 66 isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...); 159 isc_result_t 160 dlz_create(const char *dlzname, unsigned int argc, const char *argv[], 161 void **dbdata, ...); 67 162 68 163 /* … … 70 165 * unloaded if supplied 71 166 */ 72 void dlz_destroy(void *dbdata); 73 74 /* 75 dlz_findzonedb is required for all DLZ external drivers 76 */ 77 isc_result_t dlz_findzonedb(void *dbdata, const char *name); 78 79 /* 80 dlz_lookup is required for all DLZ external drivers 81 */ 82 isc_result_t dlz_lookup(const char *zone, const char *name, 83 void *dbdata, dns_sdlzlookup_t *lookup); 84 85 /* 86 dlz_allowzonexfr() is optional, and should be supplied if you want 87 to support zone transfers 88 */ 89 isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client); 90 91 92 /* 93 dlz_allnodes() is optional, but must be supplied if supply a 94 dlz_allowzonexfr() function 95 */ 96 isc_result_t dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes); 97 98 /* 99 dlz_newversion() is optional. It should be supplied if you want to 100 support dynamic updates. 101 */ 102 isc_result_t dlz_newversion(const char *zone, void *dbdata, void **versionp); 103 104 /* 105 dlz_closeversion() is optional, but must be supplied if you supply 106 a dlz_newversion() function 107 */ 108 void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void **versionp); 109 110 /* 111 dlz_configure() is optional, but must be supplied if you want to 112 support dynamic updates 113 */ 114 isc_result_t dlz_configure(dns_view_t *view, void *dbdata); 115 116 /* 117 dlz_ssumatch() is optional, but must be supplied if you want to 118 support dynamic updates 119 */ 120 isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, 121 const char *type, const char *key, uint32_t keydatalen, uint8_t *keydata, 122 void *dbdata); 123 124 /* 125 dlz_addrdataset() is optional, but must be supplied if you want to 126 support dynamic updates 127 */ 128 isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); 129 130 /* 131 dlz_subrdataset() is optional, but must be supplied if you want to 132 support dynamic updates 133 */ 134 isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); 135 136 /* 137 dlz_delrdataset() is optional, but must be supplied if you want to 138 support dynamic updates 139 */ 140 isc_result_t dlz_delrdataset(const char *name, const char *type, void *dbdata, void *version); 167 void 168 dlz_destroy(void *dbdata); 169 170 /* 171 * dlz_findzonedb is required for all DLZ external drivers 172 */ 173 #if DLZ_DLOPEN_VERSION < 3 174 isc_result_t 175 dlz_findzonedb(void *dbdata, const char *name); 176 #else /* DLZ_DLOPEN_VERSION >= 3 */ 177 isc_result_t 178 dlz_findzonedb(void *dbdata, const char *name, 179 dns_clientinfomethods_t *methods, 180 dns_clientinfo_t *clientinfo); 181 #endif /* DLZ_DLOPEN_VERSION */ 182 183 /* 184 * dlz_lookup is required for all DLZ external drivers 185 */ 186 #if DLZ_DLOPEN_VERSION == 1 187 isc_result_t 188 dlz_lookup(const char *zone, const char *name, void *dbdata, 189 dns_sdlzlookup_t *lookup); 190 #else /* DLZ_DLOPEN_VERSION > 1 */ 191 isc_result_t 192 dlz_lookup(const char *zone, const char *name, void *dbdata, 193 dns_sdlzlookup_t *lookup, 194 dns_clientinfomethods_t *methods, 195 dns_clientinfo_t *clientinfo); 196 #endif /* DLZ_DLOPEN_VERSION */ 197 198 /* 199 * dlz_authority() is optional if dlz_lookup() supplies 200 * authority information (i.e., SOA, NS) for the dns record 201 */ 202 isc_result_t 203 dlz_authority(const char *zone, void *dbdata, dns_sdlzlookup_t *lookup); 204 205 /* 206 * dlz_allowzonexfr() is optional, and should be supplied if you want to 207 * support zone transfers 208 */ 209 isc_result_t 210 dlz_allowzonexfr(void *dbdata, const char *name, const char *client); 211 212 /* 213 * dlz_allnodes() is optional, but must be supplied if supply a 214 * dlz_allowzonexfr() function 215 */ 216 isc_result_t 217 dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes); 218 219 /* 220 * dlz_newversion() is optional. It should be supplied if you want to 221 * support dynamic updates. 222 */ 223 isc_result_t 224 dlz_newversion(const char *zone, void *dbdata, void **versionp); 225 226 /* 227 * dlz_closeversion() is optional, but must be supplied if you supply a 228 * dlz_newversion() function 229 */ 230 void 231 dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, 232 void **versionp); 233 234 /* 235 * dlz_configure() is optional, but must be supplied if you want to support 236 * dynamic updates 237 */ 238 #if DLZ_DLOPEN_VERSION < 3 239 isc_result_t 240 dlz_configure(dns_view_t *view, void *dbdata); 241 #else /* DLZ_DLOPEN_VERSION >= 3 */ 242 isc_result_t 243 dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata); 244 #endif /* DLZ_DLOPEN_VERSION */ 245 246 /* 247 * dlz_ssumatch() is optional, but must be supplied if you want to support 248 * dynamic updates 249 */ 250 isc_boolean_t 251 dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, 252 const char *type, const char *key, uint32_t keydatalen, 253 uint8_t *keydata, void *dbdata); 254 255 /* 256 * dlz_addrdataset() is optional, but must be supplied if you want to 257 * support dynamic updates 258 */ 259 isc_result_t 260 dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, 261 void *version); 262 263 /* 264 * dlz_subrdataset() is optional, but must be supplied if you want to 265 * support dynamic updates 266 */ 267 isc_result_t 268 dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, 269 void *version); 270 271 /* 272 * dlz_delrdataset() is optional, but must be supplied if you want to 273 * support dynamic updates 274 */ 275 isc_result_t 276 dlz_delrdataset(const char *name, const char *type, void *dbdata, 277 void *version); 278 279 #endif /* DLZ_MINIMAL_H */ -
vendor/current/source4/dns_server/dns_query.c
r740 r988 21 21 22 22 #include "includes.h" 23 #include "smbd/service_task.h" 23 24 #include "libcli/util/werror.h" 24 25 #include "librpc/ndr/libndr.h" … … 26 27 #include "librpc/gen_ndr/ndr_dnsp.h" 27 28 #include <ldb.h> 29 #include "param/param.h" 28 30 #include "dsdb/samdb/samdb.h" 29 31 #include "dsdb/common/util.h" 30 32 #include "dns_server/dns_server.h" 31 32 static WERROR handle_question(struct dns_server *dns, 33 TALLOC_CTX *mem_ctx, 34 const struct dns_name_question *question, 35 struct dns_res_rec **answers, uint16_t *ancount) 36 { 37 struct dns_res_rec *ans; 33 #include "libcli/dns/libdns.h" 34 #include "lib/util/util_net.h" 35 #include "lib/util/tevent_werror.h" 36 #include "auth/auth.h" 37 #include "auth/credentials/credentials.h" 38 #include "auth/gensec/gensec.h" 39 40 #undef DBGC_CLASS 41 #define DBGC_CLASS DBGC_DNS 42 43 static WERROR add_response_rr(const char *name, 44 const struct dnsp_DnssrvRpcRecord *rec, 45 struct dns_res_rec **answers) 46 { 47 struct dns_res_rec *ans = *answers; 48 uint16_t ai = talloc_array_length(ans); 49 enum ndr_err_code ndr_err; 50 51 if (ai == UINT16_MAX) { 52 return WERR_BUFFER_OVERFLOW; 53 } 54 55 /* 56 * "ans" is always non-NULL and thus its own talloc context 57 */ 58 ans = talloc_realloc(ans, ans, struct dns_res_rec, ai+1); 59 if (ans == NULL) { 60 return WERR_NOMEM; 61 } 62 63 ZERO_STRUCT(ans[ai]); 64 65 switch (rec->wType) { 66 case DNS_QTYPE_CNAME: 67 ans[ai].rdata.cname_record = talloc_strdup(ans, rec->data.cname); 68 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.cname_record); 69 break; 70 case DNS_QTYPE_A: 71 ans[ai].rdata.ipv4_record = talloc_strdup(ans, rec->data.ipv4); 72 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv4_record); 73 break; 74 case DNS_QTYPE_AAAA: 75 ans[ai].rdata.ipv6_record = talloc_strdup(ans, rec->data.ipv6); 76 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv6_record); 77 break; 78 case DNS_TYPE_NS: 79 ans[ai].rdata.ns_record = talloc_strdup(ans, rec->data.ns); 80 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ns_record); 81 break; 82 case DNS_QTYPE_SRV: 83 ans[ai].rdata.srv_record.priority = rec->data.srv.wPriority; 84 ans[ai].rdata.srv_record.weight = rec->data.srv.wWeight; 85 ans[ai].rdata.srv_record.port = rec->data.srv.wPort; 86 ans[ai].rdata.srv_record.target = talloc_strdup( 87 ans, rec->data.srv.nameTarget); 88 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.srv_record.target); 89 break; 90 case DNS_QTYPE_SOA: 91 ans[ai].rdata.soa_record.mname = talloc_strdup( 92 ans, rec->data.soa.mname); 93 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.mname); 94 ans[ai].rdata.soa_record.rname = talloc_strdup( 95 ans, rec->data.soa.rname); 96 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.rname); 97 ans[ai].rdata.soa_record.serial = rec->data.soa.serial; 98 ans[ai].rdata.soa_record.refresh = rec->data.soa.refresh; 99 ans[ai].rdata.soa_record.retry = rec->data.soa.retry; 100 ans[ai].rdata.soa_record.expire = rec->data.soa.expire; 101 ans[ai].rdata.soa_record.minimum = rec->data.soa.minimum; 102 break; 103 case DNS_QTYPE_PTR: 104 ans[ai].rdata.ptr_record = talloc_strdup(ans, rec->data.ptr); 105 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ptr_record); 106 break; 107 case DNS_QTYPE_MX: 108 ans[ai].rdata.mx_record.preference = rec->data.mx.wPriority; 109 ans[ai].rdata.mx_record.exchange = talloc_strdup( 110 ans, rec->data.mx.nameTarget); 111 if (ans[ai].rdata.mx_record.exchange == NULL) { 112 return WERR_NOMEM; 113 } 114 break; 115 case DNS_QTYPE_TXT: 116 ndr_err = ndr_dnsp_string_list_copy(ans, 117 &rec->data.txt, 118 &ans[ai].rdata.txt_record.txt); 119 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 120 return WERR_NOMEM; 121 } 122 break; 123 default: 124 DEBUG(0, ("Got unhandled type %u query.\n", rec->wType)); 125 return DNS_ERR(NOT_IMPLEMENTED); 126 } 127 128 ans[ai].name = talloc_strdup(ans, name); 129 W_ERROR_HAVE_NO_MEMORY(ans[ai].name); 130 ans[ai].rr_type = rec->wType; 131 ans[ai].rr_class = DNS_QCLASS_IN; 132 ans[ai].ttl = rec->dwTtlSeconds; 133 ans[ai].length = UINT16_MAX; 134 135 *answers = ans; 136 137 return WERR_OK; 138 } 139 140 static WERROR add_dns_res_rec(struct dns_res_rec **pdst, 141 const struct dns_res_rec *src) 142 { 143 struct dns_res_rec *dst = *pdst; 144 uint16_t di = talloc_array_length(dst); 145 enum ndr_err_code ndr_err; 146 147 if (di == UINT16_MAX) { 148 return WERR_BUFFER_OVERFLOW; 149 } 150 151 dst = talloc_realloc(dst, dst, struct dns_res_rec, di+1); 152 if (dst == NULL) { 153 return WERR_NOMEM; 154 } 155 156 ZERO_STRUCT(dst[di]); 157 158 dst[di] = (struct dns_res_rec) { 159 .name = talloc_strdup(dst, src->name), 160 .rr_type = src->rr_type, 161 .rr_class = src->rr_class, 162 .ttl = src->ttl, 163 .length = src->length 164 }; 165 166 if (dst[di].name == NULL) { 167 return WERR_NOMEM; 168 } 169 170 switch (src->rr_type) { 171 case DNS_QTYPE_CNAME: 172 dst[di].rdata.cname_record = talloc_strdup( 173 dst, src->rdata.cname_record); 174 if (dst[di].rdata.cname_record == NULL) { 175 return WERR_NOMEM; 176 } 177 break; 178 case DNS_QTYPE_A: 179 dst[di].rdata.ipv4_record = talloc_strdup( 180 dst, src->rdata.ipv4_record); 181 if (dst[di].rdata.ipv4_record == NULL) { 182 return WERR_NOMEM; 183 } 184 break; 185 case DNS_QTYPE_AAAA: 186 dst[di].rdata.ipv6_record = talloc_strdup( 187 dst, src->rdata.ipv6_record); 188 if (dst[di].rdata.ipv6_record == NULL) { 189 return WERR_NOMEM; 190 } 191 break; 192 case DNS_TYPE_NS: 193 dst[di].rdata.ns_record = talloc_strdup( 194 dst, src->rdata.ns_record); 195 if (dst[di].rdata.ns_record == NULL) { 196 return WERR_NOMEM; 197 } 198 break; 199 case DNS_QTYPE_SRV: 200 dst[di].rdata.srv_record = (struct dns_srv_record) { 201 .priority = src->rdata.srv_record.priority, 202 .weight = src->rdata.srv_record.weight, 203 .port = src->rdata.srv_record.port, 204 .target = talloc_strdup( 205 dst, src->rdata.srv_record.target) 206 }; 207 if (dst[di].rdata.srv_record.target == NULL) { 208 return WERR_NOMEM; 209 } 210 break; 211 case DNS_QTYPE_SOA: 212 dst[di].rdata.soa_record = (struct dns_soa_record) { 213 .mname = talloc_strdup( 214 dst, src->rdata.soa_record.mname), 215 .rname = talloc_strdup( 216 dst, src->rdata.soa_record.rname), 217 .serial = src->rdata.soa_record.serial, 218 .refresh = src->rdata.soa_record.refresh, 219 .retry = src->rdata.soa_record.retry, 220 .expire = src->rdata.soa_record.expire, 221 .minimum = src->rdata.soa_record.minimum 222 }; 223 224 if ((dst[di].rdata.soa_record.mname == NULL) || 225 (dst[di].rdata.soa_record.rname == NULL)) { 226 return WERR_NOMEM; 227 } 228 229 break; 230 case DNS_QTYPE_PTR: 231 dst[di].rdata.ptr_record = talloc_strdup( 232 dst, src->rdata.ptr_record); 233 if (dst[di].rdata.ptr_record == NULL) { 234 return WERR_NOMEM; 235 } 236 break; 237 case DNS_QTYPE_MX: 238 dst[di].rdata.mx_record = (struct dns_mx_record) { 239 .preference = src->rdata.mx_record.preference, 240 .exchange = talloc_strdup( 241 src, src->rdata.mx_record.exchange) 242 }; 243 244 if (dst[di].rdata.mx_record.exchange == NULL) { 245 return WERR_NOMEM; 246 } 247 break; 248 case DNS_QTYPE_TXT: 249 ndr_err = ndr_dnsp_string_list_copy(dst, 250 &src->rdata.txt_record.txt, 251 &dst[di].rdata.txt_record.txt); 252 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 253 return WERR_NOMEM; 254 } 255 break; 256 default: 257 DBG_WARNING("Got unhandled type %u query.\n", src->rr_type); 258 return DNS_ERR(NOT_IMPLEMENTED); 259 } 260 261 *pdst = dst; 262 263 return WERR_OK; 264 } 265 266 struct ask_forwarder_state { 267 struct tevent_context *ev; 268 uint16_t id; 269 struct dns_name_packet in_packet; 270 }; 271 272 static void ask_forwarder_done(struct tevent_req *subreq); 273 274 static struct tevent_req *ask_forwarder_send( 275 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 276 struct dns_server *dns, 277 const char *forwarder, struct dns_name_question *question) 278 { 279 struct tevent_req *req, *subreq; 280 struct ask_forwarder_state *state; 281 struct dns_res_rec *options; 282 struct dns_name_packet out_packet = { 0, }; 283 DATA_BLOB out_blob; 284 enum ndr_err_code ndr_err; 285 WERROR werr; 286 287 req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state); 288 if (req == NULL) { 289 return NULL; 290 } 291 state->ev = ev; 292 generate_random_buffer((uint8_t *)&state->id, sizeof(state->id)); 293 294 if (!is_ipaddress(forwarder)) { 295 DEBUG(0, ("Invalid 'dns forwarder' setting '%s', needs to be " 296 "an IP address\n", forwarder)); 297 tevent_req_werror(req, DNS_ERR(NAME_ERROR)); 298 return tevent_req_post(req, ev); 299 } 300 301 out_packet.id = state->id; 302 out_packet.operation |= DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED; 303 out_packet.qdcount = 1; 304 out_packet.questions = question; 305 306 werr = dns_generate_options(dns, state, &options); 307 if (!W_ERROR_IS_OK(werr)) { 308 tevent_req_werror(req, werr); 309 return tevent_req_post(req, ev); 310 } 311 312 out_packet.arcount = 1; 313 out_packet.additional = options; 314 315 ndr_err = ndr_push_struct_blob( 316 &out_blob, state, &out_packet, 317 (ndr_push_flags_fn_t)ndr_push_dns_name_packet); 318 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 319 tevent_req_werror(req, DNS_ERR(SERVER_FAILURE)); 320 return tevent_req_post(req, ev); 321 } 322 subreq = dns_udp_request_send(state, ev, forwarder, out_blob.data, 323 out_blob.length); 324 if (tevent_req_nomem(subreq, req)) { 325 return tevent_req_post(req, ev); 326 } 327 tevent_req_set_callback(subreq, ask_forwarder_done, req); 328 return req; 329 } 330 331 static void ask_forwarder_done(struct tevent_req *subreq) 332 { 333 struct tevent_req *req = tevent_req_callback_data( 334 subreq, struct tevent_req); 335 struct ask_forwarder_state *state = tevent_req_data( 336 req, struct ask_forwarder_state); 337 DATA_BLOB in_blob; 338 enum ndr_err_code ndr_err; 339 int ret; 340 341 ret = dns_udp_request_recv(subreq, state, 342 &in_blob.data, &in_blob.length); 343 TALLOC_FREE(subreq); 344 345 if (ret != 0) { 346 tevent_req_werror(req, unix_to_werror(ret)); 347 return; 348 } 349 350 ndr_err = ndr_pull_struct_blob( 351 &in_blob, state, &state->in_packet, 352 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); 353 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 354 tevent_req_werror(req, DNS_ERR(SERVER_FAILURE)); 355 return; 356 } 357 if (state->in_packet.id != state->id) { 358 tevent_req_werror(req, DNS_ERR(NAME_ERROR)); 359 return; 360 } 361 tevent_req_done(req); 362 } 363 364 static WERROR ask_forwarder_recv( 365 struct tevent_req *req, TALLOC_CTX *mem_ctx, 366 struct dns_res_rec **answers, uint16_t *ancount, 367 struct dns_res_rec **nsrecs, uint16_t *nscount, 368 struct dns_res_rec **additional, uint16_t *arcount) 369 { 370 struct ask_forwarder_state *state = tevent_req_data( 371 req, struct ask_forwarder_state); 372 struct dns_name_packet *in_packet = &state->in_packet; 373 WERROR err; 374 375 if (tevent_req_is_werror(req, &err)) { 376 return err; 377 } 378 379 *ancount = in_packet->ancount; 380 *answers = talloc_move(mem_ctx, &in_packet->answers); 381 382 *nscount = in_packet->nscount; 383 *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs); 384 385 *arcount = in_packet->arcount; 386 *additional = talloc_move(mem_ctx, &in_packet->additional); 387 388 return WERR_OK; 389 } 390 391 static WERROR add_zone_authority_record(struct dns_server *dns, 392 TALLOC_CTX *mem_ctx, 393 const struct dns_name_question *question, 394 struct dns_res_rec **nsrecs) 395 { 396 const char *zone = NULL; 397 struct dnsp_DnssrvRpcRecord *recs; 398 struct dns_res_rec *ns = *nsrecs; 399 uint16_t rec_count; 38 400 struct ldb_dn *dn = NULL; 401 unsigned int ri; 39 402 WERROR werror; 40 static const char * const attrs[] = { "dnsRecord", NULL}; 41 int ret; 42 uint16_t ai = *ancount; 43 unsigned int ri; 44 struct ldb_message *msg = NULL; 403 404 zone = dns_get_authoritative_zone(dns, question->name); 405 DEBUG(10, ("Creating zone authority record for '%s'\n", zone)); 406 407 werror = dns_name2dn(dns, mem_ctx, zone, &dn); 408 if (!W_ERROR_IS_OK(werror)) { 409 return werror; 410 } 411 412 werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count); 413 if (!W_ERROR_IS_OK(werror)) { 414 return werror; 415 } 416 417 for (ri = 0; ri < rec_count; ri++) { 418 if (recs[ri].wType == DNS_TYPE_SOA) { 419 werror = add_response_rr(zone, &recs[ri], &ns); 420 if (!W_ERROR_IS_OK(werror)) { 421 return werror; 422 } 423 } 424 } 425 426 *nsrecs = ns; 427 428 return WERR_OK; 429 } 430 431 static struct tevent_req *handle_authoritative_send( 432 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 433 struct dns_server *dns, const char *forwarder, 434 struct dns_name_question *question, 435 struct dns_res_rec **answers, struct dns_res_rec **nsrecs); 436 static WERROR handle_authoritative_recv(struct tevent_req *req); 437 438 struct handle_dnsrpcrec_state { 439 struct dns_res_rec **answers; 440 struct dns_res_rec **nsrecs; 441 }; 442 443 static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq); 444 static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq); 445 446 static struct tevent_req *handle_dnsrpcrec_send( 447 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 448 struct dns_server *dns, const char *forwarder, 449 const struct dns_name_question *question, 450 struct dnsp_DnssrvRpcRecord *rec, 451 struct dns_res_rec **answers, struct dns_res_rec **nsrecs) 452 { 453 struct tevent_req *req, *subreq; 454 struct handle_dnsrpcrec_state *state; 455 struct dns_name_question *new_q; 456 bool resolve_cname; 457 WERROR werr; 458 459 req = tevent_req_create(mem_ctx, &state, 460 struct handle_dnsrpcrec_state); 461 if (req == NULL) { 462 return NULL; 463 } 464 state->answers = answers; 465 state->nsrecs = nsrecs; 466 467 resolve_cname = ((rec->wType == DNS_TYPE_CNAME) && 468 ((question->question_type == DNS_QTYPE_A) || 469 (question->question_type == DNS_QTYPE_AAAA))); 470 471 if (!resolve_cname) { 472 if ((question->question_type != DNS_QTYPE_ALL) && 473 (rec->wType != 474 (enum dns_record_type) question->question_type)) { 475 tevent_req_done(req); 476 return tevent_req_post(req, ev); 477 } 478 479 werr = add_response_rr(question->name, rec, state->answers); 480 if (tevent_req_werror(req, werr)) { 481 return tevent_req_post(req, ev); 482 } 483 484 tevent_req_done(req); 485 return tevent_req_post(req, ev); 486 } 487 488 werr = add_response_rr(question->name, rec, state->answers); 489 if (tevent_req_werror(req, werr)) { 490 return tevent_req_post(req, ev); 491 } 492 493 new_q = talloc(state, struct dns_name_question); 494 if (tevent_req_nomem(new_q, req)) { 495 return tevent_req_post(req, ev); 496 } 497 498 *new_q = (struct dns_name_question) { 499 .question_type = question->question_type, 500 .question_class = question->question_class, 501 .name = rec->data.cname 502 }; 503 504 if (dns_authorative_for_zone(dns, new_q->name)) { 505 subreq = handle_authoritative_send( 506 state, ev, dns, forwarder, new_q, 507 state->answers, state->nsrecs); 508 if (tevent_req_nomem(subreq, req)) { 509 return tevent_req_post(req, ev); 510 } 511 tevent_req_set_callback(subreq, handle_dnsrpcrec_gotauth, req); 512 return req; 513 } 514 515 subreq = ask_forwarder_send(state, ev, dns, forwarder, new_q); 516 if (tevent_req_nomem(subreq, req)) { 517 return tevent_req_post(req, ev); 518 } 519 tevent_req_set_callback(subreq, handle_dnsrpcrec_gotforwarded, req); 520 521 return req; 522 } 523 524 static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq) 525 { 526 struct tevent_req *req = tevent_req_callback_data( 527 subreq, struct tevent_req); 528 WERROR werr; 529 530 werr = handle_authoritative_recv(subreq); 531 TALLOC_FREE(subreq); 532 if (tevent_req_werror(req, werr)) { 533 return; 534 } 535 tevent_req_done(req); 536 } 537 538 static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq) 539 { 540 struct tevent_req *req = tevent_req_callback_data( 541 subreq, struct tevent_req); 542 struct handle_dnsrpcrec_state *state = tevent_req_data( 543 req, struct handle_dnsrpcrec_state); 544 struct dns_res_rec *answers, *nsrecs, *additional; 545 uint16_t ancount = 0; 546 uint16_t nscount = 0; 547 uint16_t arcount = 0; 548 uint16_t i; 549 WERROR werr; 550 551 werr = ask_forwarder_recv(subreq, state, &answers, &ancount, 552 &nsrecs, &nscount, &additional, &arcount); 553 if (tevent_req_werror(req, werr)) { 554 return; 555 } 556 557 for (i=0; i<ancount; i++) { 558 werr = add_dns_res_rec(state->answers, &answers[i]); 559 if (tevent_req_werror(req, werr)) { 560 return; 561 } 562 } 563 564 for (i=0; i<nscount; i++) { 565 werr = add_dns_res_rec(state->nsrecs, &nsrecs[i]); 566 if (tevent_req_werror(req, werr)) { 567 return; 568 } 569 } 570 571 tevent_req_done(req); 572 } 573 574 static WERROR handle_dnsrpcrec_recv(struct tevent_req *req) 575 { 576 return tevent_req_simple_recv_werror(req); 577 } 578 579 struct handle_authoritative_state { 580 struct tevent_context *ev; 581 struct dns_server *dns; 582 struct dns_name_question *question; 583 const char *forwarder; 584 45 585 struct dnsp_DnssrvRpcRecord *recs; 46 struct ldb_message_element *el; 47 48 werror = dns_name2dn(dns, mem_ctx, question->name, &dn); 49 W_ERROR_NOT_OK_RETURN(werror); 50 51 ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn, 52 LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)"); 53 if (ret != LDB_SUCCESS) { 54 return DNS_ERR(NAME_ERROR); 55 } 56 57 el = ldb_msg_find_element(msg, attrs[0]); 58 if (el == NULL) { 59 return DNS_ERR(NAME_ERROR); 60 } 61 62 recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values); 63 for (ri = 0; ri < el->num_values; ri++) { 64 struct ldb_val *v = &el->values[ri]; 65 enum ndr_err_code ndr_err; 66 67 ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri], 68 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); 69 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 70 DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); 71 return DNS_ERR(SERVER_FAILURE); 72 } 73 } 74 75 ans = talloc_realloc(mem_ctx, *answers, struct dns_res_rec, 76 ai + el->num_values); 77 W_ERROR_HAVE_NO_MEMORY(ans); 78 79 switch (question->question_type) { 80 case DNS_QTYPE_CNAME: 81 for (ri = 0; ri < el->num_values; ri++) { 82 if (recs[ri].wType != question->question_type) { 83 continue; 586 uint16_t rec_count; 587 uint16_t recs_done; 588 589 struct dns_res_rec **answers; 590 struct dns_res_rec **nsrecs; 591 }; 592 593 static void handle_authoritative_done(struct tevent_req *subreq); 594 595 static struct tevent_req *handle_authoritative_send( 596 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 597 struct dns_server *dns, const char *forwarder, 598 struct dns_name_question *question, 599 struct dns_res_rec **answers, struct dns_res_rec **nsrecs) 600 { 601 struct tevent_req *req, *subreq; 602 struct handle_authoritative_state *state; 603 struct ldb_dn *dn = NULL; 604 WERROR werr; 605 606 req = tevent_req_create(mem_ctx, &state, 607 struct handle_authoritative_state); 608 if (req == NULL) { 609 return NULL; 610 } 611 state->ev = ev; 612 state->dns = dns; 613 state->question = question; 614 state->forwarder = forwarder; 615 state->answers = answers; 616 state->nsrecs = nsrecs; 617 618 werr = dns_name2dn(dns, state, question->name, &dn); 619 if (tevent_req_werror(req, werr)) { 620 return tevent_req_post(req, ev); 621 } 622 623 werr = dns_lookup_records(dns, state, dn, &state->recs, 624 &state->rec_count); 625 TALLOC_FREE(dn); 626 if (tevent_req_werror(req, werr)) { 627 return tevent_req_post(req, ev); 628 } 629 630 if (state->rec_count == 0) { 631 tevent_req_werror(req, DNS_ERR(NAME_ERROR)); 632 return tevent_req_post(req, ev); 633 } 634 635 subreq = handle_dnsrpcrec_send( 636 state, state->ev, state->dns, state->forwarder, 637 state->question, &state->recs[state->recs_done], 638 state->answers, state->nsrecs); 639 if (tevent_req_nomem(subreq, req)) { 640 return tevent_req_post(req, ev); 641 } 642 tevent_req_set_callback(subreq, handle_authoritative_done, req); 643 return req; 644 } 645 646 static void handle_authoritative_done(struct tevent_req *subreq) 647 { 648 struct tevent_req *req = tevent_req_callback_data( 649 subreq, struct tevent_req); 650 struct handle_authoritative_state *state = tevent_req_data( 651 req, struct handle_authoritative_state); 652 WERROR werr; 653 654 werr = handle_dnsrpcrec_recv(subreq); 655 TALLOC_FREE(subreq); 656 if (tevent_req_werror(req, werr)) { 657 return; 658 } 659 660 state->recs_done += 1; 661 662 if (state->recs_done == state->rec_count) { 663 tevent_req_done(req); 664 return; 665 } 666 667 subreq = handle_dnsrpcrec_send( 668 state, state->ev, state->dns, state->forwarder, 669 state->question, &state->recs[state->recs_done], 670 state->answers, state->nsrecs); 671 if (tevent_req_nomem(subreq, req)) { 672 return; 673 } 674 tevent_req_set_callback(subreq, handle_authoritative_done, req); 675 } 676 677 static WERROR handle_authoritative_recv(struct tevent_req *req) 678 { 679 struct handle_authoritative_state *state = tevent_req_data( 680 req, struct handle_authoritative_state); 681 WERROR werr; 682 683 if (tevent_req_is_werror(req, &werr)) { 684 return werr; 685 } 686 687 werr = add_zone_authority_record(state->dns, state, state->question, 688 state->nsrecs); 689 if (!W_ERROR_IS_OK(werr)) { 690 return werr; 691 } 692 693 return WERR_OK; 694 } 695 696 static NTSTATUS create_tkey(struct dns_server *dns, 697 const char* name, 698 const char* algorithm, 699 struct dns_server_tkey **tkey) 700 { 701 NTSTATUS status; 702 struct dns_server_tkey_store *store = dns->tkeys; 703 struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey); 704 705 if (k == NULL) { 706 return NT_STATUS_NO_MEMORY; 707 } 708 709 k->name = talloc_strdup(k, name); 710 711 if (k->name == NULL) { 712 return NT_STATUS_NO_MEMORY; 713 } 714 715 k->algorithm = talloc_strdup(k, algorithm); 716 if (k->algorithm == NULL) { 717 return NT_STATUS_NO_MEMORY; 718 } 719 720 status = samba_server_gensec_start(k, 721 dns->task->event_ctx, 722 dns->task->msg_ctx, 723 dns->task->lp_ctx, 724 dns->server_credentials, 725 "dns", 726 &k->gensec); 727 if (!NT_STATUS_IS_OK(status)) { 728 DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status))); 729 *tkey = NULL; 730 return status; 731 } 732 733 gensec_want_feature(k->gensec, GENSEC_FEATURE_SIGN); 734 735 status = gensec_start_mech_by_oid(k->gensec, GENSEC_OID_SPNEGO); 736 737 if (!NT_STATUS_IS_OK(status)) { 738 DEBUG(1, ("Failed to start GENSEC server code: %s\n", 739 nt_errstr(status))); 740 *tkey = NULL; 741 return status; 742 } 743 744 if (store->tkeys[store->next_idx] != NULL) { 745 TALLOC_FREE(store->tkeys[store->next_idx]); 746 } 747 748 store->tkeys[store->next_idx] = k; 749 (store->next_idx)++; 750 store->next_idx %= store->size; 751 752 *tkey = k; 753 return NT_STATUS_OK; 754 } 755 756 static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx, 757 struct dns_server *dns, 758 struct dns_server_tkey *tkey, 759 const DATA_BLOB *key, 760 DATA_BLOB *reply, 761 uint16_t *dns_auth_error) 762 { 763 NTSTATUS status; 764 765 status = gensec_update_ev(tkey->gensec, mem_ctx, dns->task->event_ctx, 766 *key, reply); 767 768 if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) { 769 *dns_auth_error = DNS_RCODE_OK; 770 return status; 771 } 772 773 if (NT_STATUS_IS_OK(status)) { 774 775 status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info); 776 if (!NT_STATUS_IS_OK(status)) { 777 *dns_auth_error = DNS_RCODE_BADKEY; 778 return status; 779 } 780 *dns_auth_error = DNS_RCODE_OK; 781 } 782 783 return status; 784 } 785 786 static WERROR handle_tkey(struct dns_server *dns, 787 TALLOC_CTX *mem_ctx, 788 const struct dns_name_packet *in, 789 struct dns_request_state *state, 790 struct dns_res_rec **answers, 791 uint16_t *ancount) 792 { 793 struct dns_res_rec *in_tkey = NULL; 794 struct dns_res_rec *ret_tkey; 795 uint16_t i; 796 797 for (i = 0; i < in->arcount; i++) { 798 if (in->additional[i].rr_type == DNS_QTYPE_TKEY) { 799 in_tkey = &in->additional[i]; 800 break; 801 } 802 } 803 804 /* If this is a TKEY query, it should have a TKEY RR. 805 * Behaviour is not really specified in RFC 2930 or RFC 3645, but 806 * FORMAT_ERROR seems to be what BIND uses .*/ 807 if (in_tkey == NULL) { 808 return DNS_ERR(FORMAT_ERROR); 809 } 810 811 ret_tkey = talloc_zero(mem_ctx, struct dns_res_rec); 812 if (ret_tkey == NULL) { 813 return WERR_NOMEM; 814 } 815 816 ret_tkey->name = talloc_strdup(ret_tkey, in_tkey->name); 817 if (ret_tkey->name == NULL) { 818 return WERR_NOMEM; 819 } 820 821 ret_tkey->rr_type = DNS_QTYPE_TKEY; 822 ret_tkey->rr_class = DNS_QCLASS_ANY; 823 ret_tkey->length = UINT16_MAX; 824 825 ret_tkey->rdata.tkey_record.algorithm = talloc_strdup(ret_tkey, 826 in_tkey->rdata.tkey_record.algorithm); 827 if (ret_tkey->rdata.tkey_record.algorithm == NULL) { 828 return WERR_NOMEM; 829 } 830 831 ret_tkey->rdata.tkey_record.inception = in_tkey->rdata.tkey_record.inception; 832 ret_tkey->rdata.tkey_record.expiration = in_tkey->rdata.tkey_record.expiration; 833 ret_tkey->rdata.tkey_record.mode = in_tkey->rdata.tkey_record.mode; 834 835 switch (in_tkey->rdata.tkey_record.mode) { 836 case DNS_TKEY_MODE_DH: 837 /* FIXME: According to RFC 2930, we MUST support this, but we don't. 838 * Still, claim it's a bad key instead of a bad mode */ 839 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY; 840 break; 841 case DNS_TKEY_MODE_GSSAPI: { 842 NTSTATUS status; 843 struct dns_server_tkey *tkey; 844 DATA_BLOB key; 845 DATA_BLOB reply; 846 847 tkey = dns_find_tkey(dns->tkeys, in->questions[0].name); 848 if (tkey != NULL && tkey->complete) { 849 /* TODO: check if the key is still valid */ 850 DEBUG(1, ("Rejecting tkey negotiation for already established key\n")); 851 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADNAME; 852 break; 853 } 854 855 if (tkey == NULL) { 856 status = create_tkey(dns, in->questions[0].name, 857 in_tkey->rdata.tkey_record.algorithm, 858 &tkey); 859 if (!NT_STATUS_IS_OK(status)) { 860 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY; 861 return ntstatus_to_werror(status); 84 862 } 85 86 ZERO_STRUCT(ans[ai]); 87 ans[ai].name = talloc_strdup(ans, question->name); 88 ans[ai].rr_type = DNS_QTYPE_CNAME; 89 ans[ai].rr_class = DNS_QCLASS_IP; 90 ans[ai].ttl = recs[ri].dwTtlSeconds; 91 ans[ai].length = UINT16_MAX; 92 ans[ai].rdata.cname_record = talloc_strdup(ans, recs[ri].data.cname); 93 ai++; 94 } 95 break; 96 case DNS_QTYPE_A: 97 for (ri = 0; ri < el->num_values; ri++) { 98 if (recs[ri].wType != question->question_type) { 99 continue; 863 } 864 865 key.data = in_tkey->rdata.tkey_record.key_data; 866 key.length = in_tkey->rdata.tkey_record.key_size; 867 868 status = accept_gss_ticket(ret_tkey, dns, tkey, &key, &reply, 869 &ret_tkey->rdata.tkey_record.error); 870 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 871 DEBUG(1, ("More processing required\n")); 872 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY; 873 } else if (NT_STATUS_IS_OK(status)) { 874 DEBUG(1, ("Tkey handshake completed\n")); 875 ret_tkey->rdata.tkey_record.key_size = reply.length; 876 ret_tkey->rdata.tkey_record.key_data = talloc_memdup(ret_tkey, 877 reply.data, 878 reply.length); 879 state->sign = true; 880 state->key_name = talloc_strdup(state->mem_ctx, tkey->name); 881 if (state->key_name == NULL) { 882 return WERR_NOMEM; 100 883 } 101 102 /* TODO: if the record actually is a DNS_QTYPE_A */ 103 104 ZERO_STRUCT(ans[ai]); 105 ans[ai].name = talloc_strdup(ans, question->name); 106 ans[ai].rr_type = DNS_QTYPE_A; 107 ans[ai].rr_class = DNS_QCLASS_IP; 108 ans[ai].ttl = recs[ri].dwTtlSeconds; 109 ans[ai].length = UINT16_MAX; 110 ans[ai].rdata.ipv4_record = talloc_strdup(ans, recs[ri].data.ipv4); 111 ai++; 112 } 113 break; 114 case DNS_QTYPE_AAAA: 115 for (ri = 0; ri < el->num_values; ri++) { 116 if (recs[ri].wType != question->question_type) { 117 continue; 118 } 119 120 ZERO_STRUCT(ans[ai]); 121 ans[ai].name = talloc_strdup(ans, question->name); 122 ans[ai].rr_type = DNS_QTYPE_AAAA; 123 ans[ai].rr_class = DNS_QCLASS_IP; 124 ans[ai].ttl = recs[ri].dwTtlSeconds; 125 ans[ai].length = UINT16_MAX; 126 ans[ai].rdata.ipv6_record = recs[ri].data.ipv6; 127 ai++; 128 } 129 break; 130 case DNS_QTYPE_NS: 131 for (ri = 0; ri < el->num_values; ri++) { 132 if (recs[ri].wType != question->question_type) { 133 continue; 134 } 135 136 ZERO_STRUCT(ans[ai]); 137 ans[ai].name = question->name; 138 ans[ai].rr_type = DNS_QTYPE_NS; 139 ans[ai].rr_class = DNS_QCLASS_IP; 140 ans[ai].ttl = recs[ri].dwTtlSeconds; 141 ans[ai].length = UINT16_MAX; 142 ans[ai].rdata.ns_record = recs[ri].data.ns; 143 ai++; 144 } 145 break; 146 case DNS_QTYPE_SRV: 147 for (ri = 0; ri < el->num_values; ri++) { 148 if (recs[ri].wType != question->question_type) { 149 continue; 150 } 151 152 ZERO_STRUCT(ans[ai]); 153 ans[ai].name = question->name; 154 ans[ai].rr_type = DNS_QTYPE_SRV; 155 ans[ai].rr_class = DNS_QCLASS_IP; 156 ans[ai].ttl = recs[ri].dwTtlSeconds; 157 ans[ai].length = UINT16_MAX; 158 ans[ai].rdata.srv_record.priority = recs[ri].data.srv.wPriority; 159 ans[ai].rdata.srv_record.weight = recs[ri].data.srv.wWeight; 160 ans[ai].rdata.srv_record.port = recs[ri].data.srv.wPort; 161 ans[ai].rdata.srv_record.target = recs[ri].data.srv.nameTarget; 162 ai++; 163 } 164 break; 165 case DNS_QTYPE_SOA: 166 for (ri = 0; ri < el->num_values; ri++) { 167 if (recs[ri].wType != question->question_type) { 168 continue; 169 } 170 171 ZERO_STRUCT(ans[ai]); 172 ans[ai].name = question->name; 173 ans[ai].rr_type = DNS_QTYPE_SOA; 174 ans[ai].rr_class = DNS_QCLASS_IP; 175 ans[ai].ttl = recs[ri].dwTtlSeconds; 176 ans[ai].length = UINT16_MAX; 177 ans[ai].rdata.soa_record.mname = recs[ri].data.soa.mname; 178 ans[ai].rdata.soa_record.rname = recs[ri].data.soa.rname; 179 ans[ai].rdata.soa_record.serial = recs[ri].data.soa.serial; 180 ans[ai].rdata.soa_record.refresh= recs[ri].data.soa.refresh; 181 ans[ai].rdata.soa_record.retry = recs[ri].data.soa.retry; 182 ans[ai].rdata.soa_record.expire = recs[ri].data.soa.expire; 183 ans[ai].rdata.soa_record.minimum= recs[ri].data.soa.minimum; 184 ai++; 185 } 884 } else { 885 DEBUG(1, ("GSS key negotiation returned %s\n", nt_errstr(status))); 886 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY; 887 } 888 889 break; 890 } 891 case DNS_TKEY_MODE_DELETE: 892 /* TODO: implement me */ 893 DEBUG(1, ("Should delete tkey here\n")); 894 ret_tkey->rdata.tkey_record.error = DNS_RCODE_OK; 895 break; 896 case DNS_TKEY_MODE_NULL: 897 case DNS_TKEY_MODE_SERVER: 898 case DNS_TKEY_MODE_CLIENT: 899 case DNS_TKEY_MODE_LAST: 900 /* We don't have to implement these, return a mode error */ 901 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADMODE; 186 902 break; 187 903 default: 188 return DNS_ERR(NOT_IMPLEMENTED); 189 } 190 191 if (*ancount == ai) { 192 return DNS_ERR(NAME_ERROR); 193 } 194 195 *ancount = ai; 196 *answers = ans; 904 DEBUG(1, ("Unsupported TKEY mode %d\n", 905 in_tkey->rdata.tkey_record.mode)); 906 } 907 908 *answers = ret_tkey; 909 *ancount = 1; 197 910 198 911 return WERR_OK; 199 200 } 201 202 WERROR dns_server_process_query(struct dns_server *dns, 203 TALLOC_CTX *mem_ctx, 204 struct dns_name_packet *in, 205 struct dns_res_rec **answers, uint16_t *ancount, 206 struct dns_res_rec **nsrecs, uint16_t *nscount, 207 struct dns_res_rec **additional, uint16_t *arcount) 208 { 209 uint16_t i, num_answers=0; 210 struct dns_res_rec *ans=NULL; 211 WERROR werror; 212 213 ans = talloc_array(mem_ctx, struct dns_res_rec, 0); 214 W_ERROR_HAVE_NO_MEMORY(ans); 215 216 for (i = 0; i < in->qdcount; ++i) { 217 werror = handle_question(dns, mem_ctx, &in->questions[i], &ans, &num_answers); 218 W_ERROR_NOT_OK_RETURN(werror); 219 } 220 221 *answers = ans; 222 *ancount = num_answers; 223 224 /*FIXME: Do something for these */ 225 *nsrecs = NULL; 226 *nscount = 0; 227 228 *additional = NULL; 229 *arcount = 0; 230 231 return WERR_OK; 232 } 912 } 913 914 struct dns_server_process_query_state { 915 struct dns_res_rec *answers; 916 uint16_t ancount; 917 struct dns_res_rec *nsrecs; 918 uint16_t nscount; 919 struct dns_res_rec *additional; 920 uint16_t arcount; 921 }; 922 923 static void dns_server_process_query_got_auth(struct tevent_req *subreq); 924 static void dns_server_process_query_got_response(struct tevent_req *subreq); 925 926 struct tevent_req *dns_server_process_query_send( 927 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 928 struct dns_server *dns, struct dns_request_state *req_state, 929 const struct dns_name_packet *in) 930 { 931 struct tevent_req *req, *subreq; 932 struct dns_server_process_query_state *state; 933 934 req = tevent_req_create(mem_ctx, &state, 935 struct dns_server_process_query_state); 936 if (req == NULL) { 937 return NULL; 938 } 939 if (in->qdcount != 1) { 940 tevent_req_werror(req, DNS_ERR(FORMAT_ERROR)); 941 return tevent_req_post(req, ev); 942 } 943 944 /* Windows returns NOT_IMPLEMENTED on this as well */ 945 if (in->questions[0].question_class == DNS_QCLASS_NONE) { 946 tevent_req_werror(req, DNS_ERR(NOT_IMPLEMENTED)); 947 return tevent_req_post(req, ev); 948 } 949 950 if (in->questions[0].question_type == DNS_QTYPE_TKEY) { 951 WERROR err; 952 953 err = handle_tkey(dns, state, in, req_state, 954 &state->answers, &state->ancount); 955 if (tevent_req_werror(req, err)) { 956 return tevent_req_post(req, ev); 957 } 958 tevent_req_done(req); 959 return tevent_req_post(req, ev); 960 } 961 962 if (dns_authorative_for_zone(dns, in->questions[0].name)) { 963 964 req_state->flags |= DNS_FLAG_AUTHORITATIVE; 965 966 /* 967 * Initialize the response arrays, so that we can use 968 * them as their own talloc contexts when doing the 969 * realloc 970 */ 971 state->answers = talloc_array(state, struct dns_res_rec, 0); 972 if (tevent_req_nomem(state->answers, req)) { 973 return tevent_req_post(req, ev); 974 } 975 state->nsrecs = talloc_array(state, struct dns_res_rec, 0); 976 if (tevent_req_nomem(state->nsrecs, req)) { 977 return tevent_req_post(req, ev); 978 } 979 980 subreq = handle_authoritative_send( 981 state, ev, dns, lpcfg_dns_forwarder(dns->task->lp_ctx), 982 &in->questions[0], &state->answers, &state->nsrecs); 983 if (tevent_req_nomem(subreq, req)) { 984 return tevent_req_post(req, ev); 985 } 986 tevent_req_set_callback( 987 subreq, dns_server_process_query_got_auth, req); 988 return req; 989 } 990 991 if ((req_state->flags & DNS_FLAG_RECURSION_DESIRED) && 992 (req_state->flags & DNS_FLAG_RECURSION_AVAIL)) { 993 DEBUG(2, ("Not authoritative for '%s', forwarding\n", 994 in->questions[0].name)); 995 996 subreq = ask_forwarder_send( 997 state, ev, dns, lpcfg_dns_forwarder(dns->task->lp_ctx), 998 &in->questions[0]); 999 if (tevent_req_nomem(subreq, req)) { 1000 return tevent_req_post(req, ev); 1001 } 1002 tevent_req_set_callback( 1003 subreq, dns_server_process_query_got_response, req); 1004 return req; 1005 } 1006 1007 tevent_req_werror(req, DNS_ERR(NAME_ERROR)); 1008 return tevent_req_post(req, ev); 1009 } 1010 1011 static void dns_server_process_query_got_response(struct tevent_req *subreq) 1012 { 1013 struct tevent_req *req = tevent_req_callback_data( 1014 subreq, struct tevent_req); 1015 struct dns_server_process_query_state *state = tevent_req_data( 1016 req, struct dns_server_process_query_state); 1017 WERROR err; 1018 1019 err = ask_forwarder_recv(subreq, state, 1020 &state->answers, &state->ancount, 1021 &state->nsrecs, &state->nscount, 1022 &state->additional, &state->arcount); 1023 TALLOC_FREE(subreq); 1024 if (tevent_req_werror(req, err)) { 1025 return; 1026 } 1027 tevent_req_done(req); 1028 } 1029 1030 static void dns_server_process_query_got_auth(struct tevent_req *subreq) 1031 { 1032 struct tevent_req *req = tevent_req_callback_data( 1033 subreq, struct tevent_req); 1034 struct dns_server_process_query_state *state = tevent_req_data( 1035 req, struct dns_server_process_query_state); 1036 WERROR werr; 1037 1038 werr = handle_authoritative_recv(subreq); 1039 TALLOC_FREE(subreq); 1040 if (tevent_req_werror(req, werr)) { 1041 return; 1042 } 1043 state->ancount = talloc_array_length(state->answers); 1044 state->nscount = talloc_array_length(state->nsrecs); 1045 state->arcount = talloc_array_length(state->additional); 1046 1047 tevent_req_done(req); 1048 } 1049 1050 WERROR dns_server_process_query_recv( 1051 struct tevent_req *req, TALLOC_CTX *mem_ctx, 1052 struct dns_res_rec **answers, uint16_t *ancount, 1053 struct dns_res_rec **nsrecs, uint16_t *nscount, 1054 struct dns_res_rec **additional, uint16_t *arcount) 1055 { 1056 struct dns_server_process_query_state *state = tevent_req_data( 1057 req, struct dns_server_process_query_state); 1058 WERROR err = WERR_OK; 1059 1060 if (tevent_req_is_werror(req, &err)) { 1061 1062 if ((!W_ERROR_EQUAL(err, DNS_ERR(NAME_ERROR))) && 1063 (!W_ERROR_EQUAL(err, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST))) { 1064 return err; 1065 } 1066 } 1067 *answers = talloc_move(mem_ctx, &state->answers); 1068 *ancount = state->ancount; 1069 *nsrecs = talloc_move(mem_ctx, &state->nsrecs); 1070 *nscount = state->nscount; 1071 *additional = talloc_move(mem_ctx, &state->additional); 1072 *arcount = state->arcount; 1073 return err; 1074 } -
vendor/current/source4/dns_server/dns_server.c
r740 r988 43 43 #include "auth/session.h" 44 44 #include "lib/util/dlinklist.h" 45 #include "lib/util/tevent_werror.h" 46 #include "auth/auth.h" 47 #include "auth/credentials/credentials.h" 48 #include "librpc/gen_ndr/ndr_irpc.h" 49 #include "lib/messaging/irpc.h" 50 #include "libds/common/roles.h" 51 52 #undef DBGC_CLASS 53 #define DBGC_CLASS DBGC_DNS 54 55 NTSTATUS server_service_dns_init(void); 45 56 46 57 /* hold information about one dns socket */ … … 92 103 } 93 104 94 static NTSTATUS dns_process(struct dns_server *dns, 95 TALLOC_CTX *mem_ctx, 96 DATA_BLOB *in, 97 DATA_BLOB *out) 98 { 105 struct dns_process_state { 106 DATA_BLOB *in; 107 struct dns_server *dns; 108 struct dns_name_packet in_packet; 109 struct dns_request_state state; 110 uint16_t dns_err; 111 struct dns_name_packet out_packet; 112 DATA_BLOB out; 113 }; 114 115 static void dns_process_done(struct tevent_req *subreq); 116 117 static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, 118 struct tevent_context *ev, 119 struct dns_server *dns, 120 DATA_BLOB *in) 121 { 122 struct tevent_req *req, *subreq; 123 struct dns_process_state *state; 99 124 enum ndr_err_code ndr_err; 100 125 WERROR ret; 101 struct dns_name_packet *in_packet; 102 struct dns_name_packet *out_packet; 103 struct dns_res_rec *answers = NULL, *nsrecs = NULL, *additional = NULL; 104 uint16_t num_answers = 0 , num_nsrecs = 0, num_additional = 0; 126 const char *forwarder = lpcfg_dns_forwarder(dns->task->lp_ctx); 127 req = tevent_req_create(mem_ctx, &state, struct dns_process_state); 128 if (req == NULL) { 129 return NULL; 130 } 131 state->state.mem_ctx = state; 132 state->in = in; 133 134 state->dns = dns; 105 135 106 136 if (in->length < 12) { 107 return NT_STATUS_INVALID_PARAMETER; 108 } 109 110 in_packet = talloc_zero(mem_ctx, struct dns_name_packet); 111 /* TODO: We don't really need an out_packet. */ 112 out_packet = talloc_zero(mem_ctx, struct dns_name_packet); 113 114 if (in_packet == NULL) return NT_STATUS_NO_MEMORY; 115 if (out_packet == NULL) return NT_STATUS_NO_MEMORY; 116 117 dump_data(2, in->data, in->length); 118 119 ndr_err = ndr_pull_struct_blob(in, in_packet, in_packet, 120 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); 137 tevent_req_werror(req, WERR_INVALID_PARAM); 138 return tevent_req_post(req, ev); 139 } 140 dump_data_dbgc(DBGC_DNS, 8, in->data, in->length); 141 142 ndr_err = ndr_pull_struct_blob( 143 in, state, &state->in_packet, 144 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); 145 121 146 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 122 TALLOC_FREE(in_packet); 123 DEBUG(0, ("Failed to parse packet %d!\n", ndr_err)); 124 *out = *in; 125 126 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */ 127 out->data[3] |= DNS_RCODE_FORMERR; 128 129 return NT_STATUS_OK; 130 } 131 132 NDR_PRINT_DEBUG(dns_name_packet, in_packet); 133 *out_packet = *in_packet; 134 out_packet->operation |= DNS_FLAG_REPLY; 135 136 switch (in_packet->operation & DNS_OPCODE) { 147 state->dns_err = DNS_RCODE_FORMERR; 148 tevent_req_done(req); 149 return tevent_req_post(req, ev); 150 } 151 if (DEBUGLVLC(DBGC_DNS, 8)) { 152 NDR_PRINT_DEBUGC(DBGC_DNS, dns_name_packet, &state->in_packet); 153 } 154 155 ret = dns_verify_tsig(dns, state, &state->state, &state->in_packet, in); 156 if (!W_ERROR_IS_OK(ret)) { 157 DEBUG(1, ("Failed to verify TSIG!\n")); 158 state->dns_err = werr_to_dns_err(ret); 159 tevent_req_done(req); 160 return tevent_req_post(req, ev); 161 } 162 163 if (state->in_packet.operation & DNS_FLAG_REPLY) { 164 DEBUG(1, ("Won't reply to replies.\n")); 165 tevent_req_werror(req, WERR_INVALID_PARAM); 166 return tevent_req_post(req, ev); 167 } 168 169 state->state.flags = state->in_packet.operation; 170 state->state.flags |= DNS_FLAG_REPLY; 171 172 173 if (forwarder && *forwarder) { 174 state->state.flags |= DNS_FLAG_RECURSION_AVAIL; 175 } 176 177 state->out_packet = state->in_packet; 178 179 switch (state->in_packet.operation & DNS_OPCODE) { 137 180 case DNS_OPCODE_QUERY: 138 139 ret = dns_server_process_query(dns, out_packet, in_packet, 140 &answers, &num_answers, 141 &nsrecs, &num_nsrecs, 142 &additional, &num_additional); 143 144 break; 145 case DNS_OPCODE_REGISTER: 146 ret = dns_server_process_update(dns, out_packet, in_packet, 147 answers, num_answers, 148 &nsrecs, &num_nsrecs, 149 &additional, &num_additional); 181 subreq = dns_server_process_query_send( 182 state, ev, dns, &state->state, &state->in_packet); 183 if (tevent_req_nomem(subreq, req)) { 184 return tevent_req_post(req, ev); 185 } 186 tevent_req_set_callback(subreq, dns_process_done, req); 187 return req; 188 case DNS_OPCODE_UPDATE: 189 ret = dns_server_process_update( 190 dns, &state->state, state, &state->in_packet, 191 &state->out_packet.answers, &state->out_packet.ancount, 192 &state->out_packet.nsrecs, &state->out_packet.nscount, 193 &state->out_packet.additional, 194 &state->out_packet.arcount); 150 195 break; 151 196 default: 152 197 ret = WERR_DNS_ERROR_RCODE_NOT_IMPLEMENTED; 153 break; 154 } 155 156 if (W_ERROR_IS_OK(ret)) { 157 out_packet->ancount = num_answers; 158 out_packet->answers = answers; 159 160 out_packet->nscount = num_nsrecs; 161 out_packet->nsrecs = nsrecs; 162 163 out_packet->arcount = num_additional; 164 out_packet->additional = additional; 165 } else { 166 out_packet->operation |= werr_to_dns_err(ret); 167 } 168 169 NDR_PRINT_DEBUG(dns_name_packet, out_packet); 170 ndr_err = ndr_push_struct_blob(out, out_packet, out_packet, 171 (ndr_push_flags_fn_t)ndr_push_dns_name_packet); 198 } 199 if (!W_ERROR_IS_OK(ret)) { 200 state->dns_err = werr_to_dns_err(ret); 201 } 202 tevent_req_done(req); 203 return tevent_req_post(req, ev); 204 } 205 206 static void dns_process_done(struct tevent_req *subreq) 207 { 208 struct tevent_req *req = tevent_req_callback_data( 209 subreq, struct tevent_req); 210 struct dns_process_state *state = tevent_req_data( 211 req, struct dns_process_state); 212 WERROR ret; 213 214 ret = dns_server_process_query_recv( 215 subreq, state, 216 &state->out_packet.answers, &state->out_packet.ancount, 217 &state->out_packet.nsrecs, &state->out_packet.nscount, 218 &state->out_packet.additional, &state->out_packet.arcount); 219 TALLOC_FREE(subreq); 220 221 if (!W_ERROR_IS_OK(ret)) { 222 state->dns_err = werr_to_dns_err(ret); 223 } 224 tevent_req_done(req); 225 } 226 227 static WERROR dns_process_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, 228 DATA_BLOB *out) 229 { 230 struct dns_process_state *state = tevent_req_data( 231 req, struct dns_process_state); 232 enum ndr_err_code ndr_err; 233 WERROR ret; 234 235 if (tevent_req_is_werror(req, &ret)) { 236 return ret; 237 } 238 if ((state->dns_err != DNS_RCODE_OK) && 239 (state->dns_err != DNS_RCODE_NXDOMAIN)) { 240 goto drop; 241 } 242 if (state->dns_err != DNS_RCODE_OK) { 243 state->out_packet.operation |= state->dns_err; 244 } 245 state->out_packet.operation |= state->state.flags; 246 247 if (state->state.sign) { 248 ret = dns_sign_tsig(state->dns, mem_ctx, &state->state, 249 &state->out_packet, 0); 250 if (!W_ERROR_IS_OK(ret)) { 251 state->dns_err = DNS_RCODE_SERVFAIL; 252 goto drop; 253 } 254 } 255 256 if (DEBUGLVLC(DBGC_DNS, 8)) { 257 NDR_PRINT_DEBUGC(DBGC_DNS, dns_name_packet, &state->out_packet); 258 } 259 260 ndr_err = ndr_push_struct_blob( 261 out, mem_ctx, &state->out_packet, 262 (ndr_push_flags_fn_t)ndr_push_dns_name_packet); 172 263 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 173 TALLOC_FREE(in_packet); 174 TALLOC_FREE(out_packet); 175 DEBUG(0, ("Failed to push packet %d!\n", ndr_err)); 176 *out = *in; 177 178 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */ 179 out->data[3] |= DNS_RCODE_SERVFAIL; 180 181 return NT_STATUS_OK; 182 } 183 184 dump_data(2, out->data, out->length); 185 return NT_STATUS_OK; 264 DEBUG(1, ("Failed to push packet: %s!\n", 265 ndr_errstr(ndr_err))); 266 state->dns_err = DNS_RCODE_SERVFAIL; 267 goto drop; 268 } 269 return WERR_OK; 270 271 drop: 272 *out = data_blob_talloc(mem_ctx, state->in->data, state->in->length); 273 if (out->data == NULL) { 274 return WERR_NOMEM; 275 } 276 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */ 277 out->data[3] |= state->dns_err; 278 return WERR_OK; 186 279 } 187 280 … … 194 287 }; 195 288 289 static void dns_tcp_call_process_done(struct tevent_req *subreq); 196 290 static void dns_tcp_call_writev_done(struct tevent_req *subreq); 197 291 … … 200 294 struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq, 201 295 struct dns_tcp_connection); 296 struct dns_server *dns = dns_conn->dns_socket->dns; 202 297 struct dns_tcp_call *call; 203 298 NTSTATUS status; … … 229 324 } 230 325 231 DEBUG(10,("Received krb5TCP packet of length %lu from %s\n",326 DEBUG(10,("Received DNS TCP packet of length %lu from %s\n", 232 327 (long) call->in.length, 233 328 tsocket_address_string(dns_conn->conn->remote_address, call))); 234 329 235 330 /* skip length header */ 236 call->in.data +=4; 237 call->in.length -= 4; 238 239 /* Call dns */ 240 status = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out); 241 if (!NT_STATUS_IS_OK(status)) { 242 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status))); 331 call->in.data += 2; 332 call->in.length -= 2; 333 334 subreq = dns_process_send(call, dns->task->event_ctx, dns, 335 &call->in); 336 if (subreq == NULL) { 337 dns_tcp_terminate_connection( 338 dns_conn, "dns_tcp_call_loop: dns_process_send " 339 "failed\n"); 340 return; 341 } 342 tevent_req_set_callback(subreq, dns_tcp_call_process_done, call); 343 344 /* 345 * The dns tcp pdu's has the length as 2 byte (initial_read_size), 346 * packet_full_request_u16 provides the pdu length then. 347 */ 348 subreq = tstream_read_pdu_blob_send(dns_conn, 349 dns_conn->conn->event.ctx, 350 dns_conn->tstream, 351 2, /* initial_read_size */ 352 packet_full_request_u16, 353 dns_conn); 354 if (subreq == NULL) { 355 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: " 356 "no memory for tstream_read_pdu_blob_send"); 357 return; 358 } 359 tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn); 360 } 361 362 static void dns_tcp_call_process_done(struct tevent_req *subreq) 363 { 364 struct dns_tcp_call *call = tevent_req_callback_data(subreq, 365 struct dns_tcp_call); 366 struct dns_tcp_connection *dns_conn = call->dns_conn; 367 WERROR err; 368 369 err = dns_process_recv(subreq, call, &call->out); 370 TALLOC_FREE(subreq); 371 if (!W_ERROR_IS_OK(err)) { 372 DEBUG(1, ("dns_process returned %s\n", win_errstr(err))); 243 373 dns_tcp_terminate_connection(dns_conn, 244 374 "dns_tcp_call_loop: process function failed"); … … 247 377 248 378 /* First add the length of the out buffer */ 249 RS IVAL(call->out_hdr, 0, call->out.length);379 RSSVAL(call->out_hdr, 0, call->out.length); 250 380 call->out_iov[0].iov_base = (char *) call->out_hdr; 251 call->out_iov[0].iov_len = 4;381 call->out_iov[0].iov_len = 2; 252 382 253 383 call->out_iov[1].iov_base = (char *) call->out.data; … … 265 395 } 266 396 tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call); 267 268 /*269 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),270 * packet_full_request_u32 provides the pdu length then.271 */272 subreq = tstream_read_pdu_blob_send(dns_conn,273 dns_conn->conn->event.ctx,274 dns_conn->tstream,275 4, /* initial_read_size */276 packet_full_request_u32,277 dns_conn);278 if (subreq == NULL) {279 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "280 "no memory for tstream_read_pdu_blob_send");281 return;282 }283 tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);284 397 } 285 398 … … 354 467 355 468 /* 356 * The krb5 tcp pdu's has the length as 4byte (initial_read_size),357 * packet_full_request_u 32provides the pdu length then.469 * The dns tcp pdu's has the length as 2 byte (initial_read_size), 470 * packet_full_request_u16 provides the pdu length then. 358 471 */ 359 472 subreq = tstream_read_pdu_blob_send(dns_conn, 360 473 dns_conn->conn->event.ctx, 361 474 dns_conn->tstream, 362 4, /* initial_read_size */363 packet_full_request_u 32,475 2, /* initial_read_size */ 476 packet_full_request_u16, 364 477 dns_conn); 365 478 if (subreq == NULL) { … … 379 492 380 493 struct dns_udp_call { 494 struct dns_udp_socket *sock; 381 495 struct tsocket_address *src; 382 496 DATA_BLOB in; … … 384 498 }; 385 499 500 static void dns_udp_call_process_done(struct tevent_req *subreq); 386 501 static void dns_udp_call_sendto_done(struct tevent_req *subreq); 387 502 … … 390 505 struct dns_udp_socket *sock = tevent_req_callback_data(subreq, 391 506 struct dns_udp_socket); 507 struct dns_server *dns = sock->dns_socket->dns; 392 508 struct dns_udp_call *call; 393 509 uint8_t *buf; 394 510 ssize_t len; 395 511 int sys_errno; 396 NTSTATUS status;397 512 398 513 call = talloc(sock, struct dns_udp_call); … … 401 516 goto done; 402 517 } 518 call->sock = sock; 403 519 404 520 len = tdgram_recvfrom_recv(subreq, &sys_errno, … … 413 529 call->in.length = len; 414 530 415 DEBUG(10,("Received krb5UDP packet of length %lu from %s\n",531 DEBUG(10,("Received DNS UDP packet of length %lu from %s\n", 416 532 (long)call->in.length, 417 533 tsocket_address_string(call->src, call))); 418 534 419 /* Call krb5 */ 420 status = dns_process(sock->dns_socket->dns, call, &call->in, &call->out); 421 if (!NT_STATUS_IS_OK(status)) { 422 talloc_free(call); 423 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status))); 535 subreq = dns_process_send(call, dns->task->event_ctx, dns, 536 &call->in); 537 if (subreq == NULL) { 538 TALLOC_FREE(call); 424 539 goto done; 425 540 } 426 427 subreq = tdgram_sendto_queue_send(call, 428 sock->dns_socket->dns->task->event_ctx, 429 sock->dgram, 430 sock->send_queue, 431 call->out.data, 432 call->out.length, 433 call->src); 434 if (subreq == NULL) { 435 talloc_free(call); 436 goto done; 437 } 438 tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call); 541 tevent_req_set_callback(subreq, dns_udp_call_process_done, call); 439 542 440 543 done: … … 451 554 } 452 555 556 static void dns_udp_call_process_done(struct tevent_req *subreq) 557 { 558 struct dns_udp_call *call = tevent_req_callback_data( 559 subreq, struct dns_udp_call); 560 struct dns_udp_socket *sock = call->sock; 561 struct dns_server *dns = sock->dns_socket->dns; 562 WERROR err; 563 564 err = dns_process_recv(subreq, call, &call->out); 565 TALLOC_FREE(subreq); 566 if (!W_ERROR_IS_OK(err)) { 567 DEBUG(1, ("dns_process returned %s\n", win_errstr(err))); 568 TALLOC_FREE(call); 569 return; 570 } 571 572 subreq = tdgram_sendto_queue_send(call, 573 dns->task->event_ctx, 574 sock->dgram, 575 sock->send_queue, 576 call->out.data, 577 call->out.length, 578 call->src); 579 if (subreq == NULL) { 580 talloc_free(call); 581 return; 582 } 583 tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call); 584 585 } 453 586 static void dns_udp_call_sendto_done(struct tevent_req *subreq) 454 587 { 455 588 struct dns_udp_call *call = tevent_req_callback_data(subreq, 456 589 struct dns_udp_call); 457 ssize_t ret;458 590 int sys_errno; 459 591 460 ret =tdgram_sendto_queue_recv(subreq, &sys_errno);592 tdgram_sendto_queue_recv(subreq, &sys_errno); 461 593 462 594 /* We don't care about errors */ … … 489 621 &dns_socket->local_address); 490 622 if (ret != 0) { 491 status = map_nt_error_from_unix (errno);623 status = map_nt_error_from_unix_common(errno); 492 624 return status; 493 625 } … … 518 650 &dns_udp_socket->dgram); 519 651 if (ret != 0) { 520 status = map_nt_error_from_unix (errno);652 status = map_nt_error_from_unix_common(errno); 521 653 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n", 522 654 address, port, nt_errstr(status))); … … 540 672 setup our listening sockets on the configured network interfaces 541 673 */ 542 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,674 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, 543 675 struct interface *ifaces) 544 676 { … … 558 690 } 559 691 560 num_interfaces = iface_count(ifaces); 561 562 for (i=0; i<num_interfaces; i++) { 563 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i)); 564 565 status = dns_add_socket(dns, model_ops, "dns", address, DNS_SERVICE_PORT); 566 NT_STATUS_NOT_OK_RETURN(status); 692 if (ifaces != NULL) { 693 num_interfaces = iface_list_count(ifaces); 694 695 for (i=0; i<num_interfaces; i++) { 696 const char *address = talloc_strdup(tmp_ctx, 697 iface_list_n_ip(ifaces, i)); 698 699 status = dns_add_socket(dns, model_ops, "dns", address, 700 DNS_SERVICE_PORT); 701 NT_STATUS_NOT_OK_RETURN(status); 702 } 703 } else { 704 int num_binds = 0; 705 char **wcard; 706 wcard = iface_list_wildcard(tmp_ctx); 707 if (wcard == NULL) { 708 DEBUG(0, ("No wildcard address available\n")); 709 return NT_STATUS_INTERNAL_ERROR; 710 } 711 for (i = 0; wcard[i] != NULL; i++) { 712 status = dns_add_socket(dns, model_ops, "dns", wcard[i], 713 DNS_SERVICE_PORT); 714 if (NT_STATUS_IS_OK(status)) { 715 num_binds++; 716 } 717 } 718 if (num_binds == 0) { 719 talloc_free(tmp_ctx); 720 return NT_STATUS_INVALID_PARAMETER_MIX; 721 } 567 722 } 568 723 … … 572 727 } 573 728 574 static int dns_server_sort_zones(struct ldb_message **m1, struct ldb_message **m2) 575 { 576 const char *n1, *n2; 577 size_t l1, l2; 578 579 n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL); 580 n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL); 581 582 l1 = strlen(n1); 583 l2 = strlen(n2); 584 585 /* If the string lengths are not equal just sort by length */ 586 if (l1 != l2) { 587 /* If m1 is the larger zone name, return it first */ 588 return l2 - l1; 589 } 590 591 /*TODO: We need to compare DNs here, we want the DomainDNSZones first */ 592 return 0; 729 static struct dns_server_tkey_store *tkey_store_init(TALLOC_CTX *mem_ctx, 730 uint16_t size) 731 { 732 struct dns_server_tkey_store *buffer = talloc_zero(mem_ctx, 733 struct dns_server_tkey_store); 734 735 if (buffer == NULL) { 736 return NULL; 737 } 738 739 buffer->size = size; 740 buffer->next_idx = 0; 741 742 buffer->tkeys = talloc_zero_array(buffer, struct dns_server_tkey *, size); 743 if (buffer->tkeys == NULL) { 744 TALLOC_FREE(buffer); 745 } 746 747 return buffer; 748 } 749 750 static NTSTATUS dns_server_reload_zones(struct dns_server *dns) 751 { 752 NTSTATUS status; 753 struct dns_server_zone *new_list = NULL; 754 struct dns_server_zone *old_list = NULL; 755 struct dns_server_zone *old_zone; 756 status = dns_common_zones(dns->samdb, dns, &new_list); 757 if (!NT_STATUS_IS_OK(status)) { 758 return status; 759 } 760 dns->zones = new_list; 761 while ((old_zone = DLIST_TAIL(old_list)) != NULL) { 762 DLIST_REMOVE(old_list, old_zone); 763 talloc_free(old_zone); 764 } 765 766 return NT_STATUS_OK; 767 } 768 769 /** 770 * Called when the internal DNS server should reload the zones from DB, for 771 * example, when zones are added or deleted through RPC or replicated by 772 * inbound DRS. 773 */ 774 static NTSTATUS dns_reload_zones(struct irpc_message *msg, 775 struct dnssrv_reload_dns_zones *r) 776 { 777 struct dns_server *dns; 778 779 dns = talloc_get_type(msg->private_data, struct dns_server); 780 if (dns == NULL) { 781 r->out.result = NT_STATUS_INTERNAL_ERROR; 782 return NT_STATUS_INTERNAL_ERROR; 783 } 784 785 r->out.result = dns_server_reload_zones(dns); 786 787 return NT_STATUS_OK; 593 788 } 594 789 … … 597 792 struct dns_server *dns; 598 793 NTSTATUS status; 599 struct interface *ifaces ;794 struct interface *ifaces = NULL; 600 795 int ret; 601 st ruct ldb_result *res;602 struct ldb_ dn *rootdn;603 static const char * const attrs[] = { "name", NULL};604 unsigned int i;796 static const char * const attrs_none[] = { NULL}; 797 struct ldb_message *dns_acc; 798 char *hostname_lower; 799 char *dns_spn; 605 800 606 801 switch (lpcfg_server_role(task->lp_ctx)) { … … 611 806 task_server_terminate(task, "dns: no DNS required in member server configuration", false); 612 807 return; 613 case ROLE_ DOMAIN_CONTROLLER:808 case ROLE_ACTIVE_DIRECTORY_DC: 614 809 /* Yes, we want a DNS */ 615 810 break; 616 811 } 617 812 618 load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces); 619 620 if (iface_count(ifaces) == 0) { 621 task_server_terminate(task, "dns: no network interfaces configured", false); 622 return; 813 if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) { 814 load_interface_list(task, task->lp_ctx, &ifaces); 815 816 if (iface_list_count(ifaces) == 0) { 817 task_server_terminate(task, "dns: no network interfaces configured", false); 818 return; 819 } 623 820 } 624 821 … … 632 829 633 830 dns->task = task; 831 /*FIXME: Make this a configurable option */ 832 dns->max_payload = 4096; 833 834 dns->server_credentials = cli_credentials_init(dns); 835 if (!dns->server_credentials) { 836 task_server_terminate(task, "Failed to init server credentials\n", true); 837 return; 838 } 634 839 635 840 dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx, … … 640 845 } 641 846 642 rootdn = ldb_dn_new(dns, dns->samdb, ""); 643 if (rootdn == NULL) { 644 task_server_terminate(task, "dns: out of memory", true); 645 return; 646 } 647 648 // TODO: this search does not work against windows 649 ret = dsdb_search(dns->samdb, dns, &res, rootdn, LDB_SCOPE_SUBTREE, 650 attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)"); 651 if (ret != LDB_SUCCESS) { 652 task_server_terminate(task, 653 "dns: failed to look up root DNS zones", 654 true); 655 return; 656 } 657 658 TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones); 659 660 for (i=0; i < res->count; i++) { 661 struct dns_server_zone *z; 662 663 z = talloc_zero(dns, struct dns_server_zone); 664 if (z == NULL) { 665 } 666 667 z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL); 668 z->dn = talloc_move(z, &res->msgs[i]->dn); 669 670 DLIST_ADD_END(dns->zones, z, NULL); 671 } 672 673 status = dns_startup_interfaces(dns, task->lp_ctx, ifaces); 847 cli_credentials_set_conf(dns->server_credentials, task->lp_ctx); 848 849 hostname_lower = strlower_talloc(dns, lpcfg_netbios_name(task->lp_ctx)); 850 dns_spn = talloc_asprintf(dns, "DNS/%s.%s", 851 hostname_lower, 852 lpcfg_dnsdomain(task->lp_ctx)); 853 TALLOC_FREE(hostname_lower); 854 855 ret = dsdb_search_one(dns->samdb, dns, &dns_acc, 856 ldb_get_default_basedn(dns->samdb), LDB_SCOPE_SUBTREE, 857 attrs_none, 0, "(servicePrincipalName=%s)", 858 dns_spn); 859 if (ret == LDB_SUCCESS) { 860 TALLOC_FREE(dns_acc); 861 if (!dns_spn) { 862 task_server_terminate(task, "dns: talloc_asprintf failed", true); 863 return; 864 } 865 status = cli_credentials_set_stored_principal(dns->server_credentials, task->lp_ctx, dns_spn); 866 if (!NT_STATUS_IS_OK(status)) { 867 task_server_terminate(task, 868 talloc_asprintf(task, "Failed to obtain server credentials for DNS, " 869 "despite finding it in the samdb! %s\n", 870 nt_errstr(status)), 871 true); 872 return; 873 } 874 } else { 875 TALLOC_FREE(dns_spn); 876 status = cli_credentials_set_machine_account(dns->server_credentials, task->lp_ctx); 877 if (!NT_STATUS_IS_OK(status)) { 878 task_server_terminate(task, 879 talloc_asprintf(task, "Failed to obtain server credentials, perhaps a standalone server?: %s\n", 880 nt_errstr(status)), 881 true); 882 return; 883 } 884 } 885 886 dns->tkeys = tkey_store_init(dns, TKEY_BUFFER_SIZE); 887 if (!dns->tkeys) { 888 task_server_terminate(task, "Failed to allocate tkey storage\n", true); 889 return; 890 } 891 892 status = dns_server_reload_zones(dns); 893 if (!NT_STATUS_IS_OK(status)) { 894 task_server_terminate(task, "dns: failed to load DNS zones", true); 895 return; 896 } 897 898 status = dns_startup_interfaces(dns, ifaces); 674 899 if (!NT_STATUS_IS_OK(status)) { 675 900 task_server_terminate(task, "dns failed to setup interfaces", true); 676 901 return; 677 902 } 903 904 /* Setup the IRPC interface and register handlers */ 905 status = irpc_add_name(task->msg_ctx, "dnssrv"); 906 if (!NT_STATUS_IS_OK(status)) { 907 task_server_terminate(task, "dns: failed to register IRPC name", true); 908 return; 909 } 910 911 status = IRPC_REGISTER(task->msg_ctx, irpc, DNSSRV_RELOAD_DNS_ZONES, 912 dns_reload_zones, dns); 913 if (!NT_STATUS_IS_OK(status)) { 914 task_server_terminate(task, "dns: failed to setup reload handler", true); 915 return; 916 } 678 917 } 679 918 -
vendor/current/source4/dns_server/dns_server.h
r740 r988 24 24 25 25 #include "librpc/gen_ndr/dns.h" 26 #include "librpc/gen_ndr/ndr_dnsp.h" 27 #include "dnsserver_common.h" 26 28 27 29 struct tsocket_address; 30 struct dns_server_tkey { 31 const char *name; 32 enum dns_tkey_mode mode; 33 const char *algorithm; 34 struct auth_session_info *session_info; 35 struct gensec_security *gensec; 36 bool complete; 37 }; 28 38 29 struct dns_server_zone { 30 struct dns_server_zone *prev, *next; 31 const char *name; 32 struct ldb_dn *dn; 39 #define TKEY_BUFFER_SIZE 128 40 41 struct dns_server_tkey_store { 42 struct dns_server_tkey **tkeys; 43 uint16_t next_idx; 44 uint16_t size; 33 45 }; 34 46 … … 37 49 struct ldb_context *samdb; 38 50 struct dns_server_zone *zones; 51 struct dns_server_tkey_store *tkeys; 52 struct cli_credentials *server_credentials; 53 uint16_t max_payload; 39 54 }; 40 55 56 struct dns_request_state { 57 TALLOC_CTX *mem_ctx; 58 uint16_t flags; 59 bool authenticated; 60 bool sign; 61 char *key_name; 62 struct dns_res_rec *tsig; 63 uint16_t tsig_error; 64 }; 41 65 42 WERROR dns_server_process_query(struct dns_server *dns, 43 TALLOC_CTX *mem_ctx, 44 struct dns_name_packet *in, 45 struct dns_res_rec **answers, uint16_t *ancount, 46 struct dns_res_rec **nsrecs, uint16_t *nscount, 47 struct dns_res_rec **additional, uint16_t *arcount); 66 struct tevent_req *dns_server_process_query_send( 67 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 68 struct dns_server *dns, struct dns_request_state *req_state, 69 const struct dns_name_packet *in); 70 WERROR dns_server_process_query_recv( 71 struct tevent_req *req, TALLOC_CTX *mem_ctx, 72 struct dns_res_rec **answers, uint16_t *ancount, 73 struct dns_res_rec **nsrecs, uint16_t *nscount, 74 struct dns_res_rec **additional, uint16_t *arcount); 48 75 49 76 WERROR dns_server_process_update(struct dns_server *dns, 77 const struct dns_request_state *state, 50 78 TALLOC_CTX *mem_ctx, 51 struct dns_name_packet *in,52 const struct dns_res_rec *prereqs, uint16_tprereq_count,53 struct dns_res_rec **updates, 54 struct dns_res_rec **additional, 79 const struct dns_name_packet *in, 80 struct dns_res_rec **prereqs, uint16_t *prereq_count, 81 struct dns_res_rec **updates, uint16_t *update_count, 82 struct dns_res_rec **additional, uint16_t *arcount); 55 83 56 uint8_t werr_to_dns_err(WERROR werror); 57 bool dns_name_match(const char *zone, const char *name, size_t *host_part_len); 84 bool dns_name_equal(const char *name1, const char *name2); 85 bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1, 86 struct dnsp_DnssrvRpcRecord *rec2); 87 bool dns_authorative_for_zone(struct dns_server *dns, 88 const char *name); 89 const char *dns_get_authoritative_zone(struct dns_server *dns, 90 const char *name); 91 WERROR dns_lookup_records(struct dns_server *dns, 92 TALLOC_CTX *mem_ctx, 93 struct ldb_dn *dn, 94 struct dnsp_DnssrvRpcRecord **records, 95 uint16_t *rec_count); 96 WERROR dns_replace_records(struct dns_server *dns, 97 TALLOC_CTX *mem_ctx, 98 struct ldb_dn *dn, 99 bool needs_add, 100 struct dnsp_DnssrvRpcRecord *records, 101 uint16_t rec_count); 58 102 WERROR dns_name2dn(struct dns_server *dns, 59 103 TALLOC_CTX *mem_ctx, 60 104 const char *name, 61 105 struct ldb_dn **_dn); 106 WERROR dns_generate_options(struct dns_server *dns, 107 TALLOC_CTX *mem_ctx, 108 struct dns_res_rec **options); 109 struct dns_server_tkey *dns_find_tkey(struct dns_server_tkey_store *store, 110 const char *name); 111 WERROR dns_verify_tsig(struct dns_server *dns, 112 TALLOC_CTX *mem_ctx, 113 struct dns_request_state *state, 114 struct dns_name_packet *packet, 115 DATA_BLOB *in); 116 WERROR dns_sign_tsig(struct dns_server *dns, 117 TALLOC_CTX *mem_ctx, 118 struct dns_request_state *state, 119 struct dns_name_packet *packet, 120 uint16_t error); 62 121 63 #define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str 122 #include "source4/dns_server/dnsserver_common.h" 123 64 124 #endif /* __DNS_SERVER_H__ */ -
vendor/current/source4/dns_server/dns_update.c
r740 r988 26 26 #include "librpc/gen_ndr/ndr_dnsp.h" 27 27 #include <ldb.h> 28 #include "param/param.h" 29 #include "param/loadparm.h" 28 30 #include "dsdb/samdb/samdb.h" 29 31 #include "dsdb/common/util.h" 32 #include "smbd/service_task.h" 30 33 #include "dns_server/dns_server.h" 31 32 static WERROR check_prerequsites(struct dns_server *dns, 33 TALLOC_CTX *mem_ctx, 34 const struct dns_name_packet *in, 35 const struct dns_res_rec *prereqs, uint16_t count) 34 #include "auth/auth.h" 35 36 #undef DBGC_CLASS 37 #define DBGC_CLASS DBGC_DNS 38 39 static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx, 40 const struct dns_res_rec *rrec, 41 struct dnsp_DnssrvRpcRecord *r); 42 43 static WERROR check_one_prerequisite(struct dns_server *dns, 44 TALLOC_CTX *mem_ctx, 45 const struct dns_name_question *zone, 46 const struct dns_res_rec *pr, 47 bool *final_result) 36 48 { 37 const struct dns_name_question *zone; 49 bool match; 50 WERROR werror; 51 struct ldb_dn *dn; 52 uint16_t i; 53 bool found = false; 54 struct dnsp_DnssrvRpcRecord *rec = NULL; 55 struct dnsp_DnssrvRpcRecord *ans; 56 uint16_t acount; 57 38 58 size_t host_part_len = 0; 59 60 *final_result = true; 61 62 if (pr->ttl != 0) { 63 return DNS_ERR(FORMAT_ERROR); 64 } 65 66 match = dns_name_match(zone->name, pr->name, &host_part_len); 67 if (!match) { 68 return DNS_ERR(NOTZONE); 69 } 70 71 werror = dns_name2dn(dns, mem_ctx, pr->name, &dn); 72 W_ERROR_NOT_OK_RETURN(werror); 73 74 if (pr->rr_class == DNS_QCLASS_ANY) { 75 76 if (pr->length != 0) { 77 return DNS_ERR(FORMAT_ERROR); 78 } 79 80 81 if (pr->rr_type == DNS_QTYPE_ALL) { 82 /* 83 */ 84 werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); 85 if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 86 return DNS_ERR(NAME_ERROR); 87 } 88 W_ERROR_NOT_OK_RETURN(werror); 89 90 if (acount == 0) { 91 return DNS_ERR(NAME_ERROR); 92 } 93 } else { 94 /* 95 */ 96 werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); 97 if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 98 return DNS_ERR(NXRRSET); 99 } 100 if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { 101 return DNS_ERR(NXRRSET); 102 } 103 W_ERROR_NOT_OK_RETURN(werror); 104 105 for (i = 0; i < acount; i++) { 106 if (ans[i].wType == (enum dns_record_type) pr->rr_type) { 107 found = true; 108 break; 109 } 110 } 111 if (!found) { 112 return DNS_ERR(NXRRSET); 113 } 114 } 115 116 /* 117 * RFC2136 3.2.5 doesn't actually mention the need to return 118 * OK here, but otherwise we'd always return a FORMAT_ERROR 119 * later on. This also matches Microsoft DNS behavior. 120 */ 121 return WERR_OK; 122 } 123 124 if (pr->rr_class == DNS_QCLASS_NONE) { 125 if (pr->length != 0) { 126 return DNS_ERR(FORMAT_ERROR); 127 } 128 129 if (pr->rr_type == DNS_QTYPE_ALL) { 130 /* 131 */ 132 werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); 133 if (W_ERROR_EQUAL(werror, WERR_OK)) { 134 return DNS_ERR(YXDOMAIN); 135 } 136 } else { 137 /* 138 */ 139 werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); 140 if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 141 werror = WERR_OK; 142 } 143 if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { 144 werror = WERR_OK; 145 } 146 147 for (i = 0; i < acount; i++) { 148 if (ans[i].wType == (enum dns_record_type) pr->rr_type) { 149 found = true; 150 break; 151 } 152 } 153 if (found) { 154 return DNS_ERR(YXRRSET); 155 } 156 } 157 158 /* 159 * RFC2136 3.2.5 doesn't actually mention the need to return 160 * OK here, but otherwise we'd always return a FORMAT_ERROR 161 * later on. This also matches Microsoft DNS behavior. 162 */ 163 return WERR_OK; 164 } 165 166 if (pr->rr_class != zone->question_class) { 167 return DNS_ERR(FORMAT_ERROR); 168 } 169 170 *final_result = false; 171 172 werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); 173 if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 174 return DNS_ERR(NXRRSET); 175 } 176 if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { 177 return DNS_ERR(NXRRSET); 178 } 179 W_ERROR_NOT_OK_RETURN(werror); 180 181 rec = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord); 182 W_ERROR_HAVE_NO_MEMORY(rec); 183 184 werror = dns_rr_to_dnsp(rec, pr, rec); 185 W_ERROR_NOT_OK_RETURN(werror); 186 187 for (i = 0; i < acount; i++) { 188 if (dns_records_match(rec, &ans[i])) { 189 found = true; 190 break; 191 } 192 } 193 194 if (!found) { 195 return DNS_ERR(NXRRSET); 196 } 197 198 return WERR_OK; 199 } 200 201 static WERROR check_prerequisites(struct dns_server *dns, 202 TALLOC_CTX *mem_ctx, 203 const struct dns_name_question *zone, 204 const struct dns_res_rec *prereqs, uint16_t count) 205 { 39 206 uint16_t i; 40 41 zone = in->questions; 207 WERROR final_error = WERR_OK; 42 208 43 209 for (i = 0; i < count; i++) { 44 const struct dns_res_rec *r = &prereqs[i]; 45 bool match; 46 47 if (r->ttl != 0) { 48 return DNS_ERR(FORMAT_ERROR); 49 } 50 match = dns_name_match(zone->name, r->name, &host_part_len); 51 if (!match) { 52 /* TODO: check if we need to echo all prereqs if the 53 * first fails */ 54 return DNS_ERR(NOTZONE); 55 } 56 if (r->rr_class == DNS_QCLASS_ANY) { 57 if (r->length != 0) { 58 return DNS_ERR(FORMAT_ERROR); 59 } 60 if (r->rr_type == DNS_QTYPE_ALL) { 61 /* TODO: Check if zone has at least one RR */ 62 return DNS_ERR(NAME_ERROR); 63 } else { 64 /* TODO: Check if RR exists of the specified type */ 65 return DNS_ERR(NXRRSET); 66 } 67 } 68 if (r->rr_class == DNS_QCLASS_NONE) { 69 if (r->length != 0) { 70 return DNS_ERR(FORMAT_ERROR); 71 } 72 if (r->rr_type == DNS_QTYPE_ALL) { 73 /* TODO: Return this error if the given name exits in this zone */ 74 return DNS_ERR(YXDOMAIN); 75 } else { 76 /* TODO: Return error if there's an RRset of this type in the zone */ 77 return DNS_ERR(YXRRSET); 78 } 79 } 80 if (r->rr_class == zone->question_class) { 81 /* Check if there's a RR with this */ 82 return DNS_ERR(NOT_IMPLEMENTED); 83 } else { 84 return DNS_ERR(FORMAT_ERROR); 85 } 86 } 87 210 bool final; 211 WERROR werror; 212 213 werror = check_one_prerequisite(dns, mem_ctx, zone, 214 &prereqs[i], &final); 215 if (!W_ERROR_IS_OK(werror)) { 216 if (final) { 217 return werror; 218 } 219 if (W_ERROR_IS_OK(final_error)) { 220 final_error = werror; 221 } 222 } 223 } 224 225 if (!W_ERROR_IS_OK(final_error)) { 226 return final_error; 227 } 88 228 89 229 return WERR_OK; … … 105 245 } 106 246 if (zone->question_class == r->rr_class) { 107 /*TODO: also check for AXFR,MAILA,MAILB */108 247 if (r->rr_type == DNS_QTYPE_ALL) { 109 248 return DNS_ERR(FORMAT_ERROR); 110 249 } 250 if (r->rr_type == DNS_QTYPE_AXFR) { 251 return DNS_ERR(FORMAT_ERROR); 252 } 253 if (r->rr_type == DNS_QTYPE_MAILB) { 254 return DNS_ERR(FORMAT_ERROR); 255 } 256 if (r->rr_type == DNS_QTYPE_MAILA) { 257 return DNS_ERR(FORMAT_ERROR); 258 } 111 259 } else if (r->rr_class == DNS_QCLASS_ANY) { 112 if (r->ttl != 0 || r->length != 0) { 260 if (r->ttl != 0) { 261 return DNS_ERR(FORMAT_ERROR); 262 } 263 if (r->length != 0) { 264 return DNS_ERR(FORMAT_ERROR); 265 } 266 if (r->rr_type == DNS_QTYPE_AXFR) { 267 return DNS_ERR(FORMAT_ERROR); 268 } 269 if (r->rr_type == DNS_QTYPE_MAILB) { 270 return DNS_ERR(FORMAT_ERROR); 271 } 272 if (r->rr_type == DNS_QTYPE_MAILA) { 113 273 return DNS_ERR(FORMAT_ERROR); 114 274 } 115 275 } else if (r->rr_class == DNS_QCLASS_NONE) { 116 if (r->ttl != 0 || r->rr_type == DNS_QTYPE_ALL) { 276 if (r->ttl != 0) { 277 return DNS_ERR(FORMAT_ERROR); 278 } 279 if (r->rr_type == DNS_QTYPE_ALL) { 280 return DNS_ERR(FORMAT_ERROR); 281 } 282 if (r->rr_type == DNS_QTYPE_AXFR) { 283 return DNS_ERR(FORMAT_ERROR); 284 } 285 if (r->rr_type == DNS_QTYPE_MAILB) { 286 return DNS_ERR(FORMAT_ERROR); 287 } 288 if (r->rr_type == DNS_QTYPE_MAILA) { 117 289 return DNS_ERR(FORMAT_ERROR); 118 290 } … … 124 296 } 125 297 298 static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx, 299 const struct dns_res_rec *rrec, 300 struct dnsp_DnssrvRpcRecord *r) 301 { 302 enum ndr_err_code ndr_err; 303 304 if (rrec->rr_type == DNS_QTYPE_ALL) { 305 return DNS_ERR(FORMAT_ERROR); 306 } 307 308 ZERO_STRUCTP(r); 309 310 r->wType = (enum dns_record_type) rrec->rr_type; 311 r->dwTtlSeconds = rrec->ttl; 312 r->rank = DNS_RANK_ZONE; 313 314 /* If we get QCLASS_ANY, we're done here */ 315 if (rrec->rr_class == DNS_QCLASS_ANY) { 316 goto done; 317 } 318 319 switch(rrec->rr_type) { 320 case DNS_QTYPE_A: 321 r->data.ipv4 = talloc_strdup(mem_ctx, rrec->rdata.ipv4_record); 322 W_ERROR_HAVE_NO_MEMORY(r->data.ipv4); 323 break; 324 case DNS_QTYPE_AAAA: 325 r->data.ipv6 = talloc_strdup(mem_ctx, rrec->rdata.ipv6_record); 326 W_ERROR_HAVE_NO_MEMORY(r->data.ipv6); 327 break; 328 case DNS_QTYPE_NS: 329 r->data.ns = talloc_strdup(mem_ctx, rrec->rdata.ns_record); 330 W_ERROR_HAVE_NO_MEMORY(r->data.ns); 331 break; 332 case DNS_QTYPE_CNAME: 333 r->data.cname = talloc_strdup(mem_ctx, rrec->rdata.cname_record); 334 W_ERROR_HAVE_NO_MEMORY(r->data.cname); 335 break; 336 case DNS_QTYPE_SRV: 337 r->data.srv.wPriority = rrec->rdata.srv_record.priority; 338 r->data.srv.wWeight = rrec->rdata.srv_record.weight; 339 r->data.srv.wPort = rrec->rdata.srv_record.port; 340 r->data.srv.nameTarget = talloc_strdup(mem_ctx, 341 rrec->rdata.srv_record.target); 342 W_ERROR_HAVE_NO_MEMORY(r->data.srv.nameTarget); 343 break; 344 case DNS_QTYPE_PTR: 345 r->data.ptr = talloc_strdup(mem_ctx, rrec->rdata.ptr_record); 346 W_ERROR_HAVE_NO_MEMORY(r->data.ptr); 347 break; 348 case DNS_QTYPE_MX: 349 r->data.mx.wPriority = rrec->rdata.mx_record.preference; 350 r->data.mx.nameTarget = talloc_strdup(mem_ctx, 351 rrec->rdata.mx_record.exchange); 352 W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget); 353 break; 354 case DNS_QTYPE_TXT: 355 ndr_err = ndr_dnsp_string_list_copy(mem_ctx, 356 &rrec->rdata.txt_record.txt, 357 &r->data.txt); 358 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 359 return WERR_NOMEM; 360 } 361 362 break; 363 default: 364 DEBUG(0, ("Got a qytpe of %d\n", rrec->rr_type)); 365 return DNS_ERR(NOT_IMPLEMENTED); 366 } 367 368 done: 369 370 return WERR_OK; 371 } 372 373 374 static WERROR handle_one_update(struct dns_server *dns, 375 TALLOC_CTX *mem_ctx, 376 const struct dns_name_question *zone, 377 const struct dns_res_rec *update, 378 const struct dns_server_tkey *tkey) 379 { 380 struct dnsp_DnssrvRpcRecord *recs = NULL; 381 uint16_t rcount = 0; 382 struct ldb_dn *dn; 383 uint16_t i; 384 uint16_t first = 0; 385 WERROR werror; 386 bool tombstoned = false; 387 bool needs_add = false; 388 389 DEBUG(2, ("Looking at record: \n")); 390 if (DEBUGLVL(2)) { 391 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update)); 392 } 393 394 switch (update->rr_type) { 395 case DNS_QTYPE_A: 396 case DNS_QTYPE_NS: 397 case DNS_QTYPE_CNAME: 398 case DNS_QTYPE_SOA: 399 case DNS_QTYPE_PTR: 400 case DNS_QTYPE_MX: 401 case DNS_QTYPE_AAAA: 402 case DNS_QTYPE_SRV: 403 case DNS_QTYPE_TXT: 404 break; 405 default: 406 DEBUG(0, ("Can't handle updates of type %u yet\n", 407 update->rr_type)); 408 return DNS_ERR(NOT_IMPLEMENTED); 409 } 410 411 werror = dns_name2dn(dns, mem_ctx, update->name, &dn); 412 W_ERROR_NOT_OK_RETURN(werror); 413 414 werror = dns_common_lookup(dns->samdb, mem_ctx, dn, 415 &recs, &rcount, &tombstoned); 416 if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { 417 needs_add = true; 418 werror = WERR_OK; 419 } 420 W_ERROR_NOT_OK_RETURN(werror); 421 422 if (tombstoned) { 423 /* 424 * we need to keep the existing tombstone record 425 * and ignore it 426 */ 427 first = rcount; 428 } 429 430 if (update->rr_class == zone->question_class) { 431 if (update->rr_type == DNS_QTYPE_CNAME) { 432 /* 433 * If there is a record in the directory 434 * that's not a CNAME, ignore update 435 */ 436 for (i = first; i < rcount; i++) { 437 if (recs[i].wType != DNS_TYPE_CNAME) { 438 DEBUG(5, ("Skipping update\n")); 439 return WERR_OK; 440 } 441 break; 442 } 443 444 /* 445 * There should be no entries besides one CNAME record 446 * per name, so replace everything with the new CNAME 447 */ 448 449 rcount = first; 450 recs = talloc_realloc(mem_ctx, recs, 451 struct dnsp_DnssrvRpcRecord, rcount + 1); 452 W_ERROR_HAVE_NO_MEMORY(recs); 453 454 werror = dns_rr_to_dnsp(recs, update, &recs[rcount]); 455 W_ERROR_NOT_OK_RETURN(werror); 456 rcount += 1; 457 458 werror = dns_replace_records(dns, mem_ctx, dn, 459 needs_add, recs, rcount); 460 W_ERROR_NOT_OK_RETURN(werror); 461 462 return WERR_OK; 463 } else { 464 /* 465 * If there is a CNAME record for this name, 466 * ignore update 467 */ 468 for (i = first; i < rcount; i++) { 469 if (recs[i].wType == DNS_TYPE_CNAME) { 470 DEBUG(5, ("Skipping update\n")); 471 return WERR_OK; 472 } 473 } 474 } 475 if (update->rr_type == DNS_QTYPE_SOA) { 476 bool found = false; 477 478 /* 479 * If the zone has no SOA record?? or update's 480 * serial number is smaller than existing SOA's, 481 * ignore update 482 */ 483 for (i = first; i < rcount; i++) { 484 if (recs[i].wType == DNS_TYPE_SOA) { 485 uint16_t n, o; 486 487 n = update->rdata.soa_record.serial; 488 o = recs[i].data.soa.serial; 489 /* 490 * TODO: Implement RFC 1982 comparison 491 * logic for RFC2136 492 */ 493 if (n <= o) { 494 DEBUG(5, ("Skipping update\n")); 495 return WERR_OK; 496 } 497 found = true; 498 break; 499 } 500 } 501 if (!found) { 502 DEBUG(5, ("Skipping update\n")); 503 return WERR_OK; 504 } 505 506 werror = dns_rr_to_dnsp(mem_ctx, update, &recs[i]); 507 W_ERROR_NOT_OK_RETURN(werror); 508 509 for (i++; i < rcount; i++) { 510 if (recs[i].wType != DNS_TYPE_SOA) { 511 continue; 512 } 513 514 recs[i] = (struct dnsp_DnssrvRpcRecord) { 515 .wType = DNS_TYPE_TOMBSTONE, 516 }; 517 } 518 519 werror = dns_replace_records(dns, mem_ctx, dn, 520 needs_add, recs, rcount); 521 W_ERROR_NOT_OK_RETURN(werror); 522 523 return WERR_OK; 524 } 525 526 recs = talloc_realloc(mem_ctx, recs, 527 struct dnsp_DnssrvRpcRecord, rcount+1); 528 W_ERROR_HAVE_NO_MEMORY(recs); 529 530 werror = dns_rr_to_dnsp(recs, update, &recs[rcount]); 531 W_ERROR_NOT_OK_RETURN(werror); 532 533 for (i = first; i < rcount; i++) { 534 if (!dns_records_match(&recs[i], &recs[rcount])) { 535 continue; 536 } 537 538 recs[i] = recs[rcount]; 539 540 werror = dns_replace_records(dns, mem_ctx, dn, 541 needs_add, recs, rcount); 542 W_ERROR_NOT_OK_RETURN(werror); 543 544 return WERR_OK; 545 } 546 547 werror = dns_replace_records(dns, mem_ctx, dn, 548 needs_add, recs, rcount+1); 549 W_ERROR_NOT_OK_RETURN(werror); 550 551 return WERR_OK; 552 } else if (update->rr_class == DNS_QCLASS_ANY) { 553 if (update->rr_type == DNS_QTYPE_ALL) { 554 if (dns_name_equal(update->name, zone->name)) { 555 for (i = first; i < rcount; i++) { 556 557 if (recs[i].wType == DNS_TYPE_SOA) { 558 continue; 559 } 560 561 if (recs[i].wType == DNS_TYPE_NS) { 562 continue; 563 } 564 565 recs[i] = (struct dnsp_DnssrvRpcRecord) { 566 .wType = DNS_TYPE_TOMBSTONE, 567 }; 568 } 569 570 } else { 571 for (i = first; i < rcount; i++) { 572 recs[i] = (struct dnsp_DnssrvRpcRecord) { 573 .wType = DNS_TYPE_TOMBSTONE, 574 }; 575 } 576 } 577 578 } else if (dns_name_equal(update->name, zone->name)) { 579 580 if (update->rr_type == DNS_QTYPE_SOA) { 581 return WERR_OK; 582 } 583 584 if (update->rr_type == DNS_QTYPE_NS) { 585 return WERR_OK; 586 } 587 } 588 for (i = first; i < rcount; i++) { 589 if (recs[i].wType == (enum dns_record_type) update->rr_type) { 590 recs[i] = (struct dnsp_DnssrvRpcRecord) { 591 .wType = DNS_TYPE_TOMBSTONE, 592 }; 593 } 594 } 595 596 werror = dns_replace_records(dns, mem_ctx, dn, 597 needs_add, recs, rcount); 598 W_ERROR_NOT_OK_RETURN(werror); 599 600 return WERR_OK; 601 } else if (update->rr_class == DNS_QCLASS_NONE) { 602 struct dnsp_DnssrvRpcRecord *del_rec; 603 604 if (update->rr_type == DNS_QTYPE_SOA) { 605 return WERR_OK; 606 } 607 if (update->rr_type == DNS_QTYPE_NS) { 608 bool found = false; 609 struct dnsp_DnssrvRpcRecord *ns_rec = talloc(mem_ctx, 610 struct dnsp_DnssrvRpcRecord); 611 W_ERROR_HAVE_NO_MEMORY(ns_rec); 612 613 614 werror = dns_rr_to_dnsp(ns_rec, update, ns_rec); 615 W_ERROR_NOT_OK_RETURN(werror); 616 617 for (i = first; i < rcount; i++) { 618 if (dns_records_match(ns_rec, &recs[i])) { 619 found = true; 620 break; 621 } 622 } 623 if (found) { 624 return WERR_OK; 625 } 626 } 627 628 del_rec = talloc(mem_ctx, struct dnsp_DnssrvRpcRecord); 629 W_ERROR_HAVE_NO_MEMORY(del_rec); 630 631 werror = dns_rr_to_dnsp(del_rec, update, del_rec); 632 W_ERROR_NOT_OK_RETURN(werror); 633 634 for (i = first; i < rcount; i++) { 635 if (dns_records_match(del_rec, &recs[i])) { 636 recs[i] = (struct dnsp_DnssrvRpcRecord) { 637 .wType = DNS_TYPE_TOMBSTONE, 638 }; 639 } 640 } 641 642 werror = dns_replace_records(dns, mem_ctx, dn, 643 needs_add, recs, rcount); 644 W_ERROR_NOT_OK_RETURN(werror); 645 } 646 647 return WERR_OK; 648 } 649 650 static WERROR handle_updates(struct dns_server *dns, 651 TALLOC_CTX *mem_ctx, 652 const struct dns_name_question *zone, 653 const struct dns_res_rec *prereqs, uint16_t pcount, 654 struct dns_res_rec *updates, uint16_t upd_count, 655 struct dns_server_tkey *tkey) 656 { 657 struct ldb_dn *zone_dn = NULL; 658 WERROR werror = WERR_OK; 659 int ret; 660 uint16_t ri; 661 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 662 663 if (tkey != NULL) { 664 ret = ldb_set_opaque(dns->samdb, "sessionInfo", tkey->session_info); 665 if (ret != LDB_SUCCESS) { 666 DEBUG(1, ("unable to set session info\n")); 667 werror = DNS_ERR(SERVER_FAILURE); 668 goto failed; 669 } 670 } 671 672 werror = dns_name2dn(dns, tmp_ctx, zone->name, &zone_dn); 673 W_ERROR_NOT_OK_GOTO(werror, failed); 674 675 ret = ldb_transaction_start(dns->samdb); 676 if (ret != LDB_SUCCESS) { 677 werror = DNS_ERR(SERVER_FAILURE); 678 goto failed; 679 } 680 681 werror = check_prerequisites(dns, tmp_ctx, zone, prereqs, pcount); 682 W_ERROR_NOT_OK_GOTO(werror, failed); 683 684 DEBUG(1, ("update count is %u\n", upd_count)); 685 686 for (ri = 0; ri < upd_count; ri++) { 687 werror = handle_one_update(dns, tmp_ctx, zone, 688 &updates[ri], tkey); 689 W_ERROR_NOT_OK_GOTO(werror, failed); 690 } 691 692 ldb_transaction_commit(dns->samdb); 693 TALLOC_FREE(tmp_ctx); 694 695 if (tkey != NULL) { 696 ldb_set_opaque(dns->samdb, "sessionInfo", 697 system_session(dns->task->lp_ctx)); 698 } 699 700 return WERR_OK; 701 702 failed: 703 ldb_transaction_cancel(dns->samdb); 704 705 if (tkey != NULL) { 706 ldb_set_opaque(dns->samdb, "sessionInfo", 707 system_session(dns->task->lp_ctx)); 708 } 709 710 TALLOC_FREE(tmp_ctx); 711 return werror; 712 713 } 714 715 static WERROR dns_update_allowed(struct dns_server *dns, 716 const struct dns_request_state *state, 717 struct dns_server_tkey **tkey) 718 { 719 if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_ON) { 720 DEBUG(2, ("All updates allowed.\n")); 721 return WERR_OK; 722 } 723 724 if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_OFF) { 725 DEBUG(2, ("Updates disabled.\n")); 726 return DNS_ERR(REFUSED); 727 } 728 729 if (state->authenticated == false ) { 730 DEBUG(2, ("Update not allowed for unsigned packet.\n")); 731 return DNS_ERR(REFUSED); 732 } 733 734 *tkey = dns_find_tkey(dns->tkeys, state->key_name); 735 if (*tkey == NULL) { 736 DEBUG(0, ("Authenticated, but key not found. Something is wrong.\n")); 737 return DNS_ERR(REFUSED); 738 } 739 740 return WERR_OK; 741 } 742 743 126 744 WERROR dns_server_process_update(struct dns_server *dns, 745 const struct dns_request_state *state, 127 746 TALLOC_CTX *mem_ctx, 128 struct dns_name_packet *in,129 const struct dns_res_rec *prereqs, uint16_tprereq_count,130 struct dns_res_rec **updates, 131 struct dns_res_rec **additional, 747 const struct dns_name_packet *in, 748 struct dns_res_rec **prereqs, uint16_t *prereq_count, 749 struct dns_res_rec **updates, uint16_t *update_count, 750 struct dns_res_rec **additional, uint16_t *arcount) 132 751 { 133 752 struct dns_name_question *zone; … … 135 754 size_t host_part_len = 0; 136 755 WERROR werror = DNS_ERR(NOT_IMPLEMENTED); 137 bool update_allowed = false;756 struct dns_server_tkey *tkey = NULL; 138 757 139 758 if (in->qdcount != 1) { … … 141 760 } 142 761 143 zone = in->questions; 762 zone = &in->questions[0]; 763 764 if (zone->question_class != DNS_QCLASS_IN && 765 zone->question_class != DNS_QCLASS_ANY) { 766 return DNS_ERR(NOT_IMPLEMENTED); 767 } 144 768 145 769 if (zone->question_type != DNS_QTYPE_SOA) { … … 147 771 } 148 772 149 DEBUG( 0, ("Got a dns update request.\n"));773 DEBUG(2, ("Got a dns update request.\n")); 150 774 151 775 for (z = dns->zones; z != NULL; z = z->next) { … … 159 783 160 784 if (z == NULL) { 785 DEBUG(1, ("We're not authoritative for this zone\n")); 161 786 return DNS_ERR(NOTAUTH); 162 787 } … … 164 789 if (host_part_len != 0) { 165 790 /* TODO: We need to delegate this one */ 791 DEBUG(1, ("Would have to delegate zone '%s'.\n", zone->name)); 166 792 return DNS_ERR(NOT_IMPLEMENTED); 167 793 } 168 794 169 werror = check_prerequsites(dns, mem_ctx, in, prereqs, prereq_count); 795 *prereq_count = in->ancount; 796 *prereqs = in->answers; 797 werror = check_prerequisites(dns, mem_ctx, in->questions, *prereqs, 798 *prereq_count); 170 799 W_ERROR_NOT_OK_RETURN(werror); 171 800 172 /* TODO: Check if update is allowed, we probably want "always",173 * key-based GSSAPI, key-based bind-style TSIG and "never" as174 * smb.conf options. */175 if (!update_allowed) {176 return DNS_ERR(REFUSED); 177 }178 801 werror = dns_update_allowed(dns, state, &tkey); 802 if (!W_ERROR_IS_OK(werror)) { 803 return werror; 804 } 805 806 *update_count = in->nscount; 807 *updates = in->nsrecs; 179 808 werror = update_prescan(in->questions, *updates, *update_count); 180 809 W_ERROR_NOT_OK_RETURN(werror); 181 810 811 werror = handle_updates(dns, mem_ctx, in->questions, *prereqs, 812 *prereq_count, *updates, *update_count, tkey); 813 W_ERROR_NOT_OK_RETURN(werror); 814 182 815 return werror; 183 816 } -
vendor/current/source4/dns_server/dns_utils.c
r740 r988 31 31 #include "dns_server/dns_server.h" 32 32 33 uint8_t werr_to_dns_err(WERROR werr) 34 { 35 if (W_ERROR_EQUAL(WERR_OK, werr)) { 36 return DNS_RCODE_OK; 37 } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) { 38 return DNS_RCODE_FORMERR; 39 } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) { 40 return DNS_RCODE_SERVFAIL; 41 } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { 42 return DNS_RCODE_NXDOMAIN; 43 } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { 44 return DNS_RCODE_NOTIMP; 45 } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { 46 return DNS_RCODE_REFUSED; 47 } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) { 48 return DNS_RCODE_YXDOMAIN; 49 } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) { 50 return DNS_RCODE_YXRRSET; 51 } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) { 52 return DNS_RCODE_NXRRSET; 53 } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) { 54 return DNS_RCODE_NOTAUTH; 55 } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { 56 return DNS_RCODE_NOTZONE; 57 } 58 DEBUG(5, ("No mapping exists for %%s\n")); 59 return DNS_RCODE_SERVFAIL; 60 } 61 62 bool dns_name_match(const char *zone, const char *name, size_t *host_part_len) 63 { 64 size_t zl = strlen(zone); 65 size_t nl = strlen(name); 66 ssize_t zi, ni; 67 static const size_t fixup = 'a' - 'A'; 68 69 if (zl > nl) { 33 #undef DBGC_CLASS 34 #define DBGC_CLASS DBGC_DNS 35 36 /* Names are equal if they match and there's nothing left over */ 37 bool dns_name_equal(const char *name1, const char *name2) 38 { 39 size_t host_part_len; 40 bool ret = dns_name_match(name1, name2, &host_part_len); 41 42 return ret && (host_part_len == 0); 43 } 44 45 /* 46 see if two dns records match 47 */ 48 bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1, 49 struct dnsp_DnssrvRpcRecord *rec2) 50 { 51 bool status; 52 int i; 53 54 if (rec1->wType != rec2->wType) { 70 55 return false; 71 56 } 72 57 73 for (zi = zl, ni = nl; zi >= 0; zi--, ni--) { 74 char zc = zone[zi]; 75 char nc = name[ni]; 76 77 /* convert to lower case */ 78 if (zc >= 'A' && zc <= 'Z') { 79 zc += fixup; 80 } 81 if (nc >= 'A' && nc <= 'Z') { 82 nc += fixup; 83 } 84 85 if (zc != nc) { 58 /* see if the data matches */ 59 switch (rec1->wType) { 60 case DNS_TYPE_A: 61 return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0; 62 case DNS_TYPE_AAAA: 63 return strcmp(rec1->data.ipv6, rec2->data.ipv6) == 0; 64 case DNS_TYPE_CNAME: 65 return dns_name_equal(rec1->data.cname, rec2->data.cname); 66 case DNS_TYPE_TXT: 67 if (rec1->data.txt.count != rec2->data.txt.count) { 86 68 return false; 87 69 } 88 } 89 90 if (ni >= 0) { 91 if (name[ni] != '.') { 92 return false; 93 } 94 95 ni--; 96 } 97 98 *host_part_len = ni+1; 70 status = true; 71 for (i=0; i<rec1->data.txt.count; i++) { 72 status = status && (strcmp(rec1->data.txt.str[i], 73 rec2->data.txt.str[i]) == 0); 74 } 75 return status; 76 case DNS_TYPE_PTR: 77 return strcmp(rec1->data.ptr, rec2->data.ptr) == 0; 78 case DNS_TYPE_NS: 79 return dns_name_equal(rec1->data.ns, rec2->data.ns); 80 81 case DNS_TYPE_SRV: 82 return rec1->data.srv.wPriority == rec2->data.srv.wPriority && 83 rec1->data.srv.wWeight == rec2->data.srv.wWeight && 84 rec1->data.srv.wPort == rec2->data.srv.wPort && 85 dns_name_equal(rec1->data.srv.nameTarget, rec2->data.srv.nameTarget); 86 87 case DNS_TYPE_MX: 88 return rec1->data.mx.wPriority == rec2->data.mx.wPriority && 89 dns_name_equal(rec1->data.mx.nameTarget, rec2->data.mx.nameTarget); 90 91 case DNS_TYPE_HINFO: 92 return strcmp(rec1->data.hinfo.cpu, rec2->data.hinfo.cpu) == 0 && 93 strcmp(rec1->data.hinfo.os, rec2->data.hinfo.os) == 0; 94 95 case DNS_TYPE_SOA: 96 return dns_name_equal(rec1->data.soa.mname, rec2->data.soa.mname) && 97 dns_name_equal(rec1->data.soa.rname, rec2->data.soa.rname) && 98 rec1->data.soa.serial == rec2->data.soa.serial && 99 rec1->data.soa.refresh == rec2->data.soa.refresh && 100 rec1->data.soa.retry == rec2->data.soa.retry && 101 rec1->data.soa.expire == rec2->data.soa.expire && 102 rec1->data.soa.minimum == rec2->data.soa.minimum; 103 default: 104 break; 105 } 106 107 return false; 108 } 109 110 WERROR dns_lookup_records(struct dns_server *dns, 111 TALLOC_CTX *mem_ctx, 112 struct ldb_dn *dn, 113 struct dnsp_DnssrvRpcRecord **records, 114 uint16_t *rec_count) 115 { 116 return dns_common_lookup(dns->samdb, mem_ctx, dn, 117 records, rec_count, NULL); 118 } 119 120 WERROR dns_replace_records(struct dns_server *dns, 121 TALLOC_CTX *mem_ctx, 122 struct ldb_dn *dn, 123 bool needs_add, 124 struct dnsp_DnssrvRpcRecord *records, 125 uint16_t rec_count) 126 { 127 /* TODO: Autogenerate this somehow */ 128 uint32_t dwSerial = 110; 129 return dns_common_replace(dns->samdb, mem_ctx, dn, 130 needs_add, dwSerial, records, rec_count); 131 } 132 133 bool dns_authorative_for_zone(struct dns_server *dns, 134 const char *name) 135 { 136 const struct dns_server_zone *z; 137 size_t host_part_len = 0; 138 139 if (name == NULL) { 140 return false; 141 } 142 143 if (strcmp(name, "") == 0) { 144 return true; 145 } 146 for (z = dns->zones; z != NULL; z = z->next) { 147 bool match; 148 149 match = dns_name_match(z->name, name, &host_part_len); 150 if (match) { 151 break; 152 } 153 } 154 if (z == NULL) { 155 return false; 156 } 99 157 100 158 return true; 159 } 160 161 const char *dns_get_authoritative_zone(struct dns_server *dns, 162 const char *name) 163 { 164 const struct dns_server_zone *z; 165 size_t host_part_len = 0; 166 167 for (z = dns->zones; z != NULL; z = z->next) { 168 bool match; 169 match = dns_name_match(z->name, name, &host_part_len); 170 if (match) { 171 return z->name; 172 } 173 } 174 return NULL; 101 175 } 102 176 … … 104 178 TALLOC_CTX *mem_ctx, 105 179 const char *name, 106 struct ldb_dn **_dn) 107 { 108 struct ldb_dn *base; 109 struct ldb_dn *dn; 110 const struct dns_server_zone *z; 111 size_t host_part_len = 0; 112 113 if (name == NULL) { 114 return DNS_ERR(FORMAT_ERROR); 115 } 116 117 /*TODO: Check if 'name' is a valid DNS name */ 118 119 if (strcmp(name, "") == 0) { 120 base = ldb_get_default_basedn(dns->samdb); 121 dn = ldb_dn_copy(mem_ctx, base); 122 ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System"); 123 *_dn = dn; 124 return WERR_OK; 125 } 126 127 for (z = dns->zones; z != NULL; z = z->next) { 128 bool match; 129 130 match = dns_name_match(z->name, name, &host_part_len); 131 if (match) { 132 break; 133 } 134 } 135 136 if (z == NULL) { 137 return DNS_ERR(NAME_ERROR); 138 } 139 140 if (host_part_len == 0) { 141 dn = ldb_dn_copy(mem_ctx, z->dn); 142 ldb_dn_add_child_fmt(dn, "DC=@"); 143 *_dn = dn; 144 return WERR_OK; 145 } 146 147 dn = ldb_dn_copy(mem_ctx, z->dn); 148 ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name); 149 *_dn = dn; 180 struct ldb_dn **dn) 181 { 182 return dns_common_name2dn(dns->samdb, dns->zones, 183 mem_ctx, name, dn); 184 } 185 186 WERROR dns_generate_options(struct dns_server *dns, 187 TALLOC_CTX *mem_ctx, 188 struct dns_res_rec **options) 189 { 190 struct dns_res_rec *o; 191 192 o = talloc_zero(mem_ctx, struct dns_res_rec); 193 if (o == NULL) { 194 return WERR_NOMEM; 195 } 196 o->name = NULL; 197 o->rr_type = DNS_QTYPE_OPT; 198 /* This is ugly, but RFC2671 wants the payload size in this field */ 199 o->rr_class = (enum dns_qclass) dns->max_payload; 200 o->ttl = 0; 201 o->length = 0; 202 203 *options = o; 150 204 return WERR_OK; 151 205 } -
vendor/current/source4/dns_server/wscript_build
r740 r988 1 1 #!/usr/bin/env python 2 2 3 bld.SAMBA_LIBRARY('dnsserver_common', 4 source='dnsserver_common.c', 5 deps='samba-util samba-errors ldbsamba clidns', 6 private_library=True, 7 enabled=bld.AD_DC_BUILD_IS_ENABLED()) 8 3 9 bld.SAMBA_MODULE('service_dns', 4 source='dns_server.c dns_query.c dns_update.c dns_utils.c ',10 source='dns_server.c dns_query.c dns_update.c dns_utils.c dns_crypto.c', 5 11 subsystem='service', 6 12 init_function='server_service_dns_init', 7 deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba ',13 deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba clidns gensec auth samba_server_gensec dnsserver_common', 8 14 local_include=False, 9 15 internal_module=False, 16 enabled=bld.AD_DC_BUILD_IS_ENABLED() 10 17 ) 11 18 … … 13 20 bld.SAMBA_LIBRARY('dlz_bind9', 14 21 source='dlz_bind9.c', 22 cflags='-DBIND_VERSION_9_8', 15 23 private_library=True, 16 24 link_name='modules/bind9/dlz_bind9.so', 17 deps='samba-hostconfig ldbsamba samba-util popt') 25 realname='dlz_bind9.so', 26 install_path='${MODULESDIR}/bind9', 27 deps='samba-hostconfig samdb-common gensec popt dnsserver_common', 28 enabled=bld.AD_DC_BUILD_IS_ENABLED()) 29 30 bld.SAMBA_LIBRARY('dlz_bind9_9', 31 source='dlz_bind9.c', 32 cflags='-DBIND_VERSION_9_9', 33 private_library=True, 34 link_name='modules/bind9/dlz_bind9_9.so', 35 realname='dlz_bind9_9.so', 36 install_path='${MODULESDIR}/bind9', 37 deps='samba-hostconfig samdb-common gensec popt dnsserver_common', 38 enabled=bld.AD_DC_BUILD_IS_ENABLED()) 39 40 bld.SAMBA_LIBRARY('dlz_bind9_10', 41 source='dlz_bind9.c', 42 cflags='-DBIND_VERSION_9_10', 43 private_library=True, 44 link_name='modules/bind9/dlz_bind9_10.so', 45 realname='dlz_bind9_10.so', 46 install_path='${MODULESDIR}/bind9', 47 deps='samba-hostconfig samdb-common gensec popt dnsserver_common', 48 enabled=bld.AD_DC_BUILD_IS_ENABLED()) 49 50 bld.SAMBA_LIBRARY('dlz_bind9_for_torture', 51 source='dlz_bind9.c', 52 cflags='-DBIND_VERSION_9_8', 53 private_library=True, 54 deps='samba-hostconfig samdb-common gensec popt dnsserver_common', 55 enabled=bld.AD_DC_BUILD_IS_ENABLED()) 56 57 58 bld.SAMBA_PYTHON('python_dsdb_dns', 59 source='pydns.c', 60 deps='samdb pyldb-util pyrpc_util dnsserver_common pytalloc-util', 61 realname='samba/dsdb_dns.so')
Note:
See TracChangeset
for help on using the changeset viewer.