Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : NBT netbios library routines
4 : Copyright (C) Andrew Tridgell 1994-1998
5 : Copyright (C) Jeremy Allison 2007
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 :
20 : */
21 :
22 : #include "includes.h"
23 : #include "libsmb/nmblib.h"
24 : #include "lib/util/string_wrappers.h"
25 :
26 : static const struct opcode_names {
27 : const char *nmb_opcode_name;
28 : int opcode;
29 : } nmb_header_opcode_names[] = {
30 : {"Query", 0 },
31 : {"Registration", 5 },
32 : {"Release", 6 },
33 : {"WACK", 7 },
34 : {"Refresh", 8 },
35 : {"Refresh(altcode)", 9 },
36 : {"Multi-homed Registration", 15 },
37 : {0, -1 }
38 : };
39 :
40 : /****************************************************************************
41 : Lookup a nmb opcode name.
42 : ****************************************************************************/
43 :
44 0 : static const char *lookup_opcode_name( int opcode )
45 : {
46 : const struct opcode_names *op_namep;
47 : int i;
48 :
49 0 : for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
50 0 : op_namep = &nmb_header_opcode_names[i];
51 0 : if(opcode == op_namep->opcode)
52 0 : return op_namep->nmb_opcode_name;
53 : }
54 0 : return "<unknown opcode>";
55 : }
56 :
57 : /****************************************************************************
58 : Print out a res_rec structure.
59 : ****************************************************************************/
60 :
61 1850 : static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
62 : {
63 : int i, j;
64 :
65 1850 : DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
66 : hdr,
67 : nmb_namestr(&res->rr_name),
68 : res->rr_type,
69 : res->rr_class,
70 : res->ttl ) );
71 :
72 1850 : if (res->rdlength == 0) {
73 0 : return;
74 : }
75 :
76 3850 : for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
77 2000 : DEBUGADD(4, (" %s %3x char ", hdr, i));
78 :
79 15572 : for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
80 15422 : unsigned char x = res->rdata[i+j];
81 15422 : if (x < 32 || x > 127)
82 9286 : x = '.';
83 :
84 15422 : if (i+j >= res->rdlength)
85 1850 : break;
86 13572 : DEBUGADD(4, ("%c", x));
87 : }
88 :
89 2000 : DEBUGADD(4, (" hex "));
90 :
91 15572 : for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
92 15422 : if (i+j >= res->rdlength)
93 1850 : break;
94 13572 : DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
95 : }
96 :
97 2000 : DEBUGADD(4, ("\n"));
98 : }
99 : }
100 :
101 : /****************************************************************************
102 : Process a nmb packet.
103 : ****************************************************************************/
104 :
105 3130 : void debug_nmb_packet(struct packet_struct *p)
106 : {
107 3130 : struct nmb_packet *nmb = &p->packet.nmb;
108 :
109 3130 : if( DEBUGLVL( 4 ) ) {
110 0 : dbgtext( "nmb packet from %s(%d) header: id=%d "
111 : "opcode=%s(%d) response=%s\n",
112 : inet_ntoa(p->ip), p->port,
113 : nmb->header.name_trn_id,
114 : lookup_opcode_name(nmb->header.opcode),
115 : nmb->header.opcode,
116 0 : BOOLSTR(nmb->header.response) );
117 0 : dbgtext( " header: flags: bcast=%s rec_avail=%s "
118 : "rec_des=%s trunc=%s auth=%s\n",
119 0 : BOOLSTR(nmb->header.nm_flags.bcast),
120 0 : BOOLSTR(nmb->header.nm_flags.recursion_available),
121 0 : BOOLSTR(nmb->header.nm_flags.recursion_desired),
122 0 : BOOLSTR(nmb->header.nm_flags.trunc),
123 0 : BOOLSTR(nmb->header.nm_flags.authoritative) );
124 0 : dbgtext( " header: rcode=%d qdcount=%d ancount=%d "
125 : "nscount=%d arcount=%d\n",
126 : nmb->header.rcode,
127 : nmb->header.qdcount,
128 : nmb->header.ancount,
129 : nmb->header.nscount,
130 : nmb->header.arcount );
131 : }
132 :
133 3130 : if (nmb->header.qdcount) {
134 2705 : DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
135 : nmb_namestr(&nmb->question.question_name),
136 : nmb->question.question_type,
137 : nmb->question.question_class) );
138 : }
139 :
140 3130 : if (nmb->answers && nmb->header.ancount) {
141 425 : debug_nmb_res_rec(nmb->answers,"answers");
142 : }
143 3130 : if (nmb->nsrecs && nmb->header.nscount) {
144 0 : debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
145 : }
146 3130 : if (nmb->additional && nmb->header.arcount) {
147 1425 : debug_nmb_res_rec(nmb->additional,"additional");
148 : }
149 3130 : }
150 :
151 : /*******************************************************************
152 : Handle "compressed" name pointers.
153 : ******************************************************************/
154 :
155 6452 : static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
156 : bool *got_pointer,int *ret)
157 : {
158 6452 : int loop_count=0;
159 :
160 12498 : while ((ubuf[*offset] & 0xC0) == 0xC0) {
161 1962 : if (!*got_pointer)
162 1962 : (*ret) += 2;
163 1962 : (*got_pointer)=True;
164 1962 : if (*offset > length - 2) {
165 0 : return False;
166 : }
167 1962 : (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
168 3221 : if (loop_count++ == 10 ||
169 3221 : (*offset) < 0 || (*offset)>(length-2)) {
170 0 : return False;
171 : }
172 : }
173 6452 : return True;
174 : }
175 :
176 : /*******************************************************************
177 : Parse a nmb name from "compressed" format to something readable
178 : return the space taken by the name, or 0 if the name is invalid
179 : ******************************************************************/
180 :
181 6452 : static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
182 : {
183 6452 : size_t m,n=0;
184 6452 : unsigned char *ubuf = (unsigned char *)inbuf;
185 6452 : int ret = 0;
186 6452 : bool got_pointer=False;
187 6452 : size_t loop_count=0;
188 6452 : int offset = ofs;
189 :
190 6452 : if (length - offset < 2)
191 0 : return(0);
192 :
193 : /* handle initial name pointers */
194 6452 : if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
195 0 : return(0);
196 :
197 6452 : m = ubuf[offset];
198 :
199 : /* m must be 32 to exactly fill in the 16 bytes of the netbios name */
200 6452 : if (m != 32) {
201 0 : return 0;
202 : }
203 : /* Cannot go past length. */
204 6452 : if (offset+m+2 > length) {
205 0 : return 0;
206 : }
207 :
208 6452 : memset((char *)name,'\0',sizeof(*name));
209 :
210 : /* the "compressed" part */
211 6452 : if (!got_pointer)
212 4490 : ret += m + 2;
213 6452 : offset++;
214 113768 : while (m > 0) {
215 : unsigned char c1,c2;
216 103232 : c1 = ubuf[offset++]-'A';
217 103232 : c2 = ubuf[offset++]-'A';
218 103232 : if ((c1 & 0xF0) || (c2 & 0xF0)) {
219 0 : return(0);
220 : }
221 103232 : if (n >= sizeof(name->name)) {
222 0 : return 0;
223 : }
224 103232 : name->name[n++] = (c1<<4) | c2;
225 103232 : m -= 2;
226 : }
227 : /*
228 : * RFC1002: For a valid NetBIOS name, exiting from the above,
229 : * n *must* be MAX_NETBIOSNAME_LEN (16).
230 : */
231 6452 : if (n != MAX_NETBIOSNAME_LEN) {
232 0 : return 0;
233 : }
234 :
235 : /* parse out the name type, its always
236 : * in the 16th byte of the name */
237 6452 : name->name_type = ((unsigned char)name->name[15]) & 0xff;
238 :
239 : /* remove trailing spaces */
240 6452 : name->name[15] = 0;
241 6452 : n = 14;
242 40598 : while (n && name->name[n]==' ')
243 30062 : name->name[n--] = 0;
244 :
245 : /* now the domain parts (if any) */
246 6452 : n = 0;
247 10536 : while (ubuf[offset]) {
248 : /* we can have pointers within the domain part as well */
249 0 : if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
250 0 : return(0);
251 :
252 0 : m = ubuf[offset];
253 : /*
254 : * Don't allow null domain parts.
255 : */
256 0 : if (!m)
257 0 : return(0);
258 0 : if (!got_pointer)
259 0 : ret += m+1;
260 0 : if (n)
261 0 : name->scope[n++] = '.';
262 0 : if (m+2+offset>length || n+m+1>sizeof(name->scope))
263 0 : return(0);
264 0 : offset++;
265 0 : while (m--)
266 0 : name->scope[n++] = (char)ubuf[offset++];
267 :
268 : /*
269 : * Watch for malicious loops.
270 : */
271 0 : if (loop_count++ == 10)
272 0 : return 0;
273 : }
274 6452 : name->scope[n++] = 0;
275 :
276 6452 : return(ret);
277 : }
278 :
279 : /****************************************************************************
280 : Put a netbios name, padding(s) and a name type into a 16 character buffer.
281 : name is already in DOS charset.
282 : [15 bytes name + padding][1 byte name type].
283 : ****************************************************************************/
284 :
285 3686 : void put_name(char *dest, const char *name, int pad, unsigned int name_type)
286 : {
287 3686 : size_t len = strlen(name);
288 :
289 3686 : memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ?
290 : len : MAX_NETBIOSNAME_LEN - 1);
291 3686 : if (len < MAX_NETBIOSNAME_LEN - 1) {
292 3510 : memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
293 : }
294 3686 : dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
295 3686 : }
296 :
297 : /*******************************************************************
298 : Put a compressed nmb name into a buffer. Return the length of the
299 : compressed name.
300 :
301 : Compressed names are really weird. The "compression" doubles the
302 : size. The idea is that it also means that compressed names conform
303 : to the doman name system. See RFC1002.
304 :
305 : If buf == NULL this is a length calculation.
306 : ******************************************************************/
307 :
308 2916 : static int put_nmb_name(char *buf, size_t buflen, int offset,struct nmb_name *name)
309 : {
310 : int ret,m;
311 : nstring buf1;
312 : char *p;
313 :
314 2916 : if (strcmp(name->name,"*") == 0) {
315 : /* special case for wildcard name */
316 14 : put_name(buf1, "*", '\0', name->name_type);
317 : } else {
318 2902 : put_name(buf1, name->name, ' ', name->name_type);
319 : }
320 :
321 2916 : if (buf) {
322 1677 : if (offset >= buflen) {
323 0 : return 0;
324 : }
325 1677 : buf[offset] = 0x20;
326 : }
327 :
328 2916 : ret = 34;
329 :
330 49572 : for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
331 46656 : if (buf) {
332 26832 : if (offset+2+2*m >= buflen) {
333 0 : return 0;
334 : }
335 26832 : buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
336 26832 : buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
337 : }
338 : }
339 2916 : offset += 33;
340 :
341 2916 : if (buf) {
342 1677 : if (offset >= buflen) {
343 0 : return 0;
344 : }
345 1677 : buf[offset] = 0;
346 : }
347 :
348 2916 : if (name->scope[0]) {
349 : /* XXXX this scope handling needs testing */
350 0 : size_t scopenamelen = strlen(name->scope) + 1;
351 0 : ret += scopenamelen;
352 0 : if (buf) {
353 0 : if (offset+1+scopenamelen >= buflen) {
354 0 : return 0;
355 : }
356 0 : strlcpy(&buf[offset+1],name->scope,
357 0 : buflen - (offset+1));
358 :
359 0 : p = &buf[offset+1];
360 0 : while ((p = strchr_m(p,'.'))) {
361 0 : buf[offset] = PTR_DIFF(p,&buf[offset+1]);
362 0 : offset += (buf[offset] + 1);
363 0 : if (offset+1 >= buflen) {
364 0 : return 0;
365 : }
366 0 : p = &buf[offset+1];
367 : }
368 0 : buf[offset] = strlen(&buf[offset+1]);
369 : }
370 : }
371 :
372 2916 : return ret;
373 : }
374 :
375 : /*******************************************************************
376 : Useful for debugging messages.
377 : ******************************************************************/
378 :
379 66 : char *nmb_namestr(const struct nmb_name *n)
380 : {
381 : fstring name;
382 : char *result;
383 :
384 66 : pull_ascii_fstring(name, n->name);
385 66 : if (!n->scope[0])
386 66 : result = talloc_asprintf(talloc_tos(), "%s<%02x>", name,
387 0 : n->name_type);
388 : else
389 0 : result = talloc_asprintf(talloc_tos(), "%s<%02x>.%s", name,
390 0 : n->name_type, n->scope);
391 :
392 66 : SMB_ASSERT(result != NULL);
393 66 : return result;
394 : }
395 :
396 : /*******************************************************************
397 : Allocate and parse some resource records.
398 : ******************************************************************/
399 :
400 2121 : static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
401 : struct res_rec **recs, int count)
402 : {
403 : int i;
404 :
405 2121 : *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
406 2121 : if (!*recs)
407 0 : return(False);
408 :
409 2121 : memset((char *)*recs,'\0',sizeof(**recs)*count);
410 :
411 4242 : for (i=0;i<count;i++) {
412 2121 : int l = parse_nmb_name(inbuf,*offset,length,
413 2121 : &(*recs)[i].rr_name);
414 2121 : (*offset) += l;
415 2121 : if (!l || (*offset)+10 > length) {
416 0 : SAFE_FREE(*recs);
417 0 : return(False);
418 : }
419 2121 : (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
420 2121 : (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
421 2121 : (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
422 2121 : (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
423 2121 : (*offset) += 10;
424 3480 : if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
425 2121 : (*offset)+(*recs)[i].rdlength > length) {
426 0 : SAFE_FREE(*recs);
427 0 : return(False);
428 : }
429 2121 : memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
430 2121 : (*offset) += (*recs)[i].rdlength;
431 : }
432 2121 : return(True);
433 : }
434 :
435 : /*******************************************************************
436 : Put a resource record into a packet.
437 : If buf == NULL this is a length calculation.
438 : ******************************************************************/
439 :
440 532 : static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
441 : {
442 532 : int ret=0;
443 : int i;
444 :
445 1064 : for (i=0;i<count;i++) {
446 532 : int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
447 532 : offset += l;
448 532 : ret += l;
449 532 : if (buf) {
450 266 : RSSVAL(buf,offset,recs[i].rr_type);
451 266 : RSSVAL(buf,offset+2,recs[i].rr_class);
452 266 : RSIVAL(buf,offset+4,(unsigned int)recs[i].ttl);
453 266 : RSSVAL(buf,offset+8,recs[i].rdlength);
454 266 : memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
455 : }
456 532 : offset += 10+recs[i].rdlength;
457 532 : ret += 10+recs[i].rdlength;
458 : }
459 :
460 532 : return ret;
461 : }
462 :
463 : /*******************************************************************
464 : Put a compressed name pointer record into a packet.
465 : If buf == NULL this is a length calculation.
466 : ******************************************************************/
467 :
468 1248 : static int put_compressed_name_ptr(unsigned char *buf,
469 : int offset,
470 : struct res_rec *rec,
471 : int ptr_offset)
472 : {
473 1248 : int ret=offset;
474 1248 : if (buf) {
475 624 : buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
476 624 : buf[offset+1] = (ptr_offset & 0xFF);
477 : }
478 1248 : offset += 2;
479 1248 : if (buf) {
480 624 : RSSVAL(buf,offset,rec->rr_type);
481 624 : RSSVAL(buf,offset+2,rec->rr_class);
482 624 : RSIVAL(buf,offset+4,rec->ttl);
483 624 : RSSVAL(buf,offset+8,rec->rdlength);
484 624 : memcpy(buf+offset+10,rec->rdata,rec->rdlength);
485 : }
486 1248 : offset += 10+rec->rdlength;
487 1248 : ret = (offset - ret);
488 :
489 1248 : return ret;
490 : }
491 :
492 : /*******************************************************************
493 : Parse a dgram packet. Return False if the packet can't be parsed
494 : or is invalid for some reason, True otherwise.
495 :
496 : This is documented in section 4.4.1 of RFC1002.
497 : ******************************************************************/
498 :
499 517 : static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
500 : {
501 : size_t offset;
502 : int flags;
503 :
504 517 : memset((char *)dgram,'\0',sizeof(*dgram));
505 :
506 517 : if (length < 14)
507 0 : return(False);
508 :
509 517 : dgram->header.msg_type = CVAL(inbuf,0);
510 517 : flags = CVAL(inbuf,1);
511 517 : dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
512 517 : if (flags & 1)
513 0 : dgram->header.flags.more = True;
514 517 : if (flags & 2)
515 517 : dgram->header.flags.first = True;
516 517 : dgram->header.dgm_id = RSVAL(inbuf,2);
517 517 : putip((char *)&dgram->header.source_ip,inbuf+4);
518 517 : dgram->header.source_port = RSVAL(inbuf,8);
519 517 : dgram->header.dgm_length = RSVAL(inbuf,10);
520 517 : dgram->header.packet_offset = RSVAL(inbuf,12);
521 :
522 517 : offset = 14;
523 :
524 837 : if (dgram->header.msg_type == 0x10 ||
525 514 : dgram->header.msg_type == 0x11 ||
526 0 : dgram->header.msg_type == 0x12) {
527 517 : offset += parse_nmb_name(inbuf,offset,length,
528 : &dgram->source_name);
529 517 : offset += parse_nmb_name(inbuf,offset,length,
530 : &dgram->dest_name);
531 : }
532 :
533 517 : if (offset >= length || (length-offset > sizeof(dgram->data)))
534 0 : return(False);
535 :
536 517 : dgram->datasize = length-offset;
537 517 : memcpy(dgram->data,inbuf+offset,dgram->datasize);
538 :
539 : /* Paranioa. Ensure the last 2 bytes in the dgram buffer are
540 : zero. This should be true anyway, just enforce it for
541 : paranioa sake. JRA. */
542 517 : SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
543 517 : memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
544 :
545 517 : return(True);
546 : }
547 :
548 : /*******************************************************************
549 : Parse a nmb packet. Return False if the packet can't be parsed
550 : or is invalid for some reason, True otherwise.
551 : ******************************************************************/
552 :
553 3456 : static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
554 : {
555 : int nm_flags,offset;
556 :
557 3456 : memset((char *)nmb,'\0',sizeof(*nmb));
558 :
559 3456 : if (length < 12)
560 0 : return(False);
561 :
562 : /* parse the header */
563 3456 : nmb->header.name_trn_id = RSVAL(inbuf,0);
564 :
565 3456 : DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
566 :
567 3456 : nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
568 3456 : nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
569 3456 : nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
570 3456 : nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
571 3456 : nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
572 3456 : nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
573 3456 : nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
574 3456 : nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
575 3456 : nmb->header.rcode = CVAL(inbuf,3) & 0xF;
576 3456 : nmb->header.qdcount = RSVAL(inbuf,4);
577 3456 : nmb->header.ancount = RSVAL(inbuf,6);
578 3456 : nmb->header.nscount = RSVAL(inbuf,8);
579 3456 : nmb->header.arcount = RSVAL(inbuf,10);
580 :
581 3456 : if (nmb->header.qdcount) {
582 3297 : offset = parse_nmb_name(inbuf,12,length,
583 : &nmb->question.question_name);
584 3297 : if (!offset)
585 0 : return(False);
586 :
587 3297 : if (length - (12+offset) < 4)
588 0 : return(False);
589 3297 : nmb->question.question_type = RSVAL(inbuf,12+offset);
590 3297 : nmb->question.question_class = RSVAL(inbuf,12+offset+2);
591 :
592 3297 : offset += 12+4;
593 : } else {
594 159 : offset = 12;
595 : }
596 :
597 : /* and any resource records */
598 3556 : if (nmb->header.ancount &&
599 159 : !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
600 : nmb->header.ancount))
601 0 : return(False);
602 :
603 3456 : if (nmb->header.nscount &&
604 0 : !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
605 : nmb->header.nscount))
606 0 : return(False);
607 :
608 4715 : if (nmb->header.arcount &&
609 1962 : !parse_alloc_res_rec(inbuf,&offset,length,
610 : &nmb->additional, nmb->header.arcount))
611 0 : return(False);
612 :
613 3456 : return(True);
614 : }
615 :
616 : /*******************************************************************
617 : 'Copy constructor' for an nmb packet.
618 : ******************************************************************/
619 :
620 0 : static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
621 : {
622 : struct nmb_packet *nmb;
623 : struct nmb_packet *copy_nmb;
624 : struct packet_struct *pkt_copy;
625 :
626 0 : if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
627 0 : DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
628 0 : return NULL;
629 : }
630 :
631 : /* Structure copy of entire thing. */
632 :
633 0 : *pkt_copy = *packet;
634 :
635 : /* Ensure this copy is not locked. */
636 0 : pkt_copy->locked = False;
637 0 : pkt_copy->recv_fd = -1;
638 0 : pkt_copy->send_fd = -1;
639 :
640 : /* Ensure this copy has no resource records. */
641 0 : nmb = &packet->packet.nmb;
642 0 : copy_nmb = &pkt_copy->packet.nmb;
643 :
644 0 : copy_nmb->answers = NULL;
645 0 : copy_nmb->nsrecs = NULL;
646 0 : copy_nmb->additional = NULL;
647 :
648 : /* Now copy any resource records. */
649 :
650 0 : if (nmb->answers) {
651 0 : if((copy_nmb->answers = SMB_MALLOC_ARRAY(
652 : struct res_rec,nmb->header.ancount)) == NULL)
653 0 : goto free_and_exit;
654 0 : memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
655 0 : nmb->header.ancount * sizeof(struct res_rec));
656 : }
657 0 : if (nmb->nsrecs) {
658 0 : if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(
659 : struct res_rec, nmb->header.nscount)) == NULL)
660 0 : goto free_and_exit;
661 0 : memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
662 0 : nmb->header.nscount * sizeof(struct res_rec));
663 : }
664 0 : if (nmb->additional) {
665 0 : if((copy_nmb->additional = SMB_MALLOC_ARRAY(
666 : struct res_rec, nmb->header.arcount)) == NULL)
667 0 : goto free_and_exit;
668 0 : memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
669 0 : nmb->header.arcount * sizeof(struct res_rec));
670 : }
671 :
672 0 : return pkt_copy;
673 :
674 0 : free_and_exit:
675 :
676 0 : SAFE_FREE(copy_nmb->answers);
677 0 : SAFE_FREE(copy_nmb->nsrecs);
678 0 : SAFE_FREE(copy_nmb->additional);
679 0 : SAFE_FREE(pkt_copy);
680 :
681 0 : DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
682 0 : return NULL;
683 : }
684 :
685 : /*******************************************************************
686 : 'Copy constructor' for a dgram packet.
687 : ******************************************************************/
688 :
689 0 : static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
690 : {
691 : struct packet_struct *pkt_copy;
692 :
693 0 : if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
694 0 : DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
695 0 : return NULL;
696 : }
697 :
698 : /* Structure copy of entire thing. */
699 :
700 0 : *pkt_copy = *packet;
701 :
702 : /* Ensure this copy is not locked. */
703 0 : pkt_copy->locked = False;
704 0 : pkt_copy->recv_fd = -1;
705 0 : pkt_copy->send_fd = -1;
706 :
707 : /* There are no additional pointers in a dgram packet,
708 : we are finished. */
709 0 : return pkt_copy;
710 : }
711 :
712 : /*******************************************************************
713 : 'Copy constructor' for a generic packet.
714 : ******************************************************************/
715 :
716 0 : struct packet_struct *copy_packet(struct packet_struct *packet)
717 : {
718 0 : if(packet->packet_type == NMB_PACKET)
719 0 : return copy_nmb_packet(packet);
720 0 : else if (packet->packet_type == DGRAM_PACKET)
721 0 : return copy_dgram_packet(packet);
722 0 : return NULL;
723 : }
724 :
725 : /*******************************************************************
726 : Free up any resources associated with an nmb packet.
727 : ******************************************************************/
728 :
729 3637 : static void free_nmb_packet(struct nmb_packet *nmb)
730 : {
731 3637 : SAFE_FREE(nmb->answers);
732 3637 : SAFE_FREE(nmb->nsrecs);
733 3637 : SAFE_FREE(nmb->additional);
734 3637 : }
735 :
736 : /*******************************************************************
737 : Free up any resources associated with a dgram packet.
738 : ******************************************************************/
739 :
740 517 : static void free_dgram_packet(struct dgram_packet *nmb)
741 : {
742 : /* We have nothing to do for a dgram packet. */
743 517 : }
744 :
745 : /*******************************************************************
746 : Free up any resources associated with a packet.
747 : ******************************************************************/
748 :
749 4154 : void free_packet(struct packet_struct *packet)
750 : {
751 4154 : if (packet->locked)
752 0 : return;
753 4154 : if (packet->packet_type == NMB_PACKET)
754 3637 : free_nmb_packet(&packet->packet.nmb);
755 517 : else if (packet->packet_type == DGRAM_PACKET)
756 517 : free_dgram_packet(&packet->packet.dgram);
757 4154 : ZERO_STRUCTPN(packet);
758 4154 : SAFE_FREE(packet);
759 : }
760 :
761 150 : int packet_trn_id(struct packet_struct *p)
762 : {
763 : int result;
764 150 : switch (p->packet_type) {
765 150 : case NMB_PACKET:
766 150 : result = p->packet.nmb.header.name_trn_id;
767 150 : break;
768 0 : case DGRAM_PACKET:
769 0 : result = p->packet.dgram.header.dgm_id;
770 0 : break;
771 0 : default:
772 0 : result = -1;
773 : }
774 150 : return result;
775 : }
776 :
777 : /*******************************************************************
778 : Parse a packet buffer into a packet structure.
779 : ******************************************************************/
780 :
781 3973 : struct packet_struct *parse_packet(char *buf,int length,
782 : enum packet_type packet_type,
783 : struct in_addr ip,
784 : int port)
785 : {
786 : struct packet_struct *p;
787 3973 : bool ok=False;
788 :
789 3973 : p = SMB_MALLOC_P(struct packet_struct);
790 3973 : if (!p)
791 0 : return(NULL);
792 :
793 3973 : ZERO_STRUCTP(p); /* initialize for possible padding */
794 :
795 3973 : p->next = NULL;
796 3973 : p->prev = NULL;
797 3973 : p->ip = ip;
798 3973 : p->port = port;
799 3973 : p->locked = False;
800 3973 : p->timestamp = time(NULL);
801 3973 : p->packet_type = packet_type;
802 :
803 3973 : switch (packet_type) {
804 3456 : case NMB_PACKET:
805 3456 : ok = parse_nmb(buf,length,&p->packet.nmb);
806 3456 : break;
807 :
808 517 : case DGRAM_PACKET:
809 517 : ok = parse_dgram(buf,length,&p->packet.dgram);
810 517 : break;
811 : }
812 :
813 3973 : if (!ok) {
814 0 : free_packet(p);
815 0 : return NULL;
816 : }
817 :
818 3973 : return p;
819 : }
820 :
821 151 : static struct packet_struct *copy_packet_talloc(
822 : TALLOC_CTX *mem_ctx, const struct packet_struct *src)
823 : {
824 : struct packet_struct *pkt;
825 :
826 151 : pkt = talloc_memdup(mem_ctx, src, sizeof(struct packet_struct));
827 151 : if (pkt == NULL) {
828 0 : return NULL;
829 : }
830 151 : pkt->locked = false;
831 151 : pkt->recv_fd = -1;
832 151 : pkt->send_fd = -1;
833 :
834 151 : if (src->packet_type == NMB_PACKET) {
835 150 : const struct nmb_packet *nsrc = &src->packet.nmb;
836 150 : struct nmb_packet *ndst = &pkt->packet.nmb;
837 :
838 150 : if (nsrc->answers != NULL) {
839 150 : ndst->answers = talloc_memdup(
840 : pkt, nsrc->answers,
841 : sizeof(struct res_rec) * nsrc->header.ancount);
842 150 : if (ndst->answers == NULL) {
843 0 : goto fail;
844 : }
845 : }
846 150 : if (nsrc->nsrecs != NULL) {
847 0 : ndst->nsrecs = talloc_memdup(
848 : pkt, nsrc->nsrecs,
849 : sizeof(struct res_rec) * nsrc->header.nscount);
850 0 : if (ndst->nsrecs == NULL) {
851 0 : goto fail;
852 : }
853 : }
854 150 : if (nsrc->additional != NULL) {
855 0 : ndst->additional = talloc_memdup(
856 : pkt, nsrc->additional,
857 : sizeof(struct res_rec) * nsrc->header.arcount);
858 0 : if (ndst->additional == NULL) {
859 0 : goto fail;
860 : }
861 : }
862 : }
863 :
864 151 : return pkt;
865 :
866 : /*
867 : * DGRAM packets have no substructures
868 : */
869 :
870 0 : fail:
871 0 : TALLOC_FREE(pkt);
872 0 : return NULL;
873 : }
874 :
875 151 : struct packet_struct *parse_packet_talloc(TALLOC_CTX *mem_ctx,
876 : char *buf,int length,
877 : enum packet_type packet_type,
878 : struct in_addr ip,
879 : int port)
880 : {
881 : struct packet_struct *pkt, *result;
882 :
883 151 : pkt = parse_packet(buf, length, packet_type, ip, port);
884 151 : if (pkt == NULL) {
885 0 : return NULL;
886 : }
887 151 : result = copy_packet_talloc(mem_ctx, pkt);
888 151 : free_packet(pkt);
889 151 : return result;
890 : }
891 :
892 : /*******************************************************************
893 : Send a udp packet on a already open socket.
894 : ******************************************************************/
895 :
896 1188 : static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
897 : {
898 1188 : bool ret = False;
899 : int i;
900 : struct sockaddr_in sock_out;
901 :
902 : /* set the address and port */
903 1188 : memset((char *)&sock_out,'\0',sizeof(sock_out));
904 1188 : putip((char *)&sock_out.sin_addr,(char *)&ip);
905 1188 : sock_out.sin_port = htons( port );
906 1188 : sock_out.sin_family = AF_INET;
907 :
908 1188 : DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
909 : len, inet_ntoa(ip), port ) );
910 :
911 : /*
912 : * Patch to fix asynch error notifications from Linux kernel.
913 : */
914 :
915 1192 : for (i = 0; i < 5; i++) {
916 1192 : ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
917 : sizeof(sock_out)) >= 0);
918 1192 : if (ret || errno != ECONNREFUSED)
919 : break;
920 : }
921 :
922 1188 : if (!ret)
923 27 : DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
924 : inet_ntoa(ip),port,strerror(errno)));
925 :
926 1188 : return(ret);
927 : }
928 :
929 : /*******************************************************************
930 : Build a dgram packet ready for sending.
931 : If buf == NULL this is a length calculation.
932 : ******************************************************************/
933 :
934 219 : static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
935 : {
936 219 : unsigned char *ubuf = (unsigned char *)buf;
937 219 : int offset=0;
938 :
939 : /* put in the header */
940 219 : if (buf) {
941 219 : ubuf[0] = dgram->header.msg_type;
942 219 : ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
943 219 : if (dgram->header.flags.more)
944 0 : ubuf[1] |= 1;
945 219 : if (dgram->header.flags.first)
946 219 : ubuf[1] |= 2;
947 219 : RSSVAL(ubuf,2,dgram->header.dgm_id);
948 219 : putip(ubuf+4,(char *)&dgram->header.source_ip);
949 219 : RSSVAL(ubuf,8,dgram->header.source_port);
950 219 : RSSVAL(ubuf,12,dgram->header.packet_offset);
951 : }
952 :
953 219 : offset = 14;
954 :
955 350 : if (dgram->header.msg_type == 0x10 ||
956 215 : dgram->header.msg_type == 0x11 ||
957 0 : dgram->header.msg_type == 0x12) {
958 219 : offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
959 219 : offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
960 : }
961 :
962 219 : if (buf) {
963 219 : memcpy(ubuf+offset,dgram->data,dgram->datasize);
964 : }
965 219 : offset += dgram->datasize;
966 :
967 : /* automatically set the dgm_length
968 : * NOTE: RFC1002 says the dgm_length does *not*
969 : * include the fourteen-byte header. crh
970 : */
971 219 : dgram->header.dgm_length = (offset - 14);
972 219 : if (buf) {
973 219 : RSSVAL(ubuf,10,dgram->header.dgm_length);
974 : }
975 :
976 219 : return offset;
977 : }
978 :
979 : /*******************************************************************
980 : Build a nmb name
981 : *******************************************************************/
982 :
983 2545 : void make_nmb_name( struct nmb_name *n, const char *name, int type)
984 : {
985 : fstring unix_name;
986 2545 : memset( (char *)n, '\0', sizeof(struct nmb_name) );
987 2545 : fstrcpy(unix_name, name);
988 2545 : (void)strupper_m(unix_name);
989 2545 : push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
990 2545 : n->name_type = (unsigned int)type & 0xFF;
991 2545 : push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
992 2545 : }
993 :
994 : /*******************************************************************
995 : Compare two nmb names
996 : ******************************************************************/
997 :
998 0 : bool nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
999 : {
1000 0 : return ((n1->name_type == n2->name_type) &&
1001 0 : strequal(n1->name ,n2->name ) &&
1002 0 : strequal(n1->scope,n2->scope));
1003 : }
1004 :
1005 : /*******************************************************************
1006 : Build a nmb packet ready for sending.
1007 : If buf == NULL this is a length calculation.
1008 : ******************************************************************/
1009 :
1010 1239 : static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
1011 : {
1012 1239 : unsigned char *ubuf = (unsigned char *)buf;
1013 1239 : int offset=0;
1014 :
1015 1239 : if (len && len < 12) {
1016 0 : return 0;
1017 : }
1018 :
1019 : /* put in the header */
1020 1239 : if (buf) {
1021 1239 : RSSVAL(ubuf,offset,nmb->header.name_trn_id);
1022 1239 : ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
1023 1239 : if (nmb->header.response)
1024 266 : ubuf[offset+2] |= (1<<7);
1025 1407 : if (nmb->header.nm_flags.authoritative &&
1026 266 : nmb->header.response)
1027 266 : ubuf[offset+2] |= 0x4;
1028 1239 : if (nmb->header.nm_flags.trunc)
1029 0 : ubuf[offset+2] |= 0x2;
1030 1239 : if (nmb->header.nm_flags.recursion_desired)
1031 1158 : ubuf[offset+2] |= 0x1;
1032 1404 : if (nmb->header.nm_flags.recursion_available &&
1033 262 : nmb->header.response)
1034 262 : ubuf[offset+3] |= 0x80;
1035 1239 : if (nmb->header.nm_flags.bcast)
1036 872 : ubuf[offset+3] |= 0x10;
1037 1239 : ubuf[offset+3] |= (nmb->header.rcode & 0xF);
1038 :
1039 1239 : RSSVAL(ubuf,offset+4,nmb->header.qdcount);
1040 1239 : RSSVAL(ubuf,offset+6,nmb->header.ancount);
1041 1239 : RSSVAL(ubuf,offset+8,nmb->header.nscount);
1042 1239 : RSSVAL(ubuf,offset+10,nmb->header.arcount);
1043 : }
1044 :
1045 1239 : offset += 12;
1046 1239 : if (nmb->header.qdcount) {
1047 : /* XXXX this doesn't handle a qdcount of > 1 */
1048 973 : if (len) {
1049 : /* Length check. */
1050 973 : int extra = put_nmb_name(NULL,0,offset,
1051 : &nmb->question.question_name);
1052 973 : if (offset + extra > len) {
1053 0 : return 0;
1054 : }
1055 : }
1056 973 : offset += put_nmb_name((char *)ubuf,len,offset,
1057 : &nmb->question.question_name);
1058 973 : if (buf) {
1059 973 : RSSVAL(ubuf,offset,nmb->question.question_type);
1060 973 : RSSVAL(ubuf,offset+2,nmb->question.question_class);
1061 : }
1062 973 : offset += 4;
1063 : }
1064 :
1065 1239 : if (nmb->header.ancount) {
1066 266 : if (len) {
1067 : /* Length check. */
1068 266 : int extra = put_res_rec(NULL,0,offset,nmb->answers,
1069 : nmb->header.ancount);
1070 266 : if (offset + extra > len) {
1071 0 : return 0;
1072 : }
1073 : }
1074 266 : offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
1075 : nmb->header.ancount);
1076 : }
1077 :
1078 1239 : if (nmb->header.nscount) {
1079 0 : if (len) {
1080 : /* Length check. */
1081 0 : int extra = put_res_rec(NULL,0,offset,nmb->nsrecs,
1082 : nmb->header.nscount);
1083 0 : if (offset + extra > len) {
1084 0 : return 0;
1085 : }
1086 : }
1087 0 : offset += put_res_rec((char *)ubuf,len,offset,nmb->nsrecs,
1088 : nmb->header.nscount);
1089 : }
1090 :
1091 : /*
1092 : * The spec says we must put compressed name pointers
1093 : * in the following outgoing packets :
1094 : * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
1095 : * NAME_RELEASE_REQUEST.
1096 : */
1097 :
1098 1870 : if((nmb->header.response == False) &&
1099 1204 : ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
1100 580 : (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
1101 580 : (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
1102 580 : (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
1103 749 : (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
1104 624 : (nmb->header.arcount == 1)) {
1105 :
1106 624 : if (len) {
1107 : /* Length check. */
1108 624 : int extra = put_compressed_name_ptr(NULL,offset,
1109 : nmb->additional,12);
1110 624 : if (offset + extra > len) {
1111 0 : return 0;
1112 : }
1113 : }
1114 624 : offset += put_compressed_name_ptr(ubuf,offset,
1115 624 : nmb->additional,12);
1116 615 : } else if (nmb->header.arcount) {
1117 0 : if (len) {
1118 : /* Length check. */
1119 0 : int extra = put_res_rec(NULL,0,offset,nmb->additional,
1120 : nmb->header.arcount);
1121 0 : if (offset + extra > len) {
1122 0 : return 0;
1123 : }
1124 : }
1125 0 : offset += put_res_rec((char *)ubuf,len,offset,nmb->additional,
1126 : nmb->header.arcount);
1127 : }
1128 1239 : return offset;
1129 : }
1130 :
1131 : /*******************************************************************
1132 : Linearise a packet.
1133 : ******************************************************************/
1134 :
1135 1458 : int build_packet(char *buf, size_t buflen, struct packet_struct *p)
1136 : {
1137 1458 : int len = 0;
1138 :
1139 1458 : switch (p->packet_type) {
1140 1239 : case NMB_PACKET:
1141 1239 : len = build_nmb(buf,buflen,&p->packet.nmb);
1142 1239 : break;
1143 :
1144 219 : case DGRAM_PACKET:
1145 219 : len = build_dgram(buf,buflen,&p->packet.dgram);
1146 219 : break;
1147 : }
1148 :
1149 1458 : return len;
1150 : }
1151 :
1152 : /*******************************************************************
1153 : Send a packet_struct.
1154 : ******************************************************************/
1155 :
1156 1188 : bool send_packet(struct packet_struct *p)
1157 : {
1158 : char buf[1024];
1159 1188 : int len=0;
1160 :
1161 1188 : memset(buf,'\0',sizeof(buf));
1162 :
1163 1188 : len = build_packet(buf, sizeof(buf), p);
1164 :
1165 1188 : if (!len)
1166 0 : return(False);
1167 :
1168 1188 : return(send_udp(p->send_fd,buf,len,p->ip,p->port));
1169 : }
1170 :
1171 : /****************************************************************************
1172 : Receive a UDP/138 packet either via UDP or from the unexpected packet
1173 : queue. The packet must be a reply packet and have the specified mailslot name
1174 : The timeout is in milliseconds.
1175 : ***************************************************************************/
1176 :
1177 : /****************************************************************************
1178 : See if a datagram has the right mailslot name.
1179 : ***************************************************************************/
1180 :
1181 2 : bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
1182 : {
1183 2 : struct dgram_packet *dgram = &p->packet.dgram;
1184 : char *buf;
1185 :
1186 2 : buf = &dgram->data[0];
1187 2 : buf -= 4;
1188 :
1189 2 : buf = smb_buf(buf);
1190 :
1191 2 : if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
1192 2 : return True;
1193 : }
1194 :
1195 0 : return False;
1196 : }
1197 :
1198 : /****************************************************************************
1199 : Return the number of bits that match between two len character buffers
1200 : ***************************************************************************/
1201 :
1202 22 : int matching_len_bits(const unsigned char *p1, const unsigned char *p2, size_t len)
1203 : {
1204 : size_t i, j;
1205 22 : int ret = 0;
1206 44 : for (i=0; i<len; i++) {
1207 44 : if (p1[i] != p2[i])
1208 22 : break;
1209 22 : ret += 8;
1210 : }
1211 :
1212 22 : if (i==len)
1213 0 : return ret;
1214 :
1215 22 : for (j=0; j<8; j++) {
1216 22 : if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
1217 22 : break;
1218 0 : ret++;
1219 : }
1220 :
1221 22 : return ret;
1222 : }
1223 :
1224 : static unsigned char sort_ip[4];
1225 :
1226 : /****************************************************************************
1227 : Compare two query reply records.
1228 : ***************************************************************************/
1229 :
1230 0 : static int name_query_comp(unsigned char *p1, unsigned char *p2)
1231 : {
1232 0 : return matching_len_bits(p2+2, sort_ip, 4) -
1233 0 : matching_len_bits(p1+2, sort_ip, 4);
1234 : }
1235 :
1236 : /****************************************************************************
1237 : Sort a set of 6 byte name query response records so that the IPs that
1238 : have the most leading bits in common with the specified address come first.
1239 : ***************************************************************************/
1240 :
1241 262 : void sort_query_replies(char *data, int n, struct in_addr ip)
1242 : {
1243 262 : if (n <= 1)
1244 262 : return;
1245 :
1246 0 : putip(sort_ip, (char *)&ip);
1247 :
1248 : /* TODO:
1249 : this can't use TYPESAFE_QSORT() as the types are wrong.
1250 : It should be fixed to use a real type instead of char*
1251 : */
1252 0 : qsort(data, n, 6, QSORT_CAST name_query_comp);
1253 : }
1254 :
1255 : /****************************************************************************
1256 : Interpret the weird netbios "name" into a unix fstring. Return the name type.
1257 : Returns -1 on error.
1258 : ****************************************************************************/
1259 :
1260 752 : static int name_interpret(unsigned char *buf, size_t buf_len,
1261 : unsigned char *in, fstring name)
1262 : {
1263 752 : unsigned char *end_ptr = buf + buf_len;
1264 : int ret;
1265 : unsigned int len;
1266 : fstring out_string;
1267 752 : unsigned char *out = (unsigned char *)out_string;
1268 :
1269 752 : *out=0;
1270 :
1271 752 : if (in >= end_ptr) {
1272 0 : return -1;
1273 : }
1274 752 : len = (*in++) / 2;
1275 :
1276 752 : if (len<1) {
1277 0 : return -1;
1278 : }
1279 :
1280 13196 : while (len--) {
1281 12032 : if (&in[1] >= end_ptr) {
1282 0 : return -1;
1283 : }
1284 12032 : if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1285 0 : *out = 0;
1286 0 : return(0);
1287 : }
1288 12032 : *out = ((in[0]-'A')<<4) + (in[1]-'A');
1289 12032 : in += 2;
1290 12032 : out++;
1291 12032 : if (PTR_DIFF(out,out_string) >= sizeof(fstring)) {
1292 0 : return -1;
1293 : }
1294 : }
1295 752 : ret = out[-1];
1296 752 : out[-1] = 0;
1297 :
1298 752 : pull_ascii_fstring(name, out_string);
1299 :
1300 752 : return(ret);
1301 : }
1302 :
1303 : /****************************************************************************
1304 : Mangle a name into netbios format.
1305 : Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
1306 : ****************************************************************************/
1307 :
1308 770 : char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type)
1309 : {
1310 : int i;
1311 : int len;
1312 : nstring buf;
1313 : char *result;
1314 : char *p;
1315 :
1316 770 : result = talloc_array(mem_ctx, char, 33 + strlen(lp_netbios_scope()) + 2);
1317 770 : if (result == NULL) {
1318 0 : return NULL;
1319 : }
1320 770 : p = result;
1321 :
1322 : /* Safely copy the input string, In, into buf[]. */
1323 770 : if (strcmp(In,"*") == 0)
1324 0 : put_name(buf, "*", '\0', 0x00);
1325 : else {
1326 : /* We use an fstring here as mb dos names can expend x3 when
1327 : going to utf8. */
1328 : fstring buf_unix;
1329 : nstring buf_dos;
1330 :
1331 770 : pull_ascii_fstring(buf_unix, In);
1332 770 : if (!strupper_m(buf_unix)) {
1333 0 : return NULL;
1334 : }
1335 :
1336 770 : push_ascii_nstring(buf_dos, buf_unix);
1337 770 : put_name(buf, buf_dos, ' ', name_type);
1338 : }
1339 :
1340 : /* Place the length of the first field into the output buffer. */
1341 770 : p[0] = 32;
1342 770 : p++;
1343 :
1344 : /* Now convert the name to the rfc1001/1002 format. */
1345 13090 : for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
1346 12320 : p[i*2] = ( (buf[i] >> 4) & 0x000F ) + 'A';
1347 12320 : p[(i*2)+1] = (buf[i] & 0x000F) + 'A';
1348 : }
1349 770 : p += 32;
1350 770 : p[0] = '\0';
1351 :
1352 : /* Add the scope string. */
1353 770 : for( i = 0, len = 0; *(lp_netbios_scope()) != '\0'; i++, len++ ) {
1354 0 : switch( (lp_netbios_scope())[i] ) {
1355 0 : case '\0':
1356 0 : p[0] = len;
1357 0 : if( len > 0 )
1358 0 : p[len+1] = 0;
1359 0 : return result;
1360 0 : case '.':
1361 0 : p[0] = len;
1362 0 : p += (len + 1);
1363 0 : len = -1;
1364 0 : break;
1365 0 : default:
1366 0 : p[len+1] = (lp_netbios_scope())[i];
1367 0 : break;
1368 : }
1369 : }
1370 :
1371 770 : return result;
1372 : }
1373 :
1374 : /****************************************************************************
1375 : Find a pointer to a netbios name.
1376 : ****************************************************************************/
1377 :
1378 752 : static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs)
1379 : {
1380 752 : unsigned char c = 0;
1381 :
1382 752 : if (ofs > buf_len || buf_len < 1) {
1383 0 : return NULL;
1384 : }
1385 :
1386 752 : c = *(unsigned char *)(buf+ofs);
1387 752 : if ((c & 0xC0) == 0xC0) {
1388 0 : uint16_t l = 0;
1389 :
1390 0 : if (ofs > buf_len - 1) {
1391 0 : return NULL;
1392 : }
1393 0 : l = RSVAL(buf, ofs) & 0x3FFF;
1394 0 : if (l > buf_len) {
1395 0 : return NULL;
1396 : }
1397 0 : DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1398 0 : return(buf + l);
1399 : } else {
1400 752 : return(buf+ofs);
1401 : }
1402 : }
1403 :
1404 : /****************************************************************************
1405 : Extract a netbios name from a buf (into a unix string) return name type.
1406 : Returns -1 on error.
1407 : ****************************************************************************/
1408 :
1409 752 : int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name)
1410 : {
1411 752 : unsigned char *p = name_ptr(buf,buf_len,ofs);
1412 :
1413 752 : name[0] = '\0';
1414 752 : if (p == NULL) {
1415 0 : return -1;
1416 : }
1417 752 : return(name_interpret(buf,buf_len,p,name));
1418 : }
1419 :
1420 : /****************************************************************************
1421 : Return the total storage length of a mangled name.
1422 : Returns -1 on error.
1423 : ****************************************************************************/
1424 :
1425 1522 : int name_len(unsigned char *s1, size_t buf_len)
1426 : {
1427 : /* NOTE: this argument _must_ be unsigned */
1428 1522 : unsigned char *s = (unsigned char *)s1;
1429 1522 : int len = 0;
1430 :
1431 1522 : if (buf_len < 1) {
1432 0 : return -1;
1433 : }
1434 : /* If the two high bits of the byte are set, return 2. */
1435 1522 : if (0xC0 == (*s & 0xC0)) {
1436 0 : if (buf_len < 2) {
1437 0 : return -1;
1438 : }
1439 0 : return(2);
1440 : }
1441 :
1442 : /* Add up the length bytes. */
1443 3044 : for (len = 1; (*s); s += (*s) + 1) {
1444 1522 : len += *s + 1;
1445 1522 : if (len > buf_len) {
1446 0 : return -1;
1447 : }
1448 : }
1449 :
1450 1522 : return(len);
1451 : }
1452 :
1453 : /*******************************************************************
1454 : Setup the word count and byte count for a client smb message.
1455 : ********************************************************************/
1456 :
1457 216 : int cli_set_message(char *buf,int num_words,int num_bytes,bool zero)
1458 : {
1459 216 : if (zero && (num_words || num_bytes)) {
1460 216 : memset(buf + smb_size,'\0',num_words*2 + num_bytes);
1461 : }
1462 216 : SCVAL(buf,smb_wct,num_words);
1463 216 : SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
1464 216 : smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
1465 216 : return (smb_size + num_words*2 + num_bytes);
1466 : }
|