LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_dns_utils.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 44 47 93.6 %
Date: 2024-04-21 15:09:00 Functions: 1 1 100.0 %

          Line data    Source code
       1             : #include "includes.h"
       2             : #include "../librpc/ndr/libndr.h"
       3             : #include "ndr_dns_utils.h"
       4             : 
       5             : 
       6             : /**
       7             :   push a dns/nbt string list to the wire
       8             : */
       9       77380 : enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
      10             :                                            struct ndr_token_list *string_list,
      11             :                                            ndr_flags_type ndr_flags,
      12             :                                            const char *s,
      13             :                                            bool is_nbt)
      14             : {
      15       77380 :         const char *start = s;
      16         449 :         bool use_compression;
      17         449 :         size_t max_length;
      18       77380 :         if (is_nbt) {
      19       37535 :                 use_compression = true;
      20             :                 /*
      21             :                  * Max length is longer in NBT/Wins, because Windows counts
      22             :                  * the semi-decompressed size of the netbios name (16 bytes)
      23             :                  * rather than the wire size of 32, which is what you'd expect
      24             :                  * if it followed RFC1002 (it uses the short form in
      25             :                  * [MS-WINSRA]). In other words the maximum size of the
      26             :                  * "scope" is 237, not 221.
      27             :                  *
      28             :                  * We make the size limit slightly larger than 255 + 16,
      29             :                  * because the 237 scope limit is already enforced in the
      30             :                  * winsserver code with a specific return value; bailing out
      31             :                  * here would muck with that.
      32             :                  */
      33       37535 :                 max_length = 274;
      34             :         } else {
      35       39398 :                 use_compression = !(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION);
      36       39398 :                 max_length = 255;
      37             :         }
      38             : 
      39       77380 :         if (!(ndr_flags & NDR_SCALARS)) {
      40           0 :                 return NDR_ERR_SUCCESS;
      41             :         }
      42             : 
      43      205993 :         while (s && *s) {
      44         818 :                 enum ndr_err_code ndr_err;
      45         818 :                 char *compname;
      46         818 :                 size_t complen;
      47         818 :                 uint32_t offset;
      48             : 
      49      162004 :                 if (use_compression) {
      50             :                         /* see if we have pushed the remaining string already,
      51             :                          * if so we use a label pointer to this string
      52             :                          */
      53      159170 :                         ndr_err = ndr_token_retrieve_cmp_fn(string_list, s,
      54             :                                                             &offset,
      55             :                                                             (comparison_fn_t)strcmp,
      56             :                                                             false);
      57      159170 :                         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      58         155 :                                 uint8_t b[2];
      59             : 
      60       33379 :                                 if (offset > 0x3FFF) {
      61           0 :                                         return ndr_push_error(ndr, NDR_ERR_STRING,
      62             :                                                               "offset for dns string " \
      63             :                                                               "label pointer " \
      64             :                                                               "%"PRIu32"[%08"PRIX32"] > 0x00003FFF",
      65             :                                                               offset, offset);
      66             :                                 }
      67             : 
      68       33379 :                                 b[0] = 0xC0 | (offset>>8);
      69       33379 :                                 b[1] = (offset & 0xFF);
      70             : 
      71       33379 :                                 return ndr_push_bytes(ndr, b, 2);
      72             :                         }
      73             :                 }
      74             : 
      75      128625 :                 complen = strcspn(s, ".");
      76             : 
      77             :                 /* the length must fit into 6 bits (i.e. <= 63) */
      78      128625 :                 if (complen > 0x3F) {
      79           0 :                         return ndr_push_error(ndr, NDR_ERR_STRING,
      80             :                                               "component length %zu[%08zX] > " \
      81             :                                               "0x0000003F",
      82             :                                               complen,
      83             :                                               complen);
      84             :                 }
      85             : 
      86      128625 :                 if (complen == 0 && s[complen] == '.') {
      87           6 :                         return ndr_push_error(ndr, NDR_ERR_STRING,
      88             :                                               "component length is 0 "
      89             :                                               "(consecutive dots)");
      90             :                 }
      91             : 
      92      128619 :                 if (is_nbt && s[complen] == '.' && s[complen + 1] == '\0') {
      93             :                         /* nbt names are sometimes usernames, and we need to
      94             :                          * keep a trailing dot to ensure it is byte-identical,
      95             :                          * (not just semantically identical given DNS
      96             :                          * semantics). */
      97          74 :                         complen++;
      98             :                 }
      99             : 
     100      128619 :                 compname = talloc_asprintf(ndr, "%c%*.*s",
     101      127958 :                                                 (unsigned char)complen,
     102      127958 :                                                 (unsigned char)complen,
     103      127958 :                                                 (unsigned char)complen, s);
     104      128619 :                 NDR_ERR_HAVE_NO_MEMORY(compname);
     105             : 
     106             :                 /* remember the current component + the rest of the string
     107             :                  * so it can be reused later
     108             :                  */
     109      128619 :                 if (use_compression) {
     110      125785 :                         NDR_CHECK(ndr_token_store(ndr, string_list, s,
     111             :                                                   ndr->offset));
     112             :                 }
     113             : 
     114             :                 /* push just this component into the blob */
     115      128619 :                 NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname,
     116             :                                          complen+1));
     117      128619 :                 talloc_free(compname);
     118             : 
     119      128619 :                 s += complen;
     120      128619 :                 if (*s == '.') {
     121       86972 :                         s++;
     122             :                 }
     123      128619 :                 if (s - start > max_length) {
     124           6 :                         return ndr_push_error(ndr, NDR_ERR_STRING,
     125             :                                               "name > %zu characters long",
     126             :                                               max_length);
     127             :                 }
     128             :         }
     129             : 
     130             :         /* if we reach the end of the string and have pushed the last component
     131             :          * without using a label pointer, we need to terminate the string
     132             :          */
     133       43989 :         return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
     134             : }

Generated by: LCOV version 1.14