source: vendor/current/source3/nmbd/nmbd_incomingrequests.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 20.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-2003
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 This file contains all the code to process NetBIOS requests coming
22 in on port 137. It does not deal with the code needed to service
23 WINS server requests, but only broadcast and unicast requests.
24
25*/
26
27#include "includes.h"
28#include "nmbd/nmbd.h"
29
30/****************************************************************************
31Send a name release response.
32**************************************************************************/
33
34static void send_name_release_response(int rcode, struct packet_struct *p)
35{
36 struct nmb_packet *nmb = &p->packet.nmb;
37 char rdata[6];
38
39 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
40
41 reply_netbios_packet(p, /* Packet to reply to. */
42 rcode, /* Result code. */
43 NMB_REL, /* nmbd type code. */
44 NMB_NAME_RELEASE_OPCODE, /* opcode. */
45 0, /* ttl. */
46 rdata, /* data to send. */
47 6); /* data length. */
48}
49
50/****************************************************************************
51Process a name release packet on a broadcast subnet.
52Ignore it if it's not one of our names.
53****************************************************************************/
54
55void process_name_release_request(struct subnet_record *subrec,
56 struct packet_struct *p)
57{
58 struct nmb_packet *nmb = &p->packet.nmb;
59 struct in_addr owner_ip;
60 struct nmb_name *question = &nmb->question.question_name;
61 unstring qname;
62 bool bcast = nmb->header.nm_flags.bcast;
63 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
64 bool group = (nb_flags & NB_GROUP) ? True : False;
65 struct name_record *namerec;
66 int rcode = 0;
67
68 putip((char *)&owner_ip,&nmb->additional->rdata[2]);
69
70 if(!bcast) {
71 /* We should only get broadcast name release packets here.
72 Anyone trying to release unicast should be going to a WINS
73 server. If the code gets here, then either we are not a wins
74 server and they sent it anyway, or we are a WINS server and
75 the request was malformed. Either way, log an error here.
76 and send an error reply back.
77 */
78 DEBUG(0,("process_name_release_request: unicast name release request \
79received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
80 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
81
82 send_name_release_response(FMT_ERR, p);
83 return;
84 }
85
86 DEBUG(3,("process_name_release_request: Name release on name %s, \
87subnet %s from owner IP %s\n",
88 nmb_namestr(&nmb->question.question_name),
89 subrec->subnet_name, inet_ntoa(owner_ip)));
90
91 /* If someone is releasing a broadcast group name, just ignore it. */
92 if( group && !ismyip_v4(owner_ip) )
93 return;
94
95 /*
96 * Code to work around a bug in FTP OnNet software NBT implementation.
97 * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
98 * names and *don't set the group bit* !!!!!
99 */
100
101 pull_ascii_nstring(qname, sizeof(qname), question->name);
102 if( !group && !ismyip_v4(owner_ip) && strequal(qname, lp_workgroup()) &&
103 ((question->name_type == 0x0) || (question->name_type == 0x1e))) {
104 DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
105group release name %s from IP %s on subnet %s with no group bit set.\n",
106 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
107 return;
108 }
109
110 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
111
112 /* We only care about someone trying to release one of our names. */
113 if( namerec && ( (namerec->data.source == SELF_NAME)
114 || (namerec->data.source == PERMANENT_NAME) ) ) {
115 rcode = ACT_ERR;
116 DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
117on subnet %s being rejected as it is one of our names.\n",
118 nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
119 }
120
121 if(rcode == 0)
122 return;
123
124 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
125 send_name_release_response(rcode, p);
126}
127
128/****************************************************************************
129Send a name registration response.
130**************************************************************************/
131
132static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
133{
134 struct nmb_packet *nmb = &p->packet.nmb;
135 char rdata[6];
136
137 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
138
139 reply_netbios_packet(p, /* Packet to reply to. */
140 rcode, /* Result code. */
141 NMB_REG, /* nmbd type code. */
142 NMB_NAME_REG_OPCODE, /* opcode. */
143 ttl, /* ttl. */
144 rdata, /* data to send. */
145 6); /* data length. */
146}
147
148/****************************************************************************
149Process a name refresh request on a broadcast subnet.
150**************************************************************************/
151
152void process_name_refresh_request(struct subnet_record *subrec,
153 struct packet_struct *p)
154{
155 struct nmb_packet *nmb = &p->packet.nmb;
156 struct nmb_name *question = &nmb->question.question_name;
157 bool bcast = nmb->header.nm_flags.bcast;
158 struct in_addr from_ip;
159
160 putip((char *)&from_ip,&nmb->additional->rdata[2]);
161
162 if(!bcast) {
163 /* We should only get broadcast name refresh packets here.
164 Anyone trying to refresh unicast should be going to a WINS
165 server. If the code gets here, then either we are not a wins
166 server and they sent it anyway, or we are a WINS server and
167 the request was malformed. Either way, log an error here.
168 and send an error reply back.
169 */
170 DEBUG(0,("process_name_refresh_request: unicast name registration request \
171received for name %s from IP %s on subnet %s.\n",
172 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
173 DEBUG(0,("Error - should be sent to WINS server\n"));
174
175 send_name_registration_response(FMT_ERR, 0, p);
176 return;
177 }
178
179 /* Just log a message. We really don't care about broadcast name refreshes. */
180
181 DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
182IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
183}
184
185/****************************************************************************
186Process a name registration request on a broadcast subnet.
187**************************************************************************/
188
189void process_name_registration_request(struct subnet_record *subrec,
190 struct packet_struct *p)
191{
192 struct nmb_packet *nmb = &p->packet.nmb;
193 struct nmb_name *question = &nmb->question.question_name;
194 bool bcast = nmb->header.nm_flags.bcast;
195 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
196 bool group = (nb_flags & NB_GROUP) ? True : False;
197 struct name_record *namerec = NULL;
198 int ttl = nmb->additional->ttl;
199 struct in_addr from_ip;
200
201 putip((char *)&from_ip,&nmb->additional->rdata[2]);
202
203 if(!bcast) {
204 /* We should only get broadcast name registration packets here.
205 Anyone trying to register unicast should be going to a WINS
206 server. If the code gets here, then either we are not a wins
207 server and they sent it anyway, or we are a WINS server and
208 the request was malformed. Either way, log an error here.
209 and send an error reply back.
210 */
211 DEBUG(0,("process_name_registration_request: unicast name registration request \
212received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
213 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
214
215 send_name_registration_response(FMT_ERR, 0, p);
216 return;
217 }
218
219 DEBUG(3,("process_name_registration_request: Name registration for name %s \
220IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
221
222 /* See if the name already exists. */
223 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
224
225 /*
226 * If the name being registered exists and is a WINS_PROXY_NAME
227 * then delete the WINS proxy name entry so we don't reply erroneously
228 * later to queries.
229 */
230
231 if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
232 remove_name_from_namelist( subrec, namerec );
233 namerec = NULL;
234 }
235
236 if (!group) {
237 /* Unique name. */
238
239 if( (namerec != NULL)
240 && ( (namerec->data.source == SELF_NAME)
241 || (namerec->data.source == PERMANENT_NAME)
242 || NAME_GROUP(namerec) ) ) {
243 /* No-one can register one of Samba's names, nor can they
244 register a name that's a group name as a unique name */
245
246 send_name_registration_response(ACT_ERR, 0, p);
247 return;
248 } else if(namerec != NULL) {
249 /* Update the namelist record with the new information. */
250 namerec->data.ip[0] = from_ip;
251 update_name_ttl(namerec, ttl);
252
253 DEBUG(3,("process_name_registration_request: Updated name record %s \
254with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
255 return;
256 }
257 } else {
258 /* Group name. */
259
260 if( (namerec != NULL)
261 && !NAME_GROUP(namerec)
262 && ( (namerec->data.source == SELF_NAME)
263 || (namerec->data.source == PERMANENT_NAME) ) ) {
264 /* Disallow group names when we have a unique name. */
265 send_name_registration_response(ACT_ERR, 0, p);
266 return;
267 }
268 }
269}
270
271/****************************************************************************
272This is used to sort names for a name status into a sensible order.
273We put our own names first, then in alphabetical order.
274**************************************************************************/
275
276static int status_compare(char *n1,char *n2)
277{
278 unstring name1, name2;
279 int l1,l2,l3;
280
281 memset(name1, '\0', sizeof(name1));
282 memset(name2, '\0', sizeof(name2));
283 pull_ascii_nstring(name1, sizeof(name1), n1);
284 pull_ascii_nstring(name2, sizeof(name2), n2);
285 n1 = name1;
286 n2 = name2;
287
288 /* It's a bit tricky because the names are space padded */
289 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
290 ;
291 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
292 ;
293 l3 = strlen(lp_netbios_name());
294
295 if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 &&
296 (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0))
297 return -1;
298
299 if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 &&
300 (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0))
301 return 1;
302
303 return memcmp(n1,n2,sizeof(name1));
304}
305
306/****************************************************************************
307 Process a node status query
308 ****************************************************************************/
309
310void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
311{
312 struct nmb_packet *nmb = &p->packet.nmb;
313 unstring qname;
314 int ques_type = nmb->question.question_name.name_type;
315 char rdata[MAX_DGRAM_SIZE];
316 char *countptr, *buf, *bufend, *buf0;
317 int names_added,i;
318 struct name_record *namerec = NULL;
319
320 pull_ascii_nstring(qname, sizeof(qname), nmb->question.question_name.name);
321
322 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
323subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
324
325 if(find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME) == 0) {
326 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
327subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
328 inet_ntoa(p->ip), subrec->subnet_name));
329
330 return;
331 }
332
333 /* this is not an exact calculation. the 46 is for the stats buffer
334 and the 60 is to leave room for the header etc */
335 bufend = &rdata[MAX_DGRAM_SIZE-1] - (18 + 46 + 60);
336 countptr = buf = rdata;
337 buf += 1;
338 buf0 = buf;
339
340 names_added = 0;
341
342 namerec = subrec->namelist;
343
344 while (buf < bufend) {
345 if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
346 int name_type = namerec->name.name_type;
347 unstring name;
348
349 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
350 if (!strupper_m(name)) {
351 DEBUG(2,("strupper_m %s failed\n", name));
352 return;
353 }
354 if (!strequal(name,"*") &&
355 !strequal(name,"__SAMBA__") &&
356 (name_type < 0x1b || name_type >= 0x20 ||
357 ques_type < 0x1b || ques_type >= 0x20 ||
358 strequal(qname, name))) {
359 /* Start with the name. */
360 size_t len;
361 push_ascii_nstring(buf, name);
362 len = strlen(buf);
363 memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
364 buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
365
366 /* Put the name type and netbios flags in the buffer. */
367
368 buf[15] = name_type;
369 set_nb_flags( &buf[16],namerec->data.nb_flags );
370 buf[16] |= NB_ACTIVE; /* all our names are active */
371
372 buf += 18;
373
374 names_added++;
375 }
376 }
377
378 /* Remove duplicate names. */
379 if (names_added > 1) {
380 /* TODO: should use a real type and
381 TYPESAFE_QSORT() */
382 qsort( buf0, names_added, 18, QSORT_CAST status_compare );
383 }
384
385 for( i=1; i < names_added ; i++ ) {
386 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
387 names_added--;
388 if (names_added == i)
389 break;
390 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
391 i--;
392 }
393 }
394
395 buf = buf0 + 18*names_added;
396
397 namerec = namerec->next;
398
399 if (!namerec) {
400 /* End of the subnet specific name list. Now
401 add the names on the unicast subnet . */
402 struct subnet_record *uni_subrec = unicast_subnet;
403
404 if (uni_subrec != subrec) {
405 subrec = uni_subrec;
406 namerec = subrec->namelist;
407 }
408 }
409 if (!namerec)
410 break;
411
412 }
413
414 SCVAL(countptr,0,names_added);
415
416 /* We don't send any stats as they could be used to attack
417 the protocol. */
418 memset(buf,'\0',46);
419
420 buf += 46;
421
422 /* Send a NODE STATUS RESPONSE */
423 reply_netbios_packet(p, /* Packet to reply to. */
424 0, /* Result code. */
425 NMB_STATUS, /* nmbd type code. */
426 NMB_NAME_QUERY_OPCODE, /* opcode. */
427 0, /* ttl. */
428 rdata, /* data to send. */
429 PTR_DIFF(buf,rdata)); /* data length. */
430}
431
432
433/***************************************************************************
434Process a name query.
435
436For broadcast name queries:
437
438 - Only reply if the query is for one of YOUR names.
439 - NEVER send a negative response to a broadcast query.
440
441****************************************************************************/
442
443void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
444{
445 struct nmb_packet *nmb = &p->packet.nmb;
446 struct nmb_name *question = &nmb->question.question_name;
447 int name_type = question->name_type;
448 bool bcast = nmb->header.nm_flags.bcast;
449 int ttl=0;
450 int rcode = 0;
451 char *prdata = NULL;
452 char rdata[6];
453 bool success = False;
454 struct name_record *namerec = NULL;
455 int reply_data_len = 0;
456 int i;
457
458 DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
459 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
460
461 /* Look up the name in the cache - if the request is a broadcast request that
462 came from a subnet we don't know about then search all the broadcast subnets
463 for a match (as we don't know what interface the request came in on). */
464
465 if(subrec == remote_broadcast_subnet)
466 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
467 else
468 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
469
470 /* Check if it is a name that expired */
471 if (namerec &&
472 ((namerec->data.death_time != PERMANENT_TTL) &&
473 (namerec->data.death_time < p->timestamp))) {
474 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
475 namerec = NULL;
476 }
477
478 if (namerec) {
479 /*
480 * Always respond to unicast queries.
481 * Don't respond to broadcast queries unless the query is for
482 * a name we own, a Primary Domain Controller name, or a WINS_PROXY
483 * name with type 0 or 0x20. WINS_PROXY names are only ever added
484 * into the namelist if we were configured as a WINS proxy.
485 */
486
487 if (!bcast ||
488 (bcast && ((name_type == 0x1b) ||
489 (namerec->data.source == SELF_NAME) ||
490 (namerec->data.source == PERMANENT_NAME) ||
491 ((namerec->data.source == WINS_PROXY_NAME) &&
492 ((name_type == 0) || (name_type == 0x20)))))) {
493 /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
494 or it's a Domain Master type. */
495
496 /*
497 * If this is a WINS_PROXY_NAME, then ceck that none of the IP
498 * addresses we are returning is on the same broadcast subnet
499 * as the requesting packet. If it is then don't reply as the
500 * actual machine will be replying also and we don't want two
501 * replies to a broadcast query.
502 */
503
504 if (namerec->data.source == WINS_PROXY_NAME) {
505 for( i = 0; i < namerec->data.num_ips; i++) {
506 if (same_net_v4(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
507 DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n",
508 nmb_namestr(&namerec->name), subrec->subnet_name ));
509 return;
510 }
511 }
512 }
513
514 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
515 namerec->data.death_time - p->timestamp : lp_max_ttl();
516
517 /* Copy all known ip addresses into the return data. */
518 /* Optimise for the common case of one IP address so
519 we don't need a malloc. */
520
521 if (namerec->data.num_ips == 1) {
522 prdata = rdata;
523 } else {
524 if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
525 DEBUG(0,("process_name_query_request: malloc fail !\n"));
526 return;
527 }
528 }
529
530 for (i = 0; i < namerec->data.num_ips; i++) {
531 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
532 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
533 }
534
535 sort_query_replies(prdata, i, p->ip);
536
537 reply_data_len = namerec->data.num_ips * 6;
538 success = True;
539 }
540 }
541
542 /*
543 * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
544 * set we should initiate a WINS query here. On success we add the resolved name
545 * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
546 */
547
548 if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
549 bcast && (subrec != remote_broadcast_subnet)) {
550 make_wins_proxy_name_query_request( subrec, p, question );
551 return;
552 }
553
554 if (!success && bcast) {
555 if(prdata != rdata)
556 SAFE_FREE(prdata);
557 return; /* Never reply with a negative response to broadcasts. */
558 }
559
560 /*
561 * Final check. From observation, if a unicast packet is sent
562 * to a non-WINS server with the recursion desired bit set
563 * then never send a negative response.
564 */
565
566 if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
567 if(prdata != rdata)
568 SAFE_FREE(prdata);
569 return;
570 }
571
572 if (success) {
573 rcode = 0;
574 DEBUG(3,("OK\n"));
575 } else {
576 rcode = NAM_ERR;
577 DEBUG(3,("UNKNOWN\n"));
578 }
579
580 /* See rfc1002.txt 4.2.13. */
581
582 reply_netbios_packet(p, /* Packet to reply to. */
583 rcode, /* Result code. */
584 NMB_QUERY, /* nmbd type code. */
585 NMB_NAME_QUERY_OPCODE, /* opcode. */
586 ttl, /* ttl. */
587 prdata, /* data to send. */
588 reply_data_len); /* data length. */
589
590 if(prdata != rdata)
591 SAFE_FREE(prdata);
592}
Note: See TracBrowser for help on using the repository browser.