Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/source4/dns_server
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/dns_server/TODO

    r740 r988  
    44Just so we don't forget the required features for an AD-compatible DNS server:
    55
    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
    117  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)
    1410- 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  
    2626#include "dsdb/samdb/samdb.h"
    2727#include "dsdb/common/util.h"
     28#include "auth/auth.h"
    2829#include "auth/session.h"
    2930#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"
    3035#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"
    3440#include "dlz_minimal.h"
     41#include "dns_server/dnsserver_common.h"
     42
     43struct b9_options {
     44        const char *url;
     45        const char *debug;
     46};
     47
     48struct b9_zone {
     49        char *name;
     50        struct b9_zone *prev, *next;
     51};
    3552
    3653struct dlz_bind9_data {
     54        struct b9_options options;
    3755        struct ldb_context *samdb;
    3856        struct tevent_context *ev_ctx;
     
    4058        int *transaction_token;
    4159        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;
    4267
    4368        /* 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;
    5073};
    5174
     75static struct dlz_bind9_data *dlz_bind9_state = NULL;
     76static int dlz_bind9_state_ref_count = 0;
    5277
    5378static const char *zone_prefixes[] = {
    5479        "CN=MicrosoftDNS,DC=DomainDnsZones",
    5580        "CN=MicrosoftDNS,DC=ForestDnsZones",
     81        "CN=MicrosoftDNS,CN=System",
    5682        NULL
    5783};
     
    82108                state->writeable_zone = ptr;
    83109        }
     110}
     111
     112/*
     113 * Add a trailing '.' if it's missing
     114 */
     115static 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;
    84131}
    85132
     
    92139                      const char **type, const char **data)
    93140{
     141        uint32_t i;
     142        char *tmp;
     143        const char *fqdn;
     144
    94145        switch (rec->wType) {
    95146        case DNS_TYPE_A:
     
    105156        case DNS_TYPE_CNAME:
    106157                *type = "cname";
    107                 *data = rec->data.cname;
     158                *data = b9_format_fqdn(mem_ctx, rec->data.cname);
    108159                break;
    109160
    110161        case DNS_TYPE_TXT:
    111162                *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;
    113168                break;
    114169
    115170        case DNS_TYPE_PTR:
    116171                *type = "ptr";
    117                 *data = rec->data.ptr;
     172                *data = b9_format_fqdn(mem_ctx, rec->data.ptr);
    118173                break;
    119174
    120175        case DNS_TYPE_SRV:
    121176                *type = "srv";
     177                fqdn = b9_format_fqdn(mem_ctx, rec->data.srv.nameTarget);
     178                if (fqdn == NULL) {
     179                        return false;
     180                }
    122181                *data = talloc_asprintf(mem_ctx, "%u %u %u %s",
    123182                                        rec->data.srv.wPriority,
    124183                                        rec->data.srv.wWeight,
    125184                                        rec->data.srv.wPort,
    126                                         rec->data.srv.nameTarget);
     185                                        fqdn);
    127186                break;
    128187
    129188        case DNS_TYPE_MX:
    130189                *type = "mx";
     190                fqdn = b9_format_fqdn(mem_ctx, rec->data.mx.nameTarget);
     191                if (fqdn == NULL) {
     192                        return false;
     193                }
    131194                *data = talloc_asprintf(mem_ctx, "%u %s",
    132                                         rec->data.mx.wPriority,
    133                                         rec->data.mx.nameTarget);
     195                                        rec->data.mx.wPriority, fqdn);
    134196                break;
    135197
     
    143205        case DNS_TYPE_NS:
    144206                *type = "ns";
    145                 *data = rec->data.ns;
     207                *data = b9_format_fqdn(mem_ctx, rec->data.ns);
    146208                break;
    147209
     
    154216                 * force clients to send updates to the right local DC
    155217                 */
    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));
    158221                if (mname == NULL) {
    159222                        return false;
     
    164227                }
    165228
     229                fqdn = b9_format_fqdn(mem_ctx, rec->data.soa.rname);
     230                if (fqdn == NULL) {
     231                        return false;
     232                }
     233
    166234                state->soa_serial = rec->data.soa.serial;
    167235
    168236                *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u",
    169                                         mname,
    170                                         rec->data.soa.rname,
     237                                        mname, fqdn,
    171238                                        rec->data.soa.serial,
    172239                                        rec->data.soa.refresh,
     
    178245
    179246        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",
    181248                           rec->wType);
    182249                return false;
     
    253320{
    254321        char *full_name, *dclass, *type;
    255         char *str, *saveptr=NULL;
     322        char *str, *tmp, *saveptr=NULL;
    256323        int i;
    257324
     
    294361
    295362        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                }
    297378                break;
    298379
     
    333414
    334415        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",
    336417                           rec->wType);
    337418                return false;
     
    340421        /* we should be at the end of the buffer now */
    341422        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);
    343425                return false;
    344426        }
     
    348430
    349431/*
    350   send a resource recond to bind9
     432  send a resource record to bind9
    351433 */
    352434static isc_result_t b9_putrr(struct dlz_bind9_data *state,
     
    388470
    389471/*
    390   send a named resource recond to bind9
     472  send a named resource record to bind9
    391473 */
    392474static isc_result_t b9_putnamedrr(struct dlz_bind9_data *state,
     
    415497}
    416498
    417 struct b9_options {
    418         const char *url;
    419 };
    420 
    421499/*
    422500   parse options
    423501 */
    424502static isc_result_t parse_options(struct dlz_bind9_data *state,
    425                                   unsigned int argc, char *argv[],
     503                                  unsigned int argc, const char **argv,
    426504                                  struct b9_options *options)
    427505{
     
    429507        poptContext pc;
    430508        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" },
    432511                { NULL }
    433512        };
    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);
    451516        while ((opt = poptGetNextOpt(pc)) != -1) {
    452517                switch (opt) {
    453518                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",
    455520                                   poptBadOption(pc, 0), poptStrerror(opt));
    456521                        return ISC_R_FAILURE;
     
    458523        }
    459524
    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 
    466525        return ISC_R_SUCCESS;
    467526}
     
    469528
    470529/*
     530 * Create session info from PAC
     531 * This is called as auth_context->generate_session_info_pac()
     532 */
     533static 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 */
     578static 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
     597static 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/*
    471605  called to initialise the driver
    472606 */
    473607_PUBLIC_ isc_result_t dlz_create(const char *dlzname,
    474                                  unsigned int argc, char *argv[],
     608                                 unsigned int argc, const char **argv,
    475609                                 void **dbdata, ...)
    476610{
     
    479613        va_list ap;
    480614        isc_result_t result;
    481         TALLOC_CTX *tmp_ctx;
    482         int ret;
    483615        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        }
    487623
    488624        state = talloc_zero(NULL, struct dlz_bind9_data);
     
    491627        }
    492628
    493         tmp_ctx = talloc_new(state);
     629        talloc_set_destructor(state, dlz_state_debug_unregister);
    494630
    495631        /* fill in the helper functions */
     
    500636        va_end(ap);
    501637
     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
    502644        state->ev_ctx = s4_event_context_init(state);
    503645        if (state->ev_ctx == NULL) {
     
    506648        }
    507649
    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);
    516651        if (result != ISC_R_SUCCESS) {
    517652                goto failed;
     
    524659        }
    525660
    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) {
    530687                        result = ISC_R_NOMEMORY;
    531688                        goto failed;
     
    533690        }
    534691
    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);
    547697                result = ISC_R_FAILURE;
    548698                goto failed;
     
    552702        if (dn == NULL) {
    553703                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));
    555705                result = ISC_R_FAILURE;
    556706                goto failed;
     
    560710                   ldb_dn_get_linearized(dn));
    561711
     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
    562717        *dbdata = state;
    563 
    564         talloc_free(tmp_ctx);
     718        dlz_bind9_state = state;
     719        dlz_bind9_state_ref_count++;
     720
    565721        return ISC_R_SUCCESS;
    566722
     
    577733        struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
    578734        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        }
    580742}
    581743
     
    665827  see if we handle a given zone
    666828 */
     829#if DLZ_DLOPEN_VERSION < 3
    667830_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
    668836{
    669837        struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
     
    681849{
    682850        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;
    687851        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;
    688855
    689856        for (i=0; zone_prefixes[i]; i++) {
     
    699866                }
    700867
    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)) {
    704871                        break;
    705872                }
    706873        }
    707         if (ret != LDB_SUCCESS) {
     874        if (!W_ERROR_IS_OK(werr)) {
    708875                talloc_free(tmp_ctx);
    709876                return ISC_R_NOTFOUND;
    710877        }
    711878
    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++) {
    721880                isc_result_t result;
    722881
    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);
    733883                if (result != ISC_R_SUCCESS) {
    734884                        talloc_free(tmp_ctx);
     
    744894  lookup one record
    745895 */
     896#if DLZ_DLOPEN_VERSION == 1
    746897_PUBLIC_ isc_result_t dlz_lookup(const char *zone, const char *name,
    747898                                 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
    748905{
    749906        struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
     
    758915{
    759916        /* 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);
    761920}
    762921
     
    802961                const char *rdn, *name;
    803962                const struct ldb_val *v;
     963                WERROR werr;
     964                struct dnsp_DnssrvRpcRecord *recs = NULL;
     965                uint16_t num_recs = 0;
    804966
    805967                el = ldb_msg_find_element(res->msgs[i], "dnsRecord");
     
    830992                        name = talloc_asprintf(el_ctx, "%s.%s", rdn, zone);
    831993                }
     994                name = b9_format_fqdn(el_ctx, name);
    832995                if (name == NULL) {
    833996                        talloc_free(tmp_ctx);
     
    835998                }
    836999
    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++) {
    8401009                        isc_result_t result;
    8411010
    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]);
    8511012                        if (result != ISC_R_SUCCESS) {
    8521013                                continue;
    8531014                        }
    8541015                }
     1016
     1017                talloc_free(el_ctx);
    8551018        }
    8561019
     
    9301093static bool b9_has_soa(struct dlz_bind9_data *state, struct ldb_dn *dn, const char *zone)
    9311094{
    932         const char *attrs[] = { "dnsRecord", NULL };
    933         struct ldb_result *res;
    934         struct ldb_message_element *el;
    9351095        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;
    9371099
    9381100        if (!ldb_dn_add_child_fmt(dn, "DC=@,DC=%s", zone)) {
     
    9411103        }
    9421104
    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)) {
    9461108                talloc_free(tmp_ctx);
    9471109                return false;
    9481110        }
    9491111
    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) {
    9651114                        talloc_free(tmp_ctx);
    9661115                        return true;
     
    9721121}
    9731122
     1123static 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
     1142static 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
    9741159/*
    9751160  configure a writeable zone
    9761161 */
     1162#if DLZ_DLOPEN_VERSION < 3
    9771163_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
    9781168{
    9791169        struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
     
    10151205                        isc_result_t result;
    10161206                        const char *zone = ldb_msg_find_attr_as_string(res->msgs[j], "name", NULL);
     1207                        struct ldb_dn *zone_dn;
     1208
    10171209                        if (zone == NULL) {
    10181210                                continue;
    10191211                        }
    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)) {
    10211215                                continue;
    10221216                        }
     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
    10231239                        result = state->writeable_zone(view, zone);
     1240#else
     1241                        result = state->writeable_zone(view, dlzdb, zone);
     1242#endif
    10241243                        if (result != ISC_R_SUCCESS) {
    10251244                                state->log(ISC_LOG_ERROR, "samba_dlz: Failed to configure zone '%s'",
     
    10441263{
    10451264        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;
    10631269        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;
    10901400}
    10911401
     
    11121422                            struct dnsp_DnssrvRpcRecord *rec1, struct dnsp_DnssrvRpcRecord *rec2)
    11131423{
     1424        bool status;
     1425        int i;
     1426        struct in6_addr rec1_in_addr6;
     1427        struct in6_addr rec2_in_addr6;
     1428
    11141429        if (rec1->wType != rec2->wType) {
    11151430                return false;
     
    11241439        case DNS_TYPE_A:
    11251440                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        }
    11281455        case DNS_TYPE_CNAME:
    11291456                return dns_name_equal(rec1->data.cname, rec2->data.cname);
    11301457        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;
    11321464        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);
    11341466        case DNS_TYPE_NS:
    11351467                return dns_name_equal(rec1->data.ns, rec2->data.ns);
     
    11581490                        rec1->data.soa.minimum == rec2->data.soa.minimum;
    11591491        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",
    11611493                           rec1->wType);
    11621494                break;
     
    11661498}
    11671499
     1500/*
     1501 * Update session_info on samdb using the cached credentials
     1502 */
     1503static 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 */
     1529static void b9_reset_session_info(struct dlz_bind9_data *state)
     1530{
     1531        ldb_set_opaque(state->samdb, "sessionInfo", system_session(state->lp));
     1532}
    11681533
    11691534/*
     
    11761541        struct ldb_dn *dn;
    11771542        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;
    11831549        NTTIME t;
     1550        WERROR werr;
    11841551
    11851552        if (state->transaction_token != (void*)version) {
     
    11981565
    11991566        rec->rank        = DNS_RANK_ZONE;
    1200         rec->dwSerial    = state->soa_serial;
    12011567        rec->dwTimeStamp = (uint32_t)t;
    12021568
     
    12151581
    12161582        /* 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));
    12201592                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;
    12251602        }
    12261603
     
    12281605         * replace a record or add to it
    12291606         */
    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));
    12341615                talloc_free(rec);
    12351616                return ISC_R_FAILURE;
    12361617        }
    12371618
    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) {
    12551620                /* 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) {
    12581625                        talloc_free(rec);
    12591626                        return ISC_R_NOMEMORY;
    12601627                }
    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)) {
    12691634                talloc_free(rec);
    12701635                return ISC_R_FAILURE;
     
    12721637
    12731638        /* 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));
    12791648                talloc_free(rec);
    12801649                return ISC_R_FAILURE;
     
    12961665        struct ldb_dn *dn;
    12971666        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;
    13031671
    13041672        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");
    13061674                return ISC_R_FAILURE;
    13071675        }
     
    13131681
    13141682        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);
    13161684                talloc_free(rec);
    13171685                return ISC_R_FAILURE;
     
    13261694
    13271695        /* 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)) {
    13301699                talloc_free(rec);
    13311700                return ISC_R_NOTFOUND;
    13321701        }
    13331702
    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                        };
    13571708                        break;
    13581709                }
    13591710        }
    1360         if (i == el->num_values) {
     1711        if (i == num_recs) {
    13611712                talloc_free(rec);
    13621713                return ISC_R_NOTFOUND;
    13631714        }
    13641715
    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)) {
    13791728                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));
    13811730                talloc_free(rec);
    13821731                return ISC_R_FAILURE;
     
    13991748        struct ldb_dn *dn;
    14001749        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;
    14061750        enum dns_record_type dns_type;
    14071751        bool found = false;
     1752        struct dnsp_DnssrvRpcRecord *recs = NULL;
     1753        uint16_t num_recs = 0;
     1754        uint16_t ri = 0;
     1755        WERROR werr;
    14081756
    14091757        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");
    14111759                return ISC_R_FAILURE;
    14121760        }
    14131761
    14141762        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);
    14161764                return ISC_R_FAILURE;
    14171765        }
     
    14271775
    14281776        /* 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)) {
    14311780                talloc_free(tmp_ctx);
    14321781                return ISC_R_NOTFOUND;
    14331782        }
    14341783
    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                };
    14641793        }
    14651794
     
    14691798        }
    14701799
    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));
    14821814                talloc_free(tmp_ctx);
    14831815                return ISC_R_FAILURE;
  • vendor/current/source4/dns_server/dlz_minimal.h

    r740 r988  
    1717 */
    1818
    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
    2537typedef unsigned int isc_result_t;
     38#if DLZ_DLOPEN_VERSION == 1
    2639typedef bool isc_boolean_t;
     40#else
     41typedef int isc_boolean_t;
     42#endif
    2743typedef uint32_t dns_ttl_t;
    2844
    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() */
    3246#define DNS_SDLZFLAG_THREADSAFE         0x00000001U
     47#define DNS_SDLZFLAG_RELATIVEOWNER      0x00000002U
     48#define DNS_SDLZFLAG_RELATIVERDATA      0x00000004U
    3349
    3450/* result codes */
    3551#define ISC_R_SUCCESS                   0
    3652#define ISC_R_NOMEMORY                  1
     53#define ISC_R_NOPERM                    6
     54#define ISC_R_NOSPACE                   19
    3755#define ISC_R_NOTFOUND                  23
    3856#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
    3966
    4067/* log levels */
     
    4471#define ISC_LOG_ERROR           (-4)
    4572#define ISC_LOG_CRITICAL        (-5)
    46 
    47 /* some opaque structures */
     73#define ISC_LOG_DEBUG(level)    (level)
     74
     75/* opaque structures */
    4876typedef void *dns_sdlzlookup_t;
    4977typedef void *dns_sdlzallnodes_t;
    5078typedef void *dns_view_t;
    51 
    52 /*
    53  * prototypes for the functions you can include in your driver
    54  */
    55 
     79typedef 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 */
     86typedef 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
     98typedef struct dns_clientinfo {
     99        uint16_t version;
     100        void *data;
     101} dns_clientinfo_t;
     102
     103typedef 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
     109typedef 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
     120typedef void log_t(int level, const char *fmt, ...);
     121
     122typedef 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
     127typedef 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
     134typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
     135                                             const char *zone_name);
     136#else /* DLZ_DLOPEN_VERSION >= 3 */
     137typedef 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 */
    56145
    57146/*
    58147 * 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 */
     153int
     154dlz_version(unsigned int *flags);
    62155
    63156/*
    64157 * dlz_create() is required for all DLZ external drivers.
    65158 */
    66 isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...);
     159isc_result_t
     160dlz_create(const char *dlzname, unsigned int argc, const char *argv[],
     161           void **dbdata, ...);
    67162
    68163/*
     
    70165 * unloaded if supplied
    71166 */
    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);
     167void
     168dlz_destroy(void *dbdata);
     169
     170/*
     171 * dlz_findzonedb is required for all DLZ external drivers
     172 */
     173#if DLZ_DLOPEN_VERSION < 3
     174isc_result_t
     175dlz_findzonedb(void *dbdata, const char *name);
     176#else /* DLZ_DLOPEN_VERSION >= 3 */
     177isc_result_t
     178dlz_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
     187isc_result_t
     188dlz_lookup(const char *zone, const char *name, void *dbdata,
     189           dns_sdlzlookup_t *lookup);
     190#else /* DLZ_DLOPEN_VERSION > 1 */
     191isc_result_t
     192dlz_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 */
     202isc_result_t
     203dlz_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 */
     209isc_result_t
     210dlz_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 */
     216isc_result_t
     217dlz_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 */
     223isc_result_t
     224dlz_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 */
     230void
     231dlz_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
     239isc_result_t
     240dlz_configure(dns_view_t *view, void *dbdata);
     241#else /* DLZ_DLOPEN_VERSION >= 3 */
     242isc_result_t
     243dlz_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 */
     250isc_boolean_t
     251dlz_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 */
     259isc_result_t
     260dlz_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 */
     267isc_result_t
     268dlz_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 */
     275isc_result_t
     276dlz_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  
    2121
    2222#include "includes.h"
     23#include "smbd/service_task.h"
    2324#include "libcli/util/werror.h"
    2425#include "librpc/ndr/libndr.h"
     
    2627#include "librpc/gen_ndr/ndr_dnsp.h"
    2728#include <ldb.h>
     29#include "param/param.h"
    2830#include "dsdb/samdb/samdb.h"
    2931#include "dsdb/common/util.h"
    3032#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
     43static 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
     140static 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
     266struct ask_forwarder_state {
     267        struct tevent_context *ev;
     268        uint16_t id;
     269        struct dns_name_packet in_packet;
     270};
     271
     272static void ask_forwarder_done(struct tevent_req *subreq);
     273
     274static 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
     331static 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
     364static 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
     391static 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;
    38400        struct ldb_dn *dn = NULL;
     401        unsigned int ri;
    39402        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
     431static 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);
     436static WERROR handle_authoritative_recv(struct tevent_req *req);
     437
     438struct handle_dnsrpcrec_state {
     439        struct dns_res_rec **answers;
     440        struct dns_res_rec **nsrecs;
     441};
     442
     443static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq);
     444static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq);
     445
     446static 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
     524static 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
     538static 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
     574static WERROR handle_dnsrpcrec_recv(struct tevent_req *req)
     575{
     576        return tevent_req_simple_recv_werror(req);
     577}
     578
     579struct handle_authoritative_state {
     580        struct tevent_context *ev;
     581        struct dns_server *dns;
     582        struct dns_name_question *question;
     583        const char *forwarder;
     584
    45585        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
     593static void handle_authoritative_done(struct tevent_req *subreq);
     594
     595static 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
     646static 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
     677static 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
     696static 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
     756static 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
     786static 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);
    84862                        }
    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;
    100883                        }
    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;
    186902                break;
    187903        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;
    197910
    198911        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
     914struct 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
     923static void dns_server_process_query_got_auth(struct tevent_req *subreq);
     924static void dns_server_process_query_got_response(struct tevent_req *subreq);
     925
     926struct 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
     1011static 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
     1030static 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
     1050WERROR 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  
    4343#include "auth/session.h"
    4444#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
     55NTSTATUS server_service_dns_init(void);
    4556
    4657/* hold information about one dns socket */
     
    92103}
    93104
    94 static NTSTATUS dns_process(struct dns_server *dns,
    95                             TALLOC_CTX *mem_ctx,
    96                             DATA_BLOB *in,
    97                             DATA_BLOB *out)
    98 {
     105struct 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
     115static void dns_process_done(struct tevent_req *subreq);
     116
     117static 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;
    99124        enum ndr_err_code ndr_err;
    100125        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;
    105135
    106136        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
    121146        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) {
    137180        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);
    150195                break;
    151196        default:
    152197                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
     206static 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
     227static 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);
    172263        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
     271drop:
     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;
    186279}
    187280
     
    194287};
    195288
     289static void dns_tcp_call_process_done(struct tevent_req *subreq);
    196290static void dns_tcp_call_writev_done(struct tevent_req *subreq);
    197291
     
    200294        struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq,
    201295                                      struct dns_tcp_connection);
     296        struct dns_server *dns = dns_conn->dns_socket->dns;
    202297        struct dns_tcp_call *call;
    203298        NTSTATUS status;
     
    229324        }
    230325
    231         DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
     326        DEBUG(10,("Received DNS TCP packet of length %lu from %s\n",
    232327                 (long) call->in.length,
    233328                 tsocket_address_string(dns_conn->conn->remote_address, call)));
    234329
    235330        /* 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
     362static 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)));
    243373                dns_tcp_terminate_connection(dns_conn,
    244374                                "dns_tcp_call_loop: process function failed");
     
    247377
    248378        /* First add the length of the out buffer */
    249         RSIVAL(call->out_hdr, 0, call->out.length);
     379        RSSVAL(call->out_hdr, 0, call->out.length);
    250380        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;
    252382
    253383        call->out_iov[1].iov_base = (char *) call->out.data;
     
    265395        }
    266396        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);
    284397}
    285398
     
    354467
    355468        /*
    356          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
    357          * packet_full_request_u32 provides 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.
    358471         */
    359472        subreq = tstream_read_pdu_blob_send(dns_conn,
    360473                                            dns_conn->conn->event.ctx,
    361474                                            dns_conn->tstream,
    362                                             4, /* initial_read_size */
    363                                             packet_full_request_u32,
     475                                            2, /* initial_read_size */
     476                                            packet_full_request_u16,
    364477                                            dns_conn);
    365478        if (subreq == NULL) {
     
    379492
    380493struct dns_udp_call {
     494        struct dns_udp_socket *sock;
    381495        struct tsocket_address *src;
    382496        DATA_BLOB in;
     
    384498};
    385499
     500static void dns_udp_call_process_done(struct tevent_req *subreq);
    386501static void dns_udp_call_sendto_done(struct tevent_req *subreq);
    387502
     
    390505        struct dns_udp_socket *sock = tevent_req_callback_data(subreq,
    391506                                      struct dns_udp_socket);
     507        struct dns_server *dns = sock->dns_socket->dns;
    392508        struct dns_udp_call *call;
    393509        uint8_t *buf;
    394510        ssize_t len;
    395511        int sys_errno;
    396         NTSTATUS status;
    397512
    398513        call = talloc(sock, struct dns_udp_call);
     
    401516                goto done;
    402517        }
     518        call->sock = sock;
    403519
    404520        len = tdgram_recvfrom_recv(subreq, &sys_errno,
     
    413529        call->in.length = len;
    414530
    415         DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
     531        DEBUG(10,("Received DNS UDP packet of length %lu from %s\n",
    416532                 (long)call->in.length,
    417533                 tsocket_address_string(call->src, call)));
    418534
    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);
    424539                goto done;
    425540        }
    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);
    439542
    440543done:
     
    451554}
    452555
     556static 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}
    453586static void dns_udp_call_sendto_done(struct tevent_req *subreq)
    454587{
    455588        struct dns_udp_call *call = tevent_req_callback_data(subreq,
    456589                                       struct dns_udp_call);
    457         ssize_t ret;
    458590        int sys_errno;
    459591
    460         ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
     592        tdgram_sendto_queue_recv(subreq, &sys_errno);
    461593
    462594        /* We don't care about errors */
     
    489621                                                &dns_socket->local_address);
    490622        if (ret != 0) {
    491                 status = map_nt_error_from_unix(errno);
     623                status = map_nt_error_from_unix_common(errno);
    492624                return status;
    493625        }
     
    518650                                     &dns_udp_socket->dgram);
    519651        if (ret != 0) {
    520                 status = map_nt_error_from_unix(errno);
     652                status = map_nt_error_from_unix_common(errno);
    521653                DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
    522654                         address, port, nt_errstr(status)));
     
    540672  setup our listening sockets on the configured network interfaces
    541673*/
    542 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,
     674static NTSTATUS dns_startup_interfaces(struct dns_server *dns,
    543675                                       struct interface *ifaces)
    544676{
     
    558690        }
    559691
    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                }
    567722        }
    568723
     
    572727}
    573728
    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;
     729static 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
     750static 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 */
     774static 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;
    593788}
    594789
     
    597792        struct dns_server *dns;
    598793        NTSTATUS status;
    599         struct interface *ifaces;
     794        struct interface *ifaces = NULL;
    600795        int ret;
    601         struct 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;
    605800
    606801        switch (lpcfg_server_role(task->lp_ctx)) {
     
    611806                task_server_terminate(task, "dns: no DNS required in member server configuration", false);
    612807                return;
    613         case ROLE_DOMAIN_CONTROLLER:
     808        case ROLE_ACTIVE_DIRECTORY_DC:
    614809                /* Yes, we want a DNS */
    615810                break;
    616811        }
    617812
    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                }
    623820        }
    624821
     
    632829
    633830        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        }
    634839
    635840        dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx,
     
    640845        }
    641846
    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);
    674899        if (!NT_STATUS_IS_OK(status)) {
    675900                task_server_terminate(task, "dns failed to setup interfaces", true);
    676901                return;
    677902        }
     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        }
    678917}
    679918
  • vendor/current/source4/dns_server/dns_server.h

    r740 r988  
    2424
    2525#include "librpc/gen_ndr/dns.h"
     26#include "librpc/gen_ndr/ndr_dnsp.h"
     27#include "dnsserver_common.h"
    2628
    2729struct tsocket_address;
     30struct 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};
    2838
    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
     41struct dns_server_tkey_store {
     42        struct dns_server_tkey **tkeys;
     43        uint16_t next_idx;
     44        uint16_t size;
    3345};
    3446
     
    3749        struct ldb_context *samdb;
    3850        struct dns_server_zone *zones;
     51        struct dns_server_tkey_store *tkeys;
     52        struct cli_credentials *server_credentials;
     53        uint16_t max_payload;
    3954};
    4055
     56struct 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};
    4165
    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);
     66struct 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);
     70WERROR 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);
    4875
    4976WERROR dns_server_process_update(struct dns_server *dns,
     77                                 const struct dns_request_state *state,
    5078                                 TALLOC_CTX *mem_ctx,
    51                                  struct dns_name_packet *in,
    52                                  const struct dns_res_rec *prereqs, uint16_t prereq_count,
    53                                  struct dns_res_rec **updates,      uint16_t *update_count,
    54                                  struct dns_res_rec **additional,   uint16_t *arcount);
     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);
    5583
    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);
     84bool dns_name_equal(const char *name1, const char *name2);
     85bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
     86                       struct dnsp_DnssrvRpcRecord *rec2);
     87bool dns_authorative_for_zone(struct dns_server *dns,
     88                              const char *name);
     89const char *dns_get_authoritative_zone(struct dns_server *dns,
     90                                       const char *name);
     91WERROR 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);
     96WERROR 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);
    58102WERROR dns_name2dn(struct dns_server *dns,
    59103                   TALLOC_CTX *mem_ctx,
    60104                   const char *name,
    61105                   struct ldb_dn **_dn);
     106WERROR dns_generate_options(struct dns_server *dns,
     107                            TALLOC_CTX *mem_ctx,
     108                            struct dns_res_rec **options);
     109struct dns_server_tkey *dns_find_tkey(struct dns_server_tkey_store *store,
     110                                      const char *name);
     111WERROR 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);
     116WERROR 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);
    62121
    63 #define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str
     122#include "source4/dns_server/dnsserver_common.h"
     123
    64124#endif /* __DNS_SERVER_H__ */
  • vendor/current/source4/dns_server/dns_update.c

    r740 r988  
    2626#include "librpc/gen_ndr/ndr_dnsp.h"
    2727#include <ldb.h>
     28#include "param/param.h"
     29#include "param/loadparm.h"
    2830#include "dsdb/samdb/samdb.h"
    2931#include "dsdb/common/util.h"
     32#include "smbd/service_task.h"
    3033#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
     39static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
     40                             const struct dns_res_rec *rrec,
     41                             struct dnsp_DnssrvRpcRecord *r);
     42
     43static 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)
    3648{
    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
    3858        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
     201static 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{
    39206        uint16_t i;
    40 
    41         zone = in->questions;
     207        WERROR final_error = WERR_OK;
    42208
    43209        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        }
    88228
    89229        return WERR_OK;
     
    105245                }
    106246                if (zone->question_class == r->rr_class) {
    107                         /*TODO: also check for AXFR,MAILA,MAILB  */
    108247                        if (r->rr_type == DNS_QTYPE_ALL) {
    109248                                return DNS_ERR(FORMAT_ERROR);
    110249                        }
     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                        }
    111259                } 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) {
    113273                                return DNS_ERR(FORMAT_ERROR);
    114274                        }
    115275                } 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) {
    117289                                return DNS_ERR(FORMAT_ERROR);
    118290                        }
     
    124296}
    125297
     298static 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
     368done:
     369
     370        return WERR_OK;
     371}
     372
     373
     374static 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
     650static 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
     702failed:
     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
     715static 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
    126744WERROR dns_server_process_update(struct dns_server *dns,
     745                                 const struct dns_request_state *state,
    127746                                 TALLOC_CTX *mem_ctx,
    128                                  struct dns_name_packet *in,
    129                                  const struct dns_res_rec *prereqs, uint16_t prereq_count,
    130                                  struct dns_res_rec **updates,      uint16_t *update_count,
    131                                  struct dns_res_rec **additional,   uint16_t *arcount)
     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)
    132751{
    133752        struct dns_name_question *zone;
     
    135754        size_t host_part_len = 0;
    136755        WERROR werror = DNS_ERR(NOT_IMPLEMENTED);
    137         bool update_allowed = false;
     756        struct dns_server_tkey *tkey = NULL;
    138757
    139758        if (in->qdcount != 1) {
     
    141760        }
    142761
    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        }
    144768
    145769        if (zone->question_type != DNS_QTYPE_SOA) {
     
    147771        }
    148772
    149         DEBUG(0, ("Got a dns update request.\n"));
     773        DEBUG(2, ("Got a dns update request.\n"));
    150774
    151775        for (z = dns->zones; z != NULL; z = z->next) {
     
    159783
    160784        if (z == NULL) {
     785                DEBUG(1, ("We're not authoritative for this zone\n"));
    161786                return DNS_ERR(NOTAUTH);
    162787        }
     
    164789        if (host_part_len != 0) {
    165790                /* TODO: We need to delegate this one */
     791                DEBUG(1, ("Would have to delegate zone '%s'.\n", zone->name));
    166792                return DNS_ERR(NOT_IMPLEMENTED);
    167793        }
    168794
    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);
    170799        W_ERROR_NOT_OK_RETURN(werror);
    171800
    172         /* TODO: Check if update is allowed, we probably want "always",
    173          * key-based GSSAPI, key-based bind-style TSIG and "never" as
    174          * 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;
    179808        werror = update_prescan(in->questions, *updates, *update_count);
    180809        W_ERROR_NOT_OK_RETURN(werror);
    181810
     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
    182815        return werror;
    183816}
  • vendor/current/source4/dns_server/dns_utils.c

    r740 r988  
    3131#include "dns_server/dns_server.h"
    3232
    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 */
     37bool 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 */
     48bool 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) {
    7055                return false;
    7156        }
    7257
    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) {
    8668                        return false;
    8769                }
    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
     110WERROR 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
     120WERROR 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
     133bool 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        }
    99157
    100158        return true;
     159}
     160
     161const 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;
    101175}
    102176
     
    104178                   TALLOC_CTX *mem_ctx,
    105179                   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
     186WERROR 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;
    150204        return WERR_OK;
    151205}
  • vendor/current/source4/dns_server/wscript_build

    r740 r988  
    11#!/usr/bin/env python
    22
     3bld.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
    39bld.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',
    511        subsystem='service',
    612        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',
    814        local_include=False,
    915        internal_module=False,
     16        enabled=bld.AD_DC_BUILD_IS_ENABLED()
    1017        )
    1118
     
    1320bld.SAMBA_LIBRARY('dlz_bind9',
    1421                  source='dlz_bind9.c',
     22                  cflags='-DBIND_VERSION_9_8',
    1523                  private_library=True,
    1624                  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
     30bld.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
     40bld.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
     50bld.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
     58bld.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.