CVE-2016-2115: s3:winbindd: use lp_client_ipc_{min,max}_protocol()
[samba.git] / source4 / dns_server / dns_utils.c
index 1f7648cd5b418c140db771b2c2b554dc7215f1aa..ce450b56c645ba5489f9ac8fa1dc715e32aad5e0 100644 (file)
 #include "dsdb/common/util.h"
 #include "dns_server/dns_server.h"
 
-uint8_t werr_to_dns_err(WERROR werr)
-{
-       if (W_ERROR_EQUAL(WERR_OK, werr)) {
-               return DNS_RCODE_OK;
-       } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) {
-               return DNS_RCODE_FORMERR;
-       } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) {
-               return DNS_RCODE_SERVFAIL;
-       } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) {
-               return DNS_RCODE_NXDOMAIN;
-       } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) {
-               return DNS_RCODE_NOTIMP;
-       } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) {
-               return DNS_RCODE_REFUSED;
-       } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) {
-               return DNS_RCODE_YXDOMAIN;
-       } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) {
-               return DNS_RCODE_YXRRSET;
-       } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) {
-               return DNS_RCODE_NXRRSET;
-       } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) {
-               return DNS_RCODE_NOTAUTH;
-       } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) {
-               return DNS_RCODE_NOTZONE;
-       }
-       DEBUG(5, ("No mapping exists for %%s\n"));
-       return DNS_RCODE_SERVFAIL;
-}
-
-bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
-{
-       size_t zl = strlen(zone);
-       size_t nl = strlen(name);
-       ssize_t zi, ni;
-       static const size_t fixup = 'a' - 'A';
-
-       if (zl > nl) {
-               return false;
-       }
-
-       for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
-               char zc = zone[zi];
-               char nc = name[ni];
-
-               /* convert to lower case */
-               if (zc >= 'A' && zc <= 'Z') {
-                       zc += fixup;
-               }
-               if (nc >= 'A' && nc <= 'Z') {
-                       nc += fixup;
-               }
-
-               if (zc != nc) {
-                       return false;
-               }
-       }
-
-       if (ni >= 0) {
-               if (name[ni] != '.') {
-                       return false;
-               }
-
-               ni--;
-       }
-
-       *host_part_len = ni+1;
-
-       return true;
-}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_DNS
 
 /* Names are equal if they match and there's nothing left over */
 bool dns_name_equal(const char *name1, const char *name2)
@@ -180,166 +113,93 @@ WERROR dns_lookup_records(struct dns_server *dns,
                          struct dnsp_DnssrvRpcRecord **records,
                          uint16_t *rec_count)
 {
-       static const char * const attrs[] = { "dnsRecord", NULL};
-       struct ldb_message_element *el;
-       uint16_t ri;
-       int ret;
-       struct ldb_message *msg = NULL;
-       struct dnsp_DnssrvRpcRecord *recs;
-
-       ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn,
-                             LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)");
-       if (ret != LDB_SUCCESS) {
-               /* TODO: we need to check if there's a glue record we need to
-                * create a referral to */
-               return DNS_ERR(NAME_ERROR);
-       }
-
-       el = ldb_msg_find_element(msg, attrs[0]);
-       if (el == NULL) {
-               *records = NULL;
-               *rec_count = 0;
-               return WERR_OK;
-       }
-
-       recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values);
-       W_ERROR_HAVE_NO_MEMORY(recs);
-       for (ri = 0; ri < el->num_values; ri++) {
-               struct ldb_val *v = &el->values[ri];
-               enum ndr_err_code ndr_err;
-
-               ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
-                               (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
-                       return DNS_ERR(SERVER_FAILURE);
-               }
-       }
-       *records = recs;
-       *rec_count = el->num_values;
-       return WERR_OK;
+       return dns_common_lookup(dns->samdb, mem_ctx, dn,
+                                records, rec_count, NULL);
 }
 
 WERROR dns_replace_records(struct dns_server *dns,
                           TALLOC_CTX *mem_ctx,
                           struct ldb_dn *dn,
                           bool needs_add,
-                          const struct dnsp_DnssrvRpcRecord *records,
+                          struct dnsp_DnssrvRpcRecord *records,
                           uint16_t rec_count)
 {
-       struct ldb_message_element *el;
-       uint16_t i;
-       int ret;
-       struct ldb_message *msg = NULL;
-
-       msg = ldb_msg_new(mem_ctx);
-       W_ERROR_HAVE_NO_MEMORY(msg);
-
-       msg->dn = dn;
-
-       ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el);
-       if (ret != LDB_SUCCESS) {
-               return DNS_ERR(SERVER_FAILURE);
-       }
-
-       el->values = talloc_zero_array(el, struct ldb_val, rec_count);
-       if (rec_count > 0) {
-               W_ERROR_HAVE_NO_MEMORY(el->values);
-       }
+       /* TODO: Autogenerate this somehow */
+       uint32_t dwSerial = 110;
+       return dns_common_replace(dns->samdb, mem_ctx, dn,
+                                 needs_add, dwSerial, records, rec_count);
+}
 
-       for (i = 0; i < rec_count; i++) {
-               static const struct dnsp_DnssrvRpcRecord zero;
-               struct ldb_val *v = &el->values[el->num_values];
-               enum ndr_err_code ndr_err;
+bool dns_authorative_for_zone(struct dns_server *dns,
+                             const char *name)
+{
+       const struct dns_server_zone *z;
+       size_t host_part_len = 0;
 
-               if (memcmp(&records[i], &zero, sizeof(zero)) == 0) {
-                       continue;
-               }
-               ndr_err = ndr_push_struct_blob(v, el->values, &records[i],
-                               (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
-                       return DNS_ERR(SERVER_FAILURE);
-               }
-               el->num_values++;
+       if (name == NULL) {
+               return false;
        }
 
-
-       if (el->num_values == 0) {
-               if (needs_add) {
-                       return WERR_OK;
-               }
-               /* TODO: Delete object? */
+       if (strcmp(name, "") == 0) {
+               return true;
        }
+       for (z = dns->zones; z != NULL; z = z->next) {
+               bool match;
 
-       if (needs_add) {
-               ret = ldb_msg_add_string(msg, "objectClass", "dnsNode");
-               if (ret != LDB_SUCCESS) {
-                       return DNS_ERR(SERVER_FAILURE);
-               }
-
-               ret = ldb_add(dns->samdb, msg);
-               if (ret != LDB_SUCCESS) {
-                       return DNS_ERR(SERVER_FAILURE);
+               match = dns_name_match(z->name, name, &host_part_len);
+               if (match) {
+                       break;
                }
-
-               return WERR_OK;
        }
-
-       ret = ldb_modify(dns->samdb, msg);
-       if (ret != LDB_SUCCESS) {
-               return DNS_ERR(SERVER_FAILURE);
+       if (z == NULL) {
+               return false;
        }
 
-       return WERR_OK;
+       return true;
 }
 
-WERROR dns_name2dn(struct dns_server *dns,
-                  TALLOC_CTX *mem_ctx,
-                  const char *name,
-                  struct ldb_dn **_dn)
+const char *dns_get_authoritative_zone(struct dns_server *dns,
+                                      const char *name)
 {
-       struct ldb_dn *base;
-       struct ldb_dn *dn;
        const struct dns_server_zone *z;
        size_t host_part_len = 0;
 
-       if (name == NULL) {
-               return DNS_ERR(FORMAT_ERROR);
-       }
-
-       /*TODO: Check if 'name' is a valid DNS name */
-
-       if (strcmp(name, "") == 0) {
-               base = ldb_get_default_basedn(dns->samdb);
-               dn = ldb_dn_copy(mem_ctx, base);
-               ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
-               *_dn = dn;
-               return WERR_OK;
-       }
-
        for (z = dns->zones; z != NULL; z = z->next) {
                bool match;
-
                match = dns_name_match(z->name, name, &host_part_len);
                if (match) {
-                       break;
+                       return z->name;
                }
        }
+       return NULL;
+}
 
-       if (z == NULL) {
-               return DNS_ERR(NAME_ERROR);
-       }
+WERROR dns_name2dn(struct dns_server *dns,
+                  TALLOC_CTX *mem_ctx,
+                  const char *name,
+                  struct ldb_dn **dn)
+{
+       return dns_common_name2dn(dns->samdb, dns->zones,
+                                 mem_ctx, name, dn);
+}
+
+WERROR dns_generate_options(struct dns_server *dns,
+                           TALLOC_CTX *mem_ctx,
+                           struct dns_res_rec **options)
+{
+       struct dns_res_rec *o;
 
-       if (host_part_len == 0) {
-               dn = ldb_dn_copy(mem_ctx, z->dn);
-               ldb_dn_add_child_fmt(dn, "DC=@");
-               *_dn = dn;
-               return WERR_OK;
+       o = talloc_zero(mem_ctx, struct dns_res_rec);
+       if (o == NULL) {
+               return WERR_NOMEM;
        }
+       o->name = NULL;
+       o->rr_type = DNS_QTYPE_OPT;
+       /* This is ugly, but RFC2671 wants the payload size in this field */
+       o->rr_class = (enum dns_qclass) dns->max_payload;
+       o->ttl = 0;
+       o->length = 0;
 
-       dn = ldb_dn_copy(mem_ctx, z->dn);
-       ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
-       *_dn = dn;
+       *options = o;
        return WERR_OK;
 }