]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ndr/dns: shift pull_dns_string to ndr_dns_util.c
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 29 Apr 2020 04:16:26 +0000 (16:16 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Thu, 16 Apr 2026 00:54:43 +0000 (00:54 +0000)
This will allow NBT to use the same function (after modifications in
the next commit).

This is post CVE-2020-10745 hardening and optimisation.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14378

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
librpc/ndr/ndr_dns.c
librpc/ndr/ndr_dns_utils.c
librpc/ndr/ndr_dns_utils.h

index 9cc54c1a9727e40feabcf0dc2171bdc6c58cc891..b36927dc599da5c658edb8346832b50fba2698ce 100644 (file)
@@ -35,8 +35,6 @@
 #include "lib/util/util_net.h"
 #include "ndr_dns_utils.h"
 
-/* don't allow an unlimited number of name components */
-#define MAX_COMPONENTS 128
 
 /**
   print a dns string
@@ -48,66 +46,6 @@ _PUBLIC_ void ndr_print_dns_string(struct ndr_print *ndr,
        ndr_print_string(ndr, name, s);
 }
 
-/*
-  pull one component of a dns_string
-*/
-static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
-                                           uint8_t **component,
-                                           uint32_t *offset,
-                                           uint32_t *max_offset)
-{
-       uint8_t len;
-       unsigned int loops = 0;
-       while (loops < 5) {
-               if (*offset >= ndr->data_size) {
-                       return ndr_pull_error(ndr, NDR_ERR_STRING,
-                                       "BAD DNS NAME component, bad offset");
-               }
-               len = ndr->data[*offset];
-               if (len == 0) {
-                       *offset += 1;
-                       *max_offset = MAX(*max_offset, *offset);
-                       *component = NULL;
-                       return NDR_ERR_SUCCESS;
-               }
-               if ((len & 0xC0) == 0xC0) {
-                       /* its a label pointer */
-                       if (1 + *offset >= ndr->data_size) {
-                               return ndr_pull_error(ndr, NDR_ERR_STRING,
-                                               "BAD DNS NAME component, " \
-                                               "bad label offset");
-                       }
-                       *max_offset = MAX(*max_offset, *offset + 2);
-                       *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
-                       *max_offset = MAX(*max_offset, *offset);
-                       loops++;
-                       continue;
-               }
-               if ((len & 0xC0) != 0) {
-                       /* its a reserved length field */
-                       return ndr_pull_error(ndr, NDR_ERR_STRING,
-                                             "BAD DNS NAME component, " \
-                                             "reserved length field: 0x%02"PRIx8,
-                                             (len &0xC));
-               }
-               if (*offset + len + 1 > ndr->data_size) {
-                       return ndr_pull_error(ndr, NDR_ERR_STRING,
-                                             "BAD DNS NAME component, "\
-                                             "length too long");
-               }
-               *component = (uint8_t*)talloc_strndup(ndr,
-                               (const char *)&ndr->data[1 + *offset], len);
-               NDR_ERR_HAVE_NO_MEMORY(*component);
-               *offset += len + 1;
-               *max_offset = MAX(*max_offset, *offset);
-               return NDR_ERR_SUCCESS;
-       }
-
-       /* too many pointers */
-       return ndr_pull_error(ndr, NDR_ERR_STRING,
-                             "BAD DNS NAME component, too many pointers");
-}
-
 /**
   pull a dns_string from the wire
 */
@@ -115,44 +53,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr,
                                               ndr_flags_type ndr_flags,
                                               const char **s)
 {
-       uint32_t offset = ndr->offset;
-       uint32_t max_offset = offset;
-       unsigned num_components;
-       char *name;
-
-       if (!(ndr_flags & NDR_SCALARS)) {
-               return NDR_ERR_SUCCESS;
-       }
-
-       name = talloc_strdup(ndr->current_mem_ctx, "");
-
-       /* break up name into a list of components */
-       for (num_components=0; num_components<MAX_COMPONENTS;
-            num_components++) {
-               uint8_t *component = NULL;
-               NDR_CHECK(ndr_pull_component(ndr, &component, &offset,
-                                            &max_offset));
-               if (component == NULL) break;
-               if (num_components > 0) {
-                       name = talloc_asprintf_append_buffer(name, ".%s",
-                                                            component);
-               } else {
-                       name = talloc_asprintf_append_buffer(name, "%s",
-                                                            component);
-               }
-               NDR_ERR_HAVE_NO_MEMORY(name);
-       }
-       if (num_components == MAX_COMPONENTS) {
-               return ndr_pull_error(ndr, NDR_ERR_STRING,
-                                     "BAD DNS NAME too many components");
-       }
-
-       (*s) = name;
-       ndr->offset = max_offset;
-
-       return NDR_ERR_SUCCESS;
+       return ndr_pull_dns_string_list(ndr,
+                                       ndr_flags,
+                                       s);
 }
 
+
 /**
   push a dns string to the wire
 */
index fe9e060306e4863ae241569c7a1c90021cd844c0..7a38a807e5c0cf321bb7a42b498528b4b87d8081 100644 (file)
@@ -2,6 +2,117 @@
 #include "../librpc/ndr/libndr.h"
 #include "ndr_dns_utils.h"
 
+/* don't allow an unlimited number of name components. The string must be less
+   than 255, with at least one character between dots, so 128 components is
+   plenty.
+ */
+#define MAX_COMPONENTS 128
+
+/*
+  pull one component of a dns_string
+*/
+static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
+                                           uint8_t **component,
+                                           uint32_t *offset,
+                                           uint32_t *max_offset)
+{
+       uint8_t len;
+       unsigned int loops = 0;
+       while (loops < 5) {
+               if (*offset >= ndr->data_size) {
+                       return ndr_pull_error(ndr, NDR_ERR_STRING,
+                                       "BAD DNS NAME component, bad offset");
+               }
+               len = ndr->data[*offset];
+               if (len == 0) {
+                       *offset += 1;
+                       *max_offset = MAX(*max_offset, *offset);
+                       *component = NULL;
+                       return NDR_ERR_SUCCESS;
+               }
+               if ((len & 0xC0) == 0xC0) {
+                       /* its a label pointer */
+                       if (1 + *offset >= ndr->data_size) {
+                               return ndr_pull_error(ndr, NDR_ERR_STRING,
+                                               "BAD DNS NAME component, " \
+                                               "bad label offset");
+                       }
+                       *max_offset = MAX(*max_offset, *offset + 2);
+                       *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
+                       *max_offset = MAX(*max_offset, *offset);
+                       loops++;
+                       continue;
+               }
+               if ((len & 0xC0) != 0) {
+                       /* its a reserved length field */
+                       return ndr_pull_error(ndr, NDR_ERR_STRING,
+                                             "BAD DNS NAME component, " \
+                                             "reserved length field: 0x%02x",
+                                             (len &0xC));
+               }
+               if (*offset + len + 1 > ndr->data_size) {
+                       return ndr_pull_error(ndr, NDR_ERR_STRING,
+                                             "BAD DNS NAME component, "\
+                                             "length too long");
+               }
+               *component = (uint8_t*)talloc_strndup(ndr,
+                               (const char *)&ndr->data[1 + *offset], len);
+               NDR_ERR_HAVE_NO_MEMORY(*component);
+               *offset += len + 1;
+               *max_offset = MAX(*max_offset, *offset);
+               return NDR_ERR_SUCCESS;
+       }
+
+       /* too many pointers */
+       return ndr_pull_error(ndr, NDR_ERR_STRING,
+                             "BAD DNS NAME component, too many pointers");
+}
+
+/**
+  pull a dns_string from the wire
+*/
+enum ndr_err_code ndr_pull_dns_string_list(struct ndr_pull *ndr,
+                                          ndr_flags_type ndr_flags,
+                                          const char **s)
+{
+       uint32_t offset = ndr->offset;
+       uint32_t max_offset = offset;
+       unsigned num_components;
+       char *name;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return NDR_ERR_SUCCESS;
+       }
+
+       name = talloc_strdup(ndr->current_mem_ctx, "");
+
+       /* break up name into a list of components */
+       for (num_components=0; num_components<MAX_COMPONENTS;
+            num_components++) {
+               uint8_t *component = NULL;
+               NDR_CHECK(ndr_pull_component(ndr, &component, &offset,
+                                            &max_offset));
+               if (component == NULL) break;
+               if (num_components > 0) {
+                       name = talloc_asprintf_append_buffer(name, ".%s",
+                                                            component);
+               } else {
+                       name = talloc_asprintf_append_buffer(name, "%s",
+                                                            component);
+               }
+               NDR_ERR_HAVE_NO_MEMORY(name);
+       }
+       if (num_components == MAX_COMPONENTS) {
+               return ndr_pull_error(ndr, NDR_ERR_STRING,
+                                     "BAD DNS NAME too many components");
+       }
+
+       (*s) = name;
+       ndr->offset = max_offset;
+
+       return NDR_ERR_SUCCESS;
+}
+
 
 /**
   push a dns/nbt string list to the wire
index b07496f7458bafe133cb4af4bc143bc7a444f554..f75a628852cae39e883e667b4faf2210696f5fbf 100644 (file)
@@ -1,4 +1,8 @@
 
+enum ndr_err_code ndr_pull_dns_string_list(struct ndr_pull *ndr,
+                                          ndr_flags_type ndr_flags,
+                                          const char **s);
+
 enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
                                           struct ndr_token_list *string_list,
                                           ndr_flags_type ndr_flags,