Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/librpc/ndr/ndr_dnsp.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Manually parsed structures found in DNSP
5
6
   Copyright (C) Andrew Tridgell 2010
7
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#include "includes.h"
23
#include "librpc/gen_ndr/ndr_dnsp.h"
24
25
/*
26
  print a dnsp_name
27
*/
28
_PUBLIC_ void ndr_print_dnsp_name(struct ndr_print *ndr, const char *name,
29
          const char *dns_name)
30
62
{
31
62
  ndr->print(ndr, "%-25s: %s", name, dns_name);
32
62
}
33
34
/*
35
  pull a dnsp_name
36
*/
37
_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_name(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **name)
38
186
{
39
186
  uint8_t len, count, termination;
40
186
  int i;
41
186
  uint32_t total_len, raw_offset;
42
186
  char *ret;
43
44
186
  NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
45
178
  NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &count));
46
47
176
  raw_offset = ndr->offset;
48
49
176
  ret = talloc_strdup(ndr->current_mem_ctx, "");
50
176
  if (!ret) {
51
0
    return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
52
0
  }
53
176
  total_len = 1;
54
55
3.08k
  for (i=0; i<count; i++) {
56
2.96k
    uint8_t sublen, newlen;
57
2.96k
    NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &sublen));
58
2.94k
    newlen = total_len + sublen;
59
2.94k
    if (newlen < total_len) {
60
10
      return ndr_pull_error(ndr, NDR_ERR_RANGE,
61
10
                "Failed to pull dnsp_name");
62
10
    }
63
2.93k
    if (i != count-1) {
64
2.86k
      if (newlen == UINT8_MAX) {
65
1
        return ndr_pull_error(
66
1
          ndr, NDR_ERR_RANGE,
67
1
          "Failed to pull dnsp_name");
68
1
      }
69
2.86k
      newlen++; /* for the '.' */
70
2.86k
    }
71
2.93k
    ret = talloc_realloc(ndr->current_mem_ctx, ret, char, newlen);
72
2.93k
    if (!ret) {
73
0
      return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
74
0
    }
75
2.93k
    NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)&ret[total_len-1], sublen));
76
2.91k
    if (i != count-1) {
77
2.84k
      ret[newlen-2] = '.';
78
2.84k
    }
79
2.91k
    ret[newlen-1] = 0;
80
2.91k
    total_len = newlen;
81
2.91k
  }
82
122
  NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &termination));
83
118
  if (termination != 0) {
84
14
    return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - not NUL terminated");
85
14
  }
86
104
  if (ndr->offset > raw_offset + len) {
87
16
    return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - overrun by %"PRIu32" bytes",
88
16
              ndr->offset - (raw_offset + len));
89
16
  }
90
  /* there could be additional pad bytes */
91
928
  while (ndr->offset < raw_offset + len) {
92
858
    uint8_t pad;
93
858
    NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &pad));
94
858
  }
95
70
  (*name) = ret;
96
70
  return NDR_ERR_SUCCESS;
97
88
}
98
99
enum ndr_err_code ndr_push_dnsp_name(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *name)
100
77
{
101
77
  int count, total_len, i;
102
103
  /* count the dots */
104
2.63k
  for (count=i=0; name[i]; i++) {
105
2.55k
    if (name[i] == '.') count++;
106
2.55k
  }
107
77
  total_len = strlen(name) + 1;
108
109
  /*
110
   * cope with names ending in '.'
111
   */
112
77
  if (name[0] == '\0') {
113
    /*
114
     * Don't access name[-1] for the "" input, which has
115
     * the same meaning as a lone '.'.
116
     *
117
     * This allows a round-trip of a dnsRecord from
118
     * Windows of a MX record of '.'
119
     */
120
58
  } else if (name[strlen(name)-1] != '.') {
121
29
    total_len++;
122
29
    count++;
123
29
  }
124
77
  if (total_len > 255 || count > 255) {
125
0
    return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
126
0
              "dns_name of length %d larger than 255", total_len);
127
0
  }
128
77
  NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
129
77
  NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)count));
130
2.42k
  for (i=0; i<count; i++) {
131
2.35k
    const char *p = strchr(name, '.');
132
2.35k
    size_t sublen = p?(p-name):strlen(name);
133
2.35k
    NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)sublen));
134
2.35k
    NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)name, sublen));
135
2.35k
    name += sublen + 1;
136
2.35k
  }
137
77
  NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, 0));
138
139
77
  return NDR_ERR_SUCCESS;
140
77
}
141
142
/*
143
  print a dnsp_string
144
*/
145
_PUBLIC_ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
146
            const char *dns_string)
147
1.48k
{
148
1.48k
  ndr->print(ndr, "%-25s: %s", name, dns_string);
149
1.48k
}
150
151
/*
152
  pull a dnsp_string
153
*/
154
_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **string)
155
5.92M
{
156
5.92M
  uint8_t len;
157
5.92M
  char *ret;
158
159
5.92M
  NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
160
161
5.92M
  ret = talloc_zero_array(ndr->current_mem_ctx, char, len + 1);
162
5.92M
  if (!ret) {
163
0
    return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string");
164
0
  }
165
5.92M
  NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)ret, len));
166
167
5.92M
  (*string) = ret;
168
5.92M
  NDR_PULL_ALIGN(ndr, 1);
169
5.92M
  return NDR_ERR_SUCCESS;
170
5.92M
}
171
172
enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *string)
173
11.6k
{
174
11.6k
  size_t total_len;
175
11.6k
  total_len = strlen(string);
176
11.6k
  if (total_len > 255) {
177
0
    return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
178
0
              "dns_name of length %zu larger than 255",
179
0
              total_len);
180
0
  }
181
11.6k
  NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
182
11.6k
  NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)string, total_len));
183
184
11.6k
  return NDR_ERR_SUCCESS;
185
11.6k
}
186
187
/*
188
 * print a dnsp_string_list
189
 */
190
_PUBLIC_ void ndr_print_dnsp_string_list(struct ndr_print *ndr, const char *name,
191
           const struct dnsp_string_list *list)
192
1.16k
{
193
1.16k
  uint32_t i;
194
195
1.16k
  ndr->no_newline = true;
196
1.16k
  ndr->print(ndr, "%*.s%-25s:", 4 * ndr->depth, "", name);
197
11.1k
  for (i=0; i<list->count; i++) {
198
9.98k
    ndr->print(ndr, " \"%s\"", list->str[i]);
199
9.98k
  }
200
1.16k
  ndr->print(ndr, "\n");
201
1.16k
  ndr->no_newline = false;
202
1.16k
}
203
204
/*
205
 * pull a dnsp_string_list
206
 */
207
_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string_list(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dnsp_string_list *list)
208
2.29k
{
209
2.29k
  list->count = 0;
210
2.29k
  list->str = talloc_array(ndr->current_mem_ctx, const char *,
211
2.29k
         list->count);
212
2.29k
  if (! list->str) {
213
0
    return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
214
0
  }
215
216
5.92M
  while (ndr->offset < ndr->data_size) {
217
5.92M
    list->str = talloc_realloc(ndr->current_mem_ctx, list->str,
218
5.92M
             const char *, list->count+1);
219
5.92M
    if (! list->str) {
220
0
      return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
221
0
    }
222
5.92M
    NDR_CHECK(ndr_pull_dnsp_string(ndr, ndr_flags, &list->str[list->count]));
223
5.91M
    list->count++;
224
5.91M
  }
225
226
2.17k
  return NDR_ERR_SUCCESS;
227
2.29k
}
228
229
enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dnsp_string_list *list)
230
630
{
231
630
  uint8_t i;
232
233
11.5k
  for (i=0; i<list->count; i++) {
234
10.9k
    NDR_CHECK(ndr_push_dnsp_string(ndr, ndr_flags, list->str[i]));
235
10.9k
  }
236
630
  return NDR_ERR_SUCCESS;
237
630
}
238
239
enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
240
              const struct dnsp_string_list *src,
241
              struct dnsp_string_list *dst)
242
0
{
243
0
  size_t i;
244
245
0
  dst->count = 0;
246
0
  dst->str = talloc_zero_array(mem_ctx, const char *, src->count);
247
0
  if (dst->str == NULL) {
248
0
    return NDR_ERR_ALLOC;
249
0
  }
250
251
0
  for (i = 0; i < src->count; i++) {
252
0
    dst->str[i] = talloc_strdup(dst->str, src->str[i]);
253
0
    if (dst->str[i] == NULL) {
254
0
      TALLOC_FREE(dst->str);
255
0
      return NDR_ERR_ALLOC;
256
0
    }
257
0
  }
258
259
0
  dst->count = src->count;
260
0
  return NDR_ERR_SUCCESS;
261
0
}