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 : }
|