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