Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : manipulate nbt name structures
5 :
6 : Copyright (C) Andrew Tridgell 2005
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 : /*
23 : see rfc1002 for the detailed format of compressed names
24 : */
25 :
26 : #include "includes.h"
27 : #include "librpc/gen_ndr/ndr_nbt.h"
28 : #include "librpc/gen_ndr/ndr_misc.h"
29 : #include "system/locale.h"
30 : #include "lib/util/util_net.h"
31 : #include "libcli/nbt/libnbt.h"
32 :
33 : /*
34 : decompress a 'compressed' name component
35 : */
36 21501 : static bool decompress_name(char *name, enum nbt_name_type *type)
37 : {
38 197 : int i;
39 365517 : for (i=0;name[2*i];i++) {
40 344016 : uint8_t c1 = name[2*i];
41 344016 : uint8_t c2 = name[1+(2*i)];
42 344016 : if (c1 < 'A' || c1 > 'P' ||
43 344016 : c2 < 'A' || c2 > 'P') {
44 0 : return false;
45 : }
46 344016 : name[i] = ((c1-'A')<<4) | (c2-'A');
47 : }
48 21501 : name[i] = 0;
49 21501 : if (i == 16) {
50 21501 : *type = (enum nbt_name_type)(name[15]);
51 21501 : name[15] = 0;
52 21501 : i--;
53 : } else {
54 0 : *type = NBT_NAME_CLIENT;
55 : }
56 :
57 : /* trim trailing spaces */
58 141272 : for (;i>0 && name[i-1]==' ';i--) {
59 119771 : name[i-1] = 0;
60 : }
61 :
62 21304 : return true;
63 : }
64 :
65 :
66 : /*
67 : compress a name component
68 : */
69 14884 : static uint8_t *compress_name(TALLOC_CTX *mem_ctx,
70 : const uint8_t *name, enum nbt_name_type type)
71 : {
72 125 : uint8_t *cname;
73 125 : int i;
74 125 : uint8_t pad_char;
75 :
76 14884 : if (strlen((const char *)name) > 15) {
77 0 : return NULL;
78 : }
79 :
80 14884 : cname = talloc_array(mem_ctx, uint8_t, 33);
81 14884 : if (cname == NULL) return NULL;
82 :
83 133241 : for (i=0;name[i];i++) {
84 118357 : cname[2*i] = 'A' + (name[i]>>4);
85 118357 : cname[1+2*i] = 'A' + (name[i]&0xF);
86 : }
87 14884 : if (strcmp((const char *)name, "*") == 0) {
88 133 : pad_char = 0;
89 : } else {
90 14876 : pad_char = ' ';
91 : }
92 119787 : for (;i<15;i++) {
93 104903 : cname[2*i] = 'A' + (pad_char>>4);
94 104903 : cname[1+2*i] = 'A' + (pad_char&0xF);
95 : }
96 :
97 14884 : pad_char = type;
98 14884 : cname[2*i] = 'A' + (pad_char>>4);
99 14884 : cname[1+2*i] = 'A' + (pad_char&0xF);
100 :
101 14884 : cname[32] = 0;
102 14884 : return cname;
103 : }
104 :
105 :
106 : /**
107 : pull a nbt name from the wire
108 : */
109 21501 : _PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct nbt_name *r)
110 : {
111 197 : uint8_t *scope;
112 197 : char *cname;
113 197 : const char *s;
114 197 : bool ok;
115 :
116 21501 : if (!(ndr_flags & NDR_SCALARS)) {
117 0 : return NDR_ERR_SUCCESS;
118 : }
119 :
120 21501 : NDR_CHECK(ndr_pull_nbt_string(ndr, ndr_flags, &s));
121 :
122 21501 : scope = (uint8_t *)strchr(s, '.');
123 21501 : if (scope) {
124 255 : *scope = 0;
125 255 : r->scope = talloc_strdup(ndr->current_mem_ctx, (const char *)&scope[1]);
126 255 : NDR_ERR_HAVE_NO_MEMORY(r->scope);
127 : } else {
128 21246 : r->scope = NULL;
129 : }
130 :
131 21501 : cname = discard_const_p(char, s);
132 :
133 : /* the first component is limited to 16 bytes in the DOS charset,
134 : which is 32 in the 'compressed' form */
135 21501 : if (strlen(cname) > 32) {
136 0 : return ndr_pull_error(ndr, NDR_ERR_STRING,
137 : "NBT NAME cname > 32");
138 : }
139 :
140 : /* decompress the first component */
141 21501 : ok = decompress_name(cname, &r->type);
142 21501 : if (!ok) {
143 0 : return ndr_pull_error(ndr, NDR_ERR_STRING,
144 : "NBT NAME failed to decompress");
145 : }
146 :
147 21501 : r->name = talloc_strdup(ndr->current_mem_ctx, cname);
148 21501 : NDR_ERR_HAVE_NO_MEMORY(r->name);
149 :
150 21501 : talloc_free(cname);
151 :
152 21501 : return NDR_ERR_SUCCESS;
153 : }
154 :
155 : /**
156 : push a nbt name to the wire
157 : */
158 14884 : _PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct nbt_name *r)
159 : {
160 125 : uint8_t *cname, *fullname;
161 125 : enum ndr_err_code ndr_err;
162 :
163 14884 : if (!(ndr_flags & NDR_SCALARS)) {
164 0 : return NDR_ERR_SUCCESS;
165 : }
166 :
167 14884 : if (strlen(r->name) > 15) {
168 0 : return ndr_push_error(ndr, NDR_ERR_STRING,
169 : "nbt_name longer as 15 chars: %s",
170 : r->name);
171 : }
172 :
173 14884 : cname = compress_name(ndr, (const uint8_t *)r->name, r->type);
174 14884 : NDR_ERR_HAVE_NO_MEMORY(cname);
175 :
176 14884 : if (r->scope) {
177 255 : fullname = (uint8_t *)talloc_asprintf(ndr, "%s.%s", cname, r->scope);
178 255 : NDR_ERR_HAVE_NO_MEMORY(fullname);
179 255 : talloc_free(cname);
180 : } else {
181 14504 : fullname = cname;
182 : }
183 :
184 14884 : ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname);
185 :
186 14884 : return ndr_err;
187 : }
188 :
189 :
190 : /**
191 : copy a nbt name structure
192 : */
193 156818 : _PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx,
194 : const struct nbt_name *name,
195 : struct nbt_name *newname)
196 : {
197 156818 : *newname = *name;
198 156818 : newname->name = talloc_strdup(mem_ctx, newname->name);
199 156818 : NT_STATUS_HAVE_NO_MEMORY(newname->name);
200 156818 : newname->scope = talloc_strdup(mem_ctx, newname->scope);
201 156818 : if (name->scope) {
202 33 : NT_STATUS_HAVE_NO_MEMORY(newname->scope);
203 : }
204 156818 : return NT_STATUS_OK;
205 : }
206 :
207 : /**
208 : push a nbt name into a blob
209 : */
210 0 : _PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name)
211 : {
212 0 : enum ndr_err_code ndr_err;
213 :
214 0 : ndr_err = ndr_push_struct_blob(blob, mem_ctx, name, (ndr_push_flags_fn_t)ndr_push_nbt_name);
215 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216 0 : return ndr_map_error2ntstatus(ndr_err);
217 : }
218 :
219 0 : return NT_STATUS_OK;
220 : }
221 :
222 : /**
223 : pull a nbt name from a blob
224 : */
225 12 : _PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name)
226 : {
227 0 : enum ndr_err_code ndr_err;
228 :
229 12 : ndr_err = ndr_pull_struct_blob(blob, mem_ctx, name,
230 : (ndr_pull_flags_fn_t)ndr_pull_nbt_name);
231 12 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
232 0 : return ndr_map_error2ntstatus(ndr_err);
233 : }
234 :
235 12 : return NT_STATUS_OK;
236 : }
237 :
238 :
239 : /**
240 : choose a name to use when calling a server in a NBT session request.
241 : we use heuristics to see if the name we have been given is a IP
242 : address, or a too-long name. If it is then use *SMBSERVER, or a
243 : truncated name
244 : */
245 22379 : _PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx,
246 : struct nbt_name *n, const char *name, int type)
247 : {
248 22379 : n->scope = NULL;
249 22379 : n->type = type;
250 :
251 22379 : if ((name == NULL) || is_ipaddress(name)) {
252 6065 : n->name = "*SMBSERVER";
253 6065 : return;
254 : }
255 16314 : if (strlen(name) > 15) {
256 335 : const char *p = strchr(name, '.');
257 0 : char *s;
258 335 : if (p - name > 15) {
259 0 : n->name = "*SMBSERVER";
260 0 : return;
261 : }
262 335 : s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name));
263 335 : n->name = talloc_strdup_upper(mem_ctx, s);
264 335 : return;
265 : }
266 :
267 15979 : n->name = talloc_strdup_upper(mem_ctx, name);
268 : }
269 :
270 :
271 : /*
272 : escape a string into a form containing only a small set of characters,
273 : the rest is hex encoded. This is similar to URL encoding
274 : */
275 600 : static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s)
276 : {
277 13 : int i, len;
278 13 : char *ret;
279 600 : const char *valid_chars = "_-.$@ ";
280 : #define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c))
281 :
282 7122 : for (len=i=0;s[i];i++,len++) {
283 6522 : if (!NBT_CHAR_ALLOW(s[i])) {
284 10 : len += 2;
285 : }
286 : }
287 :
288 600 : ret = talloc_array(mem_ctx, char, len+1);
289 600 : if (ret == NULL) return NULL;
290 :
291 7122 : for (len=i=0;s[i];i++) {
292 6522 : if (NBT_CHAR_ALLOW(s[i])) {
293 6512 : ret[len++] = s[i];
294 : } else {
295 10 : snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]);
296 10 : len += 3;
297 : }
298 : }
299 600 : ret[len] = 0;
300 :
301 600 : return ret;
302 : }
303 :
304 :
305 : /**
306 : form a string for a NBT name
307 : */
308 580 : _PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name)
309 : {
310 580 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
311 13 : char *ret;
312 580 : if (name->scope) {
313 20 : ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s",
314 20 : nbt_hex_encode(tmp_ctx, name->name),
315 20 : name->type,
316 20 : nbt_hex_encode(tmp_ctx, name->scope));
317 : } else {
318 560 : ret = talloc_asprintf(mem_ctx, "%s<%02x>",
319 560 : nbt_hex_encode(tmp_ctx, name->name),
320 560 : name->type);
321 : }
322 580 : talloc_free(tmp_ctx);
323 580 : return ret;
324 : }
325 :
326 : /**
327 : pull a nbt name, WINS Replication uses another on wire format for nbt name
328 : */
329 1202 : _PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct nbt_name **_r)
330 : {
331 0 : struct nbt_name *r;
332 0 : uint8_t *namebuf;
333 0 : uint32_t namebuf_len;
334 :
335 1202 : if (!(ndr_flags & NDR_SCALARS)) {
336 0 : return NDR_ERR_SUCCESS;
337 : }
338 :
339 1202 : NDR_CHECK(ndr_pull_align(ndr, 4));
340 1202 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len));
341 1202 : if (namebuf_len < 1 || namebuf_len > 255) {
342 0 : return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value (%"PRIu32") out of range (1 - 255)", namebuf_len);
343 : }
344 1202 : NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len);
345 1202 : NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
346 :
347 1202 : if ((namebuf_len % 4) == 0) {
348 : /*
349 : * [MS-WINSRA] — v20091104 was wrong
350 : * regarding section "2.2.10.1 Name Record"
351 : *
352 : * If the name buffer is already 4 byte aligned
353 : * Windows (at least 2003 SP1 and 2008) add 4 extra
354 : * bytes. This can happen when the name has a scope.
355 : */
356 0 : uint32_t pad;
357 46 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &pad));
358 : }
359 :
360 1202 : NDR_PULL_ALLOC(ndr, r);
361 :
362 : /* oh wow, what a nasty bug in windows ... */
363 1202 : if (namebuf[0] == 0x1b && namebuf_len >= 16) {
364 0 : namebuf[0] = namebuf[15];
365 0 : namebuf[15] = 0x1b;
366 : }
367 :
368 1202 : if (namebuf_len < 17) {
369 0 : r->type = 0x00;
370 :
371 0 : r->name = talloc_strndup(r, (char *)namebuf, namebuf_len);
372 0 : if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
373 :
374 0 : r->scope= NULL;
375 :
376 0 : talloc_free(namebuf);
377 0 : *_r = r;
378 0 : return NDR_ERR_SUCCESS;
379 : }
380 :
381 1202 : r->type = namebuf[15];
382 :
383 1202 : namebuf[15] = '\0';
384 1202 : trim_string((char *)namebuf, NULL, " ");
385 1202 : r->name = talloc_strdup(r, (char *)namebuf);
386 1202 : if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
387 :
388 1202 : if (namebuf_len > 17) {
389 253 : r->scope = talloc_strndup(r, (char *)(namebuf+16), namebuf_len-17);
390 253 : if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
391 : } else {
392 949 : r->scope = NULL;
393 : }
394 :
395 1202 : talloc_free(namebuf);
396 1202 : *_r = r;
397 1202 : return NDR_ERR_SUCCESS;
398 : }
399 :
400 : /**
401 : push a nbt name, WINS Replication uses another on wire format for nbt name
402 : */
403 2404 : _PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct nbt_name *r)
404 : {
405 0 : uint8_t *namebuf;
406 0 : uint32_t namebuf_len;
407 0 : uint32_t _name_len;
408 2404 : uint32_t scope_len = 0;
409 :
410 2404 : if (r == NULL) {
411 0 : return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER,
412 : "wrepl_nbt_name NULL pointer");
413 : }
414 :
415 2404 : if (!(ndr_flags & NDR_SCALARS)) {
416 0 : return NDR_ERR_SUCCESS;
417 : }
418 :
419 2404 : _name_len = strlen(r->name);
420 2404 : if (_name_len > 15) {
421 0 : return ndr_push_error(ndr, NDR_ERR_STRING,
422 : "wrepl_nbt_name longer as 15 chars: %s",
423 : r->name);
424 : }
425 :
426 2404 : if (r->scope) {
427 506 : scope_len = strlen(r->scope);
428 : }
429 2404 : if (scope_len > 238) {
430 0 : return ndr_push_error(ndr, NDR_ERR_STRING,
431 : "wrepl_nbt_name scope longer as 238 chars: %s",
432 : r->scope);
433 : }
434 :
435 2404 : namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s",
436 2404 : r->name, 'X',
437 2404 : (r->scope?r->scope:""));
438 2404 : if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory");
439 :
440 2404 : namebuf_len = strlen((char *)namebuf) + 1;
441 :
442 : /*
443 : * we need to set the type here, and use a place-holder in the talloc_asprintf()
444 : * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results
445 : */
446 2404 : namebuf[15] = r->type;
447 :
448 : /* oh wow, what a nasty bug in windows ... */
449 2404 : if (r->type == 0x1b) {
450 0 : namebuf[15] = namebuf[0];
451 0 : namebuf[0] = 0x1b;
452 : }
453 :
454 2404 : NDR_CHECK(ndr_push_align(ndr, 4));
455 2404 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len));
456 2404 : NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
457 :
458 2404 : if ((namebuf_len % 4) == 0) {
459 : /*
460 : * [MS-WINSRA] — v20091104 was wrong
461 : * regarding section "2.2.10.1 Name Record"
462 : *
463 : * If the name buffer is already 4 byte aligned
464 : * Windows (at least 2003 SP1 and 2008) add 4 extra
465 : * bytes. This can happen when the name has a scope.
466 : */
467 92 : NDR_CHECK(ndr_push_zero(ndr, 4));
468 : }
469 :
470 2404 : talloc_free(namebuf);
471 2404 : return NDR_ERR_SUCCESS;
472 : }
473 :
474 0 : _PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r)
475 : {
476 0 : char *s = nbt_name_string(ndr, r);
477 0 : ndr_print_string(ndr, name, s);
478 0 : talloc_free(s);
479 0 : }
480 :
481 14645 : _PUBLIC_ enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, ndr_flags_type ndr_flags, enum nbt_qtype r)
482 : {
483 : /* For WACK replies, we need to send NBT_QTYPE_NETBIOS on the wire. */
484 14770 : NDR_CHECK(ndr_push_enum_uint16(ndr, NDR_SCALARS, (r == NBT_QTYPE_WACK) ? NBT_QTYPE_NETBIOS : r));
485 14520 : return NDR_ERR_SUCCESS;
486 : }
|