2 Unix SMB/CIFS implementation.
4 manipulate nbt name structures
6 Copyright (C) Andrew Tridgell 2005
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 see rfc1002 for the detailed format of compressed names
28 #include "librpc/gen_ndr/ndr_nbt.h"
30 /* don't allow an unlimited number of name components */
31 #define MAX_COMPONENTS 10
34 pull one component of a compressed name
36 static NTSTATUS
ndr_pull_component(struct ndr_pull
*ndr
, uint8_t **component
,
37 uint32_t *offset
, uint32_t *max_offset
)
42 if (*offset
>= ndr
->data_size
) {
43 return NT_STATUS_BAD_NETWORK_NAME
;
45 len
= ndr
->data
[*offset
];
48 *max_offset
= MAX(*max_offset
, *offset
);
52 if ((len
& 0xC0) == 0xC0) {
53 /* its a label pointer */
54 if (1 + *offset
>= ndr
->data_size
) {
55 return NT_STATUS_BAD_NETWORK_NAME
;
57 *offset
= ((len
&0x3F)<<8) | ndr
->data
[1 + *offset
];
58 *max_offset
= MAX(*max_offset
, *offset
+ 1);
62 if ((len
& 0xC0) != 0) {
63 /* its a reserved length field */
64 return NT_STATUS_BAD_NETWORK_NAME
;
66 if (*offset
+ len
+ 2 > ndr
->data_size
) {
67 return NT_STATUS_BAD_NETWORK_NAME
;
69 *component
= (uint8_t*)talloc_strndup(ndr
, &ndr
->data
[1 + *offset
], len
);
70 NT_STATUS_HAVE_NO_MEMORY(*component
);
72 *max_offset
= MAX(*max_offset
, *offset
);
76 /* too many pointers */
77 return NT_STATUS_BAD_NETWORK_NAME
;
81 decompress a 'compressed' name component
83 static NTSTATUS
decompress_name(char *name
, enum nbt_name_type
*type
)
86 for (i
=0;name
[2*i
];i
++) {
87 uint8_t c1
= name
[2*i
];
88 uint8_t c2
= name
[1+(2*i
)];
89 if (c1
< 'A' || c1
> 'P' ||
90 c2
< 'A' || c2
> 'P') {
91 return NT_STATUS_BAD_NETWORK_NAME
;
93 name
[i
] = ((c1
-'A')<<4) | (c2
-'A');
97 *type
= (enum nbt_name_type
)(name
[15]);
101 *type
= NBT_NAME_CLIENT
;
104 /* trim trailing spaces */
105 for (;i
>0 && name
[i
-1]==' ';i
--) {
114 compress a name component
116 static uint8_t *compress_name(TALLOC_CTX
*mem_ctx
,
117 uint8_t *name
, enum nbt_name_type type
)
123 if (strlen(name
) > 15) {
127 cname
= talloc_array(mem_ctx
, uint8_t, 33);
128 if (cname
== NULL
) return NULL
;
130 for (i
=0;name
[i
];i
++) {
131 cname
[2*i
] = 'A' + (name
[i
]>>4);
132 cname
[1+2*i
] = 'A' + (name
[i
]&0xF);
134 if (name
[0] == '*') {
140 cname
[2*i
] = 'A' + (pad_char
>>4);
141 cname
[1+2*i
] = 'A' + (pad_char
&0xF);
145 cname
[2*i
] = 'A' + (pad_char
>>4);
146 cname
[1+2*i
] = 'A' + (pad_char
&0xF);
153 pull a nbt name from the wire
155 NTSTATUS
ndr_pull_nbt_name(struct ndr_pull
*ndr
, int ndr_flags
, struct nbt_name
*r
)
158 uint_t num_components
;
159 uint32_t offset
= ndr
->offset
;
160 uint32_t max_offset
= offset
;
161 uint8_t *components
[MAX_COMPONENTS
];
167 if (!(ndr_flags
& NDR_SCALARS
)) {
171 /* break up name into a list of components */
172 for (num_components
=0;num_components
<MAX_COMPONENTS
;num_components
++) {
173 status
= ndr_pull_component(ndr
, &components
[num_components
],
174 &offset
, &max_offset
);
175 NT_STATUS_NOT_OK_RETURN(status
);
176 if (components
[num_components
] == NULL
) break;
178 if (num_components
== MAX_COMPONENTS
||
179 num_components
== 0) {
180 return NT_STATUS_BAD_NETWORK_NAME
;
183 ndr
->offset
= max_offset
;
185 /* the first component is limited to 16 bytes in the DOS charset,
186 which is 32 in the 'compressed' form */
187 if (strlen(components
[0]) > 32) {
188 return NT_STATUS_BAD_NETWORK_NAME
;
191 /* decompress the first component */
192 status
= decompress_name(components
[0], &r
->type
);
193 NT_STATUS_NOT_OK_RETURN(status
);
195 ret
= convert_string_talloc(ndr
, CH_DOS
, CH_UNIX
, components
[0],
196 strlen(components
[0])+1, &p
);
198 return NT_STATUS_BAD_NETWORK_NAME
;
202 /* combine the remaining components into the scope */
203 scope
= components
[1];
204 for (i
=2;i
<num_components
;i
++) {
205 talloc_asprintf_append(scope
, ".%s", components
[i
]);
209 ret
= convert_string_talloc(ndr
, CH_DOS
, CH_UNIX
, scope
,
210 strlen(r
->scope
)+1, &p
);
212 return NT_STATUS_BAD_NETWORK_NAME
;
223 push a nbt name to the wire
225 NTSTATUS
ndr_push_nbt_name(struct ndr_push
*ndr
, int ndr_flags
, struct nbt_name
*r
)
227 uint_t num_components
;
228 uint8_t *components
[MAX_COMPONENTS
];
230 char *dname
, *dscope
=NULL
, *p
;
235 if (!(ndr_flags
& NDR_SCALARS
)) {
239 /* convert to DOS format */
240 ret
= convert_string_talloc(ndr
, CH_UNIX
, CH_DOS
, r
->name
,
241 strlen(r
->name
)+1, &ptr
);
243 return NT_STATUS_BAD_NETWORK_NAME
;
245 dname
= strupper_talloc(ndr
, ptr
);
246 NT_STATUS_HAVE_NO_MEMORY(dname
);
248 ret
= convert_string_talloc(ndr
, CH_UNIX
, CH_DOS
, r
->scope
,
249 strlen(r
->scope
)+1, &ptr
);
251 return NT_STATUS_BAD_NETWORK_NAME
;
253 dscope
= strupper_talloc(ndr
, ptr
);
254 NT_STATUS_HAVE_NO_MEMORY(dscope
);
257 cname
= compress_name(ndr
, dname
, r
->type
);
258 NT_STATUS_HAVE_NO_MEMORY(cname
);
260 /* form the base components */
261 components
[0] = cname
;
264 while (dscope
&& (p
=strchr(dscope
, '.')) &&
265 num_components
< MAX_COMPONENTS
) {
267 components
[num_components
] = dscope
;
268 NT_STATUS_HAVE_NO_MEMORY(components
[num_components
]);
272 if (num_components
== MAX_COMPONENTS
) {
273 return NT_STATUS_BAD_NETWORK_NAME
;
276 /* push the components */
277 for (i
=0;i
<num_components
;i
++) {
278 uint8_t len
= strlen(components
[i
]);
279 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, len
));
280 NDR_CHECK(ndr_push_bytes(ndr
, components
[i
], len
));
282 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 0));
289 copy a nbt name structure
291 NTSTATUS
nbt_name_dup(TALLOC_CTX
*mem_ctx
, struct nbt_name
*name
, struct nbt_name
*newname
)
294 newname
->name
= talloc_strdup(mem_ctx
, newname
->name
);
295 NT_STATUS_HAVE_NO_MEMORY(newname
->name
);
296 newname
->scope
= talloc_strdup(mem_ctx
, newname
->scope
);
298 NT_STATUS_HAVE_NO_MEMORY(newname
->scope
);
304 push a nbt name into a blob
306 NTSTATUS
nbt_name_to_blob(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*blob
, struct nbt_name
*name
)
308 return ndr_push_struct_blob(blob
, mem_ctx
, name
,
309 (ndr_push_flags_fn_t
)ndr_push_nbt_name
);
314 pull a nbt name from a blob
316 NTSTATUS
nbt_name_from_blob(TALLOC_CTX
*mem_ctx
, const DATA_BLOB
*blob
, struct nbt_name
*name
)
318 return ndr_pull_struct_blob(blob
, mem_ctx
, name
,
319 (ndr_pull_flags_fn_t
)ndr_pull_nbt_name
);
324 choose a name to use when calling a server in a NBT session request.
325 we use heuristics to see if the name we have been given is a IP
326 address, or a too-long name. If it is then use *SMBSERVER, or a
329 void nbt_choose_called_name(TALLOC_CTX
*mem_ctx
,
330 struct nbt_name
*n
, const char *name
, int type
)
335 if (is_ipaddress(name
)) {
336 n
->name
= "*SMBSERVER";
339 if (strlen(name
) > 15) {
340 const char *p
= strchr(name
, '.');
342 n
->name
= "*SMBSERVER";
345 n
->name
= talloc_strndup(mem_ctx
, name
, PTR_DIFF(p
, name
));
349 n
->name
= talloc_strdup(mem_ctx
, name
);