fixed error check which caused domain logons to fail
[Samba.git] / source / nmbd / nmbd_incomingrequests.c
blobdbbb73157875c9fba45e64264da03e1ac1e3897e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file contains all the code to process NetBIOS requests coming
24 in on port 137. It does not deal with the code needed to service
25 WINS server requests, but only broadcast and unicast requests.
29 #include "includes.h"
31 extern fstring global_myworkgroup;
33 /****************************************************************************
34 Send a name release response.
35 **************************************************************************/
37 static void send_name_release_response(int rcode, struct packet_struct *p)
39 struct nmb_packet *nmb = &p->packet.nmb;
40 char rdata[6];
42 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
44 reply_netbios_packet(p, /* Packet to reply to. */
45 rcode, /* Result code. */
46 NMB_REL, /* nmbd type code. */
47 NMB_NAME_RELEASE_OPCODE, /* opcode. */
48 0, /* ttl. */
49 rdata, /* data to send. */
50 6); /* data length. */
53 /****************************************************************************
54 Process a name release packet on a broadcast subnet.
55 Ignore it if it's not one of our names.
56 ****************************************************************************/
58 void process_name_release_request(struct subnet_record *subrec,
59 struct packet_struct *p)
61 struct nmb_packet *nmb = &p->packet.nmb;
62 struct in_addr owner_ip;
63 struct nmb_name *question = &nmb->question.question_name;
64 BOOL bcast = nmb->header.nm_flags.bcast;
65 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
66 BOOL group = (nb_flags & NB_GROUP) ? True : False;
67 struct name_record *namerec;
68 int rcode = 0;
70 START_PROFILE(name_release);
71 putip((char *)&owner_ip,&nmb->additional->rdata[2]);
73 if(!bcast)
75 /* We should only get broadcast name release packets here.
76 Anyone trying to release unicast should be going to a WINS
77 server. If the code gets here, then either we are not a wins
78 server and they sent it anyway, or we are a WINS server and
79 the request was malformed. Either way, log an error here.
80 and send an error reply back.
82 DEBUG(0,("process_name_release_request: unicast name release request \
83 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
84 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
86 send_name_release_response(FMT_ERR, p);
87 goto done;
90 DEBUG(3,("process_name_release_request: Name release on name %s, \
91 subnet %s from owner IP %s\n",
92 nmb_namestr(&nmb->question.question_name),
93 subrec->subnet_name, inet_ntoa(owner_ip)));
95 /* If someone is releasing a broadcast group name, just ignore it. */
96 if( group && !ismyip(owner_ip) )
97 goto done;
100 * Code to work around a bug in FTP OnNet software NBT implementation.
101 * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
102 * names and *don't set the group bit* !!!!!
105 if( !group && !ismyip(owner_ip) && strequal(question->name, global_myworkgroup) &&
106 ((question->name_type == 0x0) || (question->name_type == 0x1e)))
108 DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
109 group release name %s from IP %s on subnet %s with no group bit set.\n",
110 nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
111 goto done;
114 namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
116 /* We only care about someone trying to release one of our names. */
117 if( namerec
118 && ( (namerec->data.source == SELF_NAME)
119 || (namerec->data.source == PERMANENT_NAME) ) )
121 rcode = ACT_ERR;
122 DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
123 on subnet %s being rejected as it is one of our names.\n",
124 nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
127 if(rcode == 0)
128 goto done;
130 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
131 send_name_release_response(rcode, p);
132 done:
133 END_PROFILE(name_release);
136 /****************************************************************************
137 Send a name registration response.
138 **************************************************************************/
140 static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
142 struct nmb_packet *nmb = &p->packet.nmb;
143 char rdata[6];
145 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
147 reply_netbios_packet(p, /* Packet to reply to. */
148 rcode, /* Result code. */
149 NMB_REG, /* nmbd type code. */
150 NMB_NAME_REG_OPCODE, /* opcode. */
151 ttl, /* ttl. */
152 rdata, /* data to send. */
153 6); /* data length. */
156 /****************************************************************************
157 Process a name refresh request on a broadcast subnet.
158 **************************************************************************/
160 void process_name_refresh_request(struct subnet_record *subrec,
161 struct packet_struct *p)
164 struct nmb_packet *nmb = &p->packet.nmb;
165 struct nmb_name *question = &nmb->question.question_name;
166 BOOL bcast = nmb->header.nm_flags.bcast;
167 struct in_addr from_ip;
169 START_PROFILE(name_refresh);
170 putip((char *)&from_ip,&nmb->additional->rdata[2]);
172 if(!bcast)
174 /* We should only get broadcast name refresh packets here.
175 Anyone trying to refresh unicast should be going to a WINS
176 server. If the code gets here, then either we are not a wins
177 server and they sent it anyway, or we are a WINS server and
178 the request was malformed. Either way, log an error here.
179 and send an error reply back.
181 DEBUG(0,("process_name_refresh_request: unicast name registration request \
182 received for name %s from IP %s on subnet %s.\n",
183 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
184 DEBUG(0,("Error - should be sent to WINS server\n"));
186 send_name_registration_response(FMT_ERR, 0, p);
187 goto done;
190 /* Just log a message. We really don't care about broadcast name
191 refreshes. */
193 DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
194 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
196 done:
197 END_PROFILE(name_refresh);
200 /****************************************************************************
201 Process a name registration request on a broadcast subnet.
202 **************************************************************************/
204 void process_name_registration_request(struct subnet_record *subrec,
205 struct packet_struct *p)
207 struct nmb_packet *nmb = &p->packet.nmb;
208 struct nmb_name *question = &nmb->question.question_name;
209 BOOL bcast = nmb->header.nm_flags.bcast;
210 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
211 BOOL group = (nb_flags & NB_GROUP) ? True : False;
212 struct name_record *namerec = NULL;
213 int ttl = nmb->additional->ttl;
214 struct in_addr from_ip;
216 START_PROFILE(name_registration);
217 putip((char *)&from_ip,&nmb->additional->rdata[2]);
219 if(!bcast)
221 /* We should only get broadcast name registration packets here.
222 Anyone trying to register unicast should be going to a WINS
223 server. If the code gets here, then either we are not a wins
224 server and they sent it anyway, or we are a WINS server and
225 the request was malformed. Either way, log an error here.
226 and send an error reply back.
228 DEBUG(0,("process_name_registration_request: unicast name registration request \
229 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
230 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
232 send_name_registration_response(FMT_ERR, 0, p);
233 goto done;
236 DEBUG(3,("process_name_registration_request: Name registration for name %s \
237 IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
239 /* See if the name already exists. */
240 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
243 * If the name being registered exists and is a WINS_PROXY_NAME
244 * then delete the WINS proxy name entry so we don't reply erroneously
245 * later to queries.
248 if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
250 remove_name_from_namelist( subrec, namerec );
251 namerec = NULL;
254 if (!group)
256 /* Unique name. */
258 if( (namerec != NULL)
259 && ( (namerec->data.source == SELF_NAME)
260 || (namerec->data.source == PERMANENT_NAME)
261 || NAME_GROUP(namerec) ) )
263 /* No-one can register one of Samba's names, nor can they
264 register a name that's a group name as a unique name */
266 send_name_registration_response(ACT_ERR, 0, p);
267 goto done;
269 else if(namerec != NULL)
271 /* Update the namelist record with the new information. */
272 namerec->data.ip[0] = from_ip;
273 update_name_ttl(namerec, ttl);
275 DEBUG(3,("process_name_registration_request: Updated name record %s \
276 with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
277 goto done;
280 else
282 /* Group name. */
284 if( (namerec != NULL)
285 && !NAME_GROUP(namerec)
286 && ( (namerec->data.source == SELF_NAME)
287 || (namerec->data.source == PERMANENT_NAME) ) )
289 /* Disallow group names when we have a unique name. */
290 send_name_registration_response(ACT_ERR, 0, p);
291 goto done;
294 done:
295 END_PROFILE(name_registration);
298 /****************************************************************************
299 This is used to sort names for a name status into a sensible order.
300 We put our own names first, then in alphabetical order.
301 **************************************************************************/
303 static int status_compare(char *n1,char *n2)
305 extern pstring global_myname;
306 int l1,l2,l3;
308 /* It's a bit tricky because the names are space padded */
309 for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
310 for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
311 l3 = strlen(global_myname);
313 if ((l1==l3) && strncmp(n1,global_myname,l3) == 0 &&
314 (l2!=l3 || strncmp(n2,global_myname,l3) != 0))
315 return -1;
317 if ((l2==l3) && strncmp(n2,global_myname,l3) == 0 &&
318 (l1!=l3 || strncmp(n1,global_myname,l3) != 0))
319 return 1;
321 return memcmp(n1,n2,18);
325 /****************************************************************************
326 Process a node status query
327 ****************************************************************************/
329 void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
331 struct nmb_packet *nmb = &p->packet.nmb;
332 char *qname = nmb->question.question_name.name;
333 int ques_type = nmb->question.question_name.name_type;
334 char rdata[MAX_DGRAM_SIZE];
335 char *countptr, *buf, *bufend, *buf0;
336 int names_added,i;
337 struct name_record *namerec;
339 START_PROFILE(node_status);
340 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
341 subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
342 subrec->subnet_name));
344 if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
345 FIND_SELF_NAME)) == 0)
347 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
348 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
349 inet_ntoa(p->ip), subrec->subnet_name));
351 goto done;
354 /* this is not an exact calculation. the 46 is for the stats buffer
355 and the 60 is to leave room for the header etc */
356 bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
357 countptr = buf = rdata;
358 buf += 1;
359 buf0 = buf;
361 names_added = 0;
363 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
365 while (buf < bufend)
367 if( (namerec->data.source == SELF_NAME)
368 || (namerec->data.source == PERMANENT_NAME) )
370 int name_type = namerec->name.name_type;
372 if (!strequal(namerec->name.name,"*") &&
373 !strequal(namerec->name.name,"__SAMBA__") &&
374 (name_type < 0x1b || name_type >= 0x20 ||
375 ques_type < 0x1b || ques_type >= 0x20 ||
376 strequal(qname, namerec->name.name)))
378 /* Start with the name. */
379 memset(buf,'\0',18);
380 slprintf(buf, 17, "%-15.15s",namerec->name.name);
381 strupper(buf);
383 /* Put the name type and netbios flags in the buffer. */
384 buf[15] = name_type;
385 set_nb_flags( &buf[16],namerec->data.nb_flags );
386 buf[16] |= NB_ACTIVE; /* all our names are active */
388 buf += 18;
390 names_added++;
394 /* Remove duplicate names. */
395 if (names_added > 1) {
396 qsort( buf0, names_added, 18, QSORT_CAST status_compare );
399 for( i=1; i < names_added ; i++ )
401 if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0)
403 names_added--;
404 if (names_added == i)
405 break;
406 memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
407 i--;
411 buf = buf0 + 18*names_added;
413 namerec = (struct name_record *)ubi_trNext( namerec );
415 if (!namerec)
417 /* End of the subnet specific name list. Now
418 add the names on the unicast subnet . */
419 struct subnet_record *uni_subrec = unicast_subnet;
421 if (uni_subrec != subrec)
423 subrec = uni_subrec;
424 namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
427 if (!namerec)
428 break;
432 SCVAL(countptr,0,names_added);
434 /* We don't send any stats as they could be used to attack
435 the protocol. */
436 memset(buf,'\0',46);
438 buf += 46;
440 /* Send a NODE STATUS RESPONSE */
441 reply_netbios_packet(p, /* Packet to reply to. */
442 0, /* Result code. */
443 NMB_STATUS, /* nmbd type code. */
444 NMB_NAME_QUERY_OPCODE, /* opcode. */
445 0, /* ttl. */
446 rdata, /* data to send. */
447 PTR_DIFF(buf,rdata)); /* data length. */
448 done:
449 END_PROFILE(node_status);
453 /***************************************************************************
454 Process a name query.
456 For broadcast name queries:
458 - Only reply if the query is for one of YOUR names.
459 - NEVER send a negative response to a broadcast query.
461 ****************************************************************************/
463 void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
465 struct nmb_packet *nmb = &p->packet.nmb;
466 struct nmb_name *question = &nmb->question.question_name;
467 int name_type = question->name_type;
468 BOOL bcast = nmb->header.nm_flags.bcast;
469 int ttl=0;
470 int rcode = 0;
471 char *prdata = NULL;
472 char rdata[6];
473 BOOL success = False;
474 struct name_record *namerec = NULL;
475 int reply_data_len = 0;
476 int i;
478 START_PROFILE(name_query);
479 DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
480 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
482 /* Look up the name in the cache - if the request is a broadcast request that
483 came from a subnet we don't know about then search all the broadcast subnets
484 for a match (as we don't know what interface the request came in on). */
486 if(subrec == remote_broadcast_subnet)
487 namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
488 else
489 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
492 /* Check if it is a name that expired */
493 if( namerec
494 && ( (namerec->data.death_time != PERMANENT_TTL)
495 && (namerec->data.death_time < p->timestamp) ) )
497 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
498 namerec = NULL;
501 if (namerec)
505 * Always respond to unicast queries.
506 * Don't respond to broadcast queries unless the query is for
507 * a name we own, a Primary Domain Controller name, or a WINS_PROXY
508 * name with type 0 or 0x20. WINS_PROXY names are only ever added
509 * into the namelist if we were configured as a WINS proxy.
512 if( !bcast
513 || ( bcast
514 && ( (name_type == 0x1b)
515 || (namerec->data.source == SELF_NAME)
516 || (namerec->data.source == PERMANENT_NAME)
517 || ( (namerec->data.source == WINS_PROXY_NAME)
518 && ( (name_type == 0) || (name_type == 0x20) )
525 /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
526 or it's a Domain Master type. */
529 * If this is a WINS_PROXY_NAME, then ceck that none of the IP
530 * addresses we are returning is on the same broadcast subnet
531 * as the requesting packet. If it is then don't reply as the
532 * actual machine will be replying also and we don't want two
533 * replies to a broadcast query.
536 if( namerec->data.source == WINS_PROXY_NAME )
538 for( i = 0; i < namerec->data.num_ips; i++)
540 if(same_net( namerec->data.ip[i], subrec->myip, subrec->mask_ip ))
542 DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
543 on the same subnet (%s) as the requestor. Not replying.\n",
544 nmb_namestr(&namerec->name), subrec->subnet_name ));
545 goto done;
550 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
551 namerec->data.death_time - p->timestamp : lp_max_ttl();
553 /* Copy all known ip addresses into the return data. */
554 /* Optimise for the common case of one IP address so
555 we don't need a malloc. */
557 if( namerec->data.num_ips == 1 )
558 prdata = rdata;
559 else
561 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
563 DEBUG(0,("process_name_query_request: malloc fail !\n"));
564 goto done;
568 for( i = 0; i < namerec->data.num_ips; i++ )
570 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
571 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
574 sort_query_replies(prdata, i, p->ip);
576 reply_data_len = namerec->data.num_ips * 6;
577 success = True;
582 * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
583 * set we should initiate a WINS query here. On success we add the resolved name
584 * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
587 if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
588 bcast && (subrec != remote_broadcast_subnet))
590 make_wins_proxy_name_query_request( subrec, p, question );
591 goto done;
594 if (!success && bcast)
596 if((prdata != rdata) && (prdata != NULL))
597 SAFE_FREE(prdata);
598 goto done; /* Never reply with a negative response to broadcasts. */
602 * Final check. From observation, if a unicast packet is sent
603 * to a non-WINS server with the recursion desired bit set
604 * then never send a negative response.
607 if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
609 if((prdata != rdata) && (prdata != NULL))
610 SAFE_FREE(prdata);
611 goto done;
614 if (success)
616 rcode = 0;
617 DEBUG(3,("OK\n"));
619 else
621 rcode = NAM_ERR;
622 DEBUG(3,("UNKNOWN\n"));
625 /* See rfc1002.txt 4.2.13. */
627 reply_netbios_packet(p, /* Packet to reply to. */
628 rcode, /* Result code. */
629 NMB_QUERY, /* nmbd type code. */
630 NMB_NAME_QUERY_OPCODE, /* opcode. */
631 ttl, /* ttl. */
632 prdata, /* data to send. */
633 reply_data_len); /* data length. */
635 if((prdata != rdata) && (prdata != NULL))
636 SAFE_FREE(prdata);
637 done:
638 END_PROFILE(name_query);