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 2 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, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22   This file contains all the code to process NetBIOS requests coming
23   in on port 137. It does not deal with the code needed to service
24   WINS server requests, but only broadcast and unicast requests.
25
26*/
27
28#include "includes.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 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(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(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 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(global_myname());
294
295	if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 &&
296			(l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
297		return -1;
298
299	if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 &&
300			(l1!=l3 || strncmp(n1,global_myname(),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;
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((namerec = 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] - (18 + 46 + 60);
336	countptr = buf = rdata;
337	buf += 1;
338	buf0 = buf;
339
340	names_added = 0;
341
342	namerec = (struct name_record *)ubi_trFirst( 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			strupper_m(name);
351			if (!strequal(name,"*") &&
352					!strequal(name,"__SAMBA__") &&
353					(name_type < 0x1b || name_type >= 0x20 ||
354					ques_type < 0x1b || ques_type >= 0x20 ||
355					strequal(qname, name))) {
356				/* Start with the name. */
357				size_t len;
358				push_ascii_nstring(buf, name);
359				len = strlen(buf);
360				memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
361				buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
362
363				/* Put the name type and netbios flags in the buffer. */
364
365				buf[15] = name_type;
366				set_nb_flags( &buf[16],namerec->data.nb_flags );
367				buf[16] |= NB_ACTIVE; /* all our names are active */
368
369				buf += 18;
370
371				names_added++;
372			}
373		}
374
375		/* Remove duplicate names. */
376		if (names_added > 1) {
377			qsort( buf0, names_added, 18, QSORT_CAST status_compare );
378		}
379
380		for( i=1; i < names_added ; i++ ) {
381			if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
382				names_added--;
383				if (names_added == i)
384					break;
385				memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
386				i--;
387			}
388		}
389
390		buf = buf0 + 18*names_added;
391
392		namerec = (struct name_record *)ubi_trNext( namerec );
393
394		if (!namerec) {
395			/* End of the subnet specific name list. Now
396				add the names on the unicast subnet . */
397			struct subnet_record *uni_subrec = unicast_subnet;
398
399			if (uni_subrec != subrec) {
400				subrec = uni_subrec;
401				namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
402			}
403		}
404		if (!namerec)
405			break;
406
407	}
408
409	SCVAL(countptr,0,names_added);
410
411	/* We don't send any stats as they could be used to attack
412		the protocol. */
413	memset(buf,'\0',46);
414
415	buf += 46;
416
417	/* Send a NODE STATUS RESPONSE */
418	reply_netbios_packet(p,                               /* Packet to reply to. */
419				0,                            /* Result code. */
420				NMB_STATUS,                   /* nmbd type code. */
421				NMB_NAME_QUERY_OPCODE,        /* opcode. */
422				0,                            /* ttl. */
423				rdata,                        /* data to send. */
424				PTR_DIFF(buf,rdata));         /* data length. */
425}
426
427
428/***************************************************************************
429Process a name query.
430
431For broadcast name queries:
432
433  - Only reply if the query is for one of YOUR names.
434  - NEVER send a negative response to a broadcast query.
435
436****************************************************************************/
437
438void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
439{
440	struct nmb_packet *nmb = &p->packet.nmb;
441	struct nmb_name *question = &nmb->question.question_name;
442	int name_type = question->name_type;
443	BOOL bcast = nmb->header.nm_flags.bcast;
444	int ttl=0;
445	int rcode = 0;
446	char *prdata = NULL;
447	char rdata[6];
448	BOOL success = False;
449	struct name_record *namerec = NULL;
450	int reply_data_len = 0;
451	int i;
452
453	DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
454		 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
455
456	/* Look up the name in the cache - if the request is a broadcast request that
457	   came from a subnet we don't know about then search all the broadcast subnets
458	   for a match (as we don't know what interface the request came in on). */
459
460	if(subrec == remote_broadcast_subnet)
461		namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
462	else
463		namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
464
465	/* Check if it is a name that expired */
466	if (namerec &&
467	    ((namerec->data.death_time != PERMANENT_TTL) &&
468	     (namerec->data.death_time < p->timestamp))) {
469		DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
470		namerec = NULL;
471	}
472
473	if (namerec) {
474		/*
475		 * Always respond to unicast queries.
476		 * Don't respond to broadcast queries unless the query is for
477		 * a name we own, a Primary Domain Controller name, or a WINS_PROXY
478		 * name with type 0 or 0x20. WINS_PROXY names are only ever added
479		 * into the namelist if we were configured as a WINS proxy.
480		 */
481
482		if (!bcast ||
483		    (bcast && ((name_type == 0x1b) ||
484			       (namerec->data.source == SELF_NAME) ||
485			       (namerec->data.source == PERMANENT_NAME) ||
486			       ((namerec->data.source == WINS_PROXY_NAME) &&
487				((name_type == 0) || (name_type == 0x20)))))) {
488			/* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
489			   or it's a Domain Master type. */
490
491			/*
492			 * If this is a WINS_PROXY_NAME, then ceck that none of the IP
493			 * addresses we are returning is on the same broadcast subnet
494			 * as the requesting packet. If it is then don't reply as the
495			 * actual machine will be replying also and we don't want two
496			 * replies to a broadcast query.
497			 */
498
499			if (namerec->data.source == WINS_PROXY_NAME) {
500				for( i = 0; i < namerec->data.num_ips; i++) {
501					if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
502						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",
503							 nmb_namestr(&namerec->name), subrec->subnet_name ));
504						return;
505					}
506				}
507			}
508
509			ttl = (namerec->data.death_time != PERMANENT_TTL) ?
510				namerec->data.death_time - p->timestamp : lp_max_ttl();
511
512			/* Copy all known ip addresses into the return data. */
513			/* Optimise for the common case of one IP address so
514			   we don't need a malloc. */
515
516			if (namerec->data.num_ips == 1) {
517				prdata = rdata;
518			} else {
519				if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
520					DEBUG(0,("process_name_query_request: malloc fail !\n"));
521					return;
522				}
523			}
524
525			for (i = 0; i < namerec->data.num_ips; i++) {
526				set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
527				putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
528			}
529
530			sort_query_replies(prdata, i, p->ip);
531
532			reply_data_len = namerec->data.num_ips * 6;
533			success = True;
534		}
535	}
536
537	/*
538	 * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
539	 * set we should initiate a WINS query here. On success we add the resolved name
540	 * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
541	 */
542
543	if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
544	   bcast && (subrec != remote_broadcast_subnet)) {
545		make_wins_proxy_name_query_request( subrec, p, question );
546		return;
547	}
548
549	if (!success && bcast) {
550		if(prdata != rdata)
551			SAFE_FREE(prdata);
552		return; /* Never reply with a negative response to broadcasts. */
553	}
554
555	/*
556	 * Final check. From observation, if a unicast packet is sent
557	 * to a non-WINS server with the recursion desired bit set
558	 * then never send a negative response.
559	 */
560
561	if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
562		if(prdata != rdata)
563			SAFE_FREE(prdata);
564		return;
565	}
566
567	if (success) {
568		rcode = 0;
569		DEBUG(3,("OK\n"));
570	} else {
571		rcode = NAM_ERR;
572		DEBUG(3,("UNKNOWN\n"));
573	}
574
575	/* See rfc1002.txt 4.2.13. */
576
577	reply_netbios_packet(p,                              /* Packet to reply to. */
578			     rcode,                          /* Result code. */
579			     NMB_QUERY,                      /* nmbd type code. */
580			     NMB_NAME_QUERY_OPCODE,          /* opcode. */
581			     ttl,                            /* ttl. */
582			     prdata,                         /* data to send. */
583			     reply_data_len);                /* data length. */
584
585	if(prdata != rdata)
586		SAFE_FREE(prdata);
587}
588