1 /*
2    Unix SMB/CIFS implementation.
3 
4    low level socket handling for nbt requests
5 
6    Copyright (C) Andrew Tridgell 2005
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 
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "lib/util/dlinklist.h"
26 #include "libcli/nbt/libnbt.h"
27 #include "lib/socket/socket.h"
28 #include "librpc/gen_ndr/ndr_nbt.h"
29 
30 #define NBT_MAX_REPLIES 1000
31 
32 /*
33   destroy a pending request
34 */
nbt_name_request_destructor(struct nbt_name_request * req)35 static int nbt_name_request_destructor(struct nbt_name_request *req)
36 {
37 	if (req->state == NBT_REQUEST_SEND) {
38 		DLIST_REMOVE(req->nbtsock->send_queue, req);
39 	}
40 	if (req->state == NBT_REQUEST_WAIT) {
41 		req->nbtsock->num_pending--;
42 	}
43 	if (req->name_trn_id != 0 && !req->is_reply) {
44 		idr_remove(req->nbtsock->idr, req->name_trn_id);
45 		req->name_trn_id = 0;
46 	}
47 	if (req->te) {
48 		talloc_free(req->te);
49 		req->te = NULL;
50 	}
51 	if (req->nbtsock->send_queue == NULL) {
52 		EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde);
53 	}
54 	if (req->nbtsock->num_pending == 0 &&
55 	    req->nbtsock->incoming.handler == NULL) {
56 		EVENT_FD_NOT_READABLE(req->nbtsock->fde);
57 	}
58 
59 	/* once this has been called for this req, don't call again */
60 	talloc_set_destructor(req, NULL);
61 
62 	return 0;
63 }
64 
65 
66 /*
67   handle send events on a nbt name socket
68 */
nbt_name_socket_send(struct nbt_name_socket * nbtsock)69 static void nbt_name_socket_send(struct nbt_name_socket *nbtsock)
70 {
71 	struct nbt_name_request *req = nbtsock->send_queue;
72 	TALLOC_CTX *tmp_ctx = talloc_new(nbtsock);
73 	NTSTATUS status;
74 
75 	while ((req = nbtsock->send_queue)) {
76 		size_t len;
77 
78 		len = req->encoded.length;
79 		status = socket_sendto(nbtsock->sock, &req->encoded, &len,
80 				       req->dest);
81 		if (NT_STATUS_IS_ERR(status)) goto failed;
82 
83 		if (!NT_STATUS_IS_OK(status)) {
84 			talloc_free(tmp_ctx);
85 			return;
86 		}
87 
88 		DLIST_REMOVE(nbtsock->send_queue, req);
89 		req->state = NBT_REQUEST_WAIT;
90 		if (req->is_reply) {
91 			talloc_free(req);
92 		} else {
93 			EVENT_FD_READABLE(nbtsock->fde);
94 			nbtsock->num_pending++;
95 		}
96 	}
97 
98 	EVENT_FD_NOT_WRITEABLE(nbtsock->fde);
99 	talloc_free(tmp_ctx);
100 	return;
101 
102 failed:
103 	DLIST_REMOVE(nbtsock->send_queue, req);
104 	nbt_name_request_destructor(req);
105 	req->status = status;
106 	req->state = NBT_REQUEST_ERROR;
107 	talloc_free(tmp_ctx);
108 	if (req->async.fn) {
109 		req->async.fn(req);
110 	}
111 	return;
112 }
113 
114 
115 /*
116   handle a request timeout
117 */
nbt_name_socket_timeout(struct event_context * ev,struct timed_event * te,struct timeval t,void * private)118 static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event *te,
119 				    struct timeval t, void *private)
120 {
121 	struct nbt_name_request *req = talloc_get_type(private,
122 						       struct nbt_name_request);
123 
124 	if (req->num_retries != 0) {
125 		req->num_retries--;
126 		req->te = event_add_timed(req->nbtsock->event_ctx, req,
127 					  timeval_add(&t, req->timeout, 0),
128 					  nbt_name_socket_timeout, req);
129 		if (req->state != NBT_REQUEST_SEND) {
130 			req->state = NBT_REQUEST_SEND;
131 			DLIST_ADD_END(req->nbtsock->send_queue, req,
132 				      struct nbt_name_request *);
133 		}
134 		EVENT_FD_WRITEABLE(req->nbtsock->fde);
135 		return;
136 	}
137 
138 	nbt_name_request_destructor(req);
139 	if (req->num_replies == 0) {
140 		req->state = NBT_REQUEST_TIMEOUT;
141 		req->status = NT_STATUS_IO_TIMEOUT;
142 	} else {
143 		req->state = NBT_REQUEST_DONE;
144 		req->status = NT_STATUS_OK;
145 	}
146 	if (req->async.fn) {
147 		req->async.fn(req);
148 	}
149 }
150 
151 
152 
153 /*
154   handle recv events on a nbt name socket
155 */
nbt_name_socket_recv(struct nbt_name_socket * nbtsock)156 static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
157 {
158 	TALLOC_CTX *tmp_ctx = talloc_new(nbtsock);
159 	NTSTATUS status;
160 	struct socket_address *src;
161 	DATA_BLOB blob;
162 	size_t nread, dsize;
163 	struct nbt_name_packet *packet;
164 	struct nbt_name_request *req;
165 
166 	status = socket_pending(nbtsock->sock, &dsize);
167 	if (!NT_STATUS_IS_OK(status)) {
168 		talloc_free(tmp_ctx);
169 		return;
170 	}
171 
172 	/*
173 	 * Given a zero length, data_blob_talloc() returns the
174 	 * NULL blob {NULL, 0}.
175 	 *
176 	 * We only want to error return here on a real out of memory condition
177 	 * (i.e. dsize != 0, so the UDP packet has data, but the return of the
178 	 * allocation failed, so blob.data==NULL).
179 	 *
180 	 * Given an actual zero length UDP packet having blob.data == NULL
181 	 * isn't an out of memory error condition, that's the defined semantics
182 	 * of data_blob_talloc() when asked for zero bytes.
183 	 *
184 	 * We still need to continue to do the zero-length socket_recvfrom()
185 	 * read in order to clear the "read pending" condition on the socket.
186 	 */
187 	blob = data_blob_talloc(tmp_ctx, NULL, dsize);
188 	if (blob.data == NULL && dsize != 0) {
189 		talloc_free(tmp_ctx);
190 		return;
191 	}
192 
193 	status = socket_recvfrom(nbtsock->sock, blob.data, blob.length, &nread,
194 				 tmp_ctx, &src);
195 	if (!NT_STATUS_IS_OK(status)) {
196 		talloc_free(tmp_ctx);
197 		return;
198 	}
199 
200 	packet = talloc(tmp_ctx, struct nbt_name_packet);
201 	if (packet == NULL) {
202 		talloc_free(tmp_ctx);
203 		return;
204 	}
205 
206 	/* parse the request */
207 	status = ndr_pull_struct_blob(&blob, packet, packet,
208 				      (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet);
209 	if (!NT_STATUS_IS_OK(status)) {
210 		DEBUG(2,("Failed to parse incoming NBT name packet - %s\n",
211 			 nt_errstr(status)));
212 		talloc_free(tmp_ctx);
213 		return;
214 	}
215 
216 	if (DEBUGLVL(10)) {
217 		DEBUG(10,("Received nbt packet of length %d from %s:%d\n",
218 			  (int)blob.length, src->addr, src->port));
219 		NDR_PRINT_DEBUG(nbt_name_packet, packet);
220 	}
221 
222 	/* if its not a reply then pass it off to the incoming request
223 	   handler, if any */
224 	if (!(packet->operation & NBT_FLAG_REPLY)) {
225 		if (nbtsock->incoming.handler) {
226 			nbtsock->incoming.handler(nbtsock, packet, src);
227 		}
228 		talloc_free(tmp_ctx);
229 		return;
230 	}
231 
232 	/* find the matching request */
233 	req = idr_find(nbtsock->idr, packet->name_trn_id);
234 	if (req == NULL) {
235 		if (nbtsock->unexpected.handler) {
236 			nbtsock->unexpected.handler(nbtsock, packet, src);
237 		} else {
238 			DEBUG(2,("Failed to match request for incoming name packet id 0x%04x on %p\n",
239 				 packet->name_trn_id, nbtsock));
240 		}
241 		talloc_free(tmp_ctx);
242 		return;
243 	}
244 
245 	talloc_steal(req, packet);
246 	talloc_steal(req, src);
247 	talloc_free(tmp_ctx);
248 	nbt_name_socket_handle_response_packet(req, packet, src);
249 }
250 
nbt_name_socket_handle_response_packet(struct nbt_name_request * req,struct nbt_name_packet * packet,struct socket_address * src)251 void nbt_name_socket_handle_response_packet(struct nbt_name_request *req,
252 					    struct nbt_name_packet *packet,
253 					    struct socket_address *src)
254 {
255 	/* if this is a WACK response, this we need to go back to waiting,
256 	   but perhaps increase the timeout */
257 	if ((packet->operation & NBT_OPCODE) == NBT_OPCODE_WACK) {
258 		if (req->received_wack || packet->ancount < 1) {
259 			nbt_name_request_destructor(req);
260 			req->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
261 			req->state  = NBT_REQUEST_ERROR;
262 			goto done;
263 		}
264 		talloc_free(req->te);
265 		/* we know we won't need any more retries - the server
266 		   has received our request */
267 		req->num_retries   = 0;
268 		req->received_wack = True;
269 		/* although there can be a timeout in the packet, w2k3 screws it up,
270 		   so better to set it ourselves */
271 		req->timeout = lp_parm_int(-1, "nbt", "wack_timeout", 30);
272 		req->te = event_add_timed(req->nbtsock->event_ctx, req,
273 					  timeval_current_ofs(req->timeout, 0),
274 					  nbt_name_socket_timeout, req);
275 		return;
276 	}
277 
278 
279 	req->replies = talloc_realloc(req, req->replies, struct nbt_name_reply, req->num_replies+1);
280 	if (req->replies == NULL) {
281 		nbt_name_request_destructor(req);
282 		req->state  = NBT_REQUEST_ERROR;
283 		req->status = NT_STATUS_NO_MEMORY;
284 		goto done;
285 	}
286 
287 	talloc_steal(req, src);
288 	req->replies[req->num_replies].dest   = src;
289 	talloc_steal(req, packet);
290 	req->replies[req->num_replies].packet = packet;
291 	req->num_replies++;
292 
293 	/* if we don't want multiple replies then we are done */
294 	if (req->allow_multiple_replies &&
295 	    req->num_replies < NBT_MAX_REPLIES) {
296 		return;
297 	}
298 
299 	nbt_name_request_destructor(req);
300 	req->state  = NBT_REQUEST_DONE;
301 	req->status = NT_STATUS_OK;
302 
303 done:
304     if (DEBUGLVL(9)) {
305         talloc_report(req, stdout);
306     }
307 	if (req->async.fn) {
308 		req->async.fn(req);
309 	}
310 }
311 
312 /*
313   handle fd events on a nbt_name_socket
314 */
nbt_name_socket_handler(struct event_context * ev,struct fd_event * fde,uint16_t flags,void * private)315 static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *fde,
316 				    uint16_t flags, void *private)
317 {
318 	struct nbt_name_socket *nbtsock = talloc_get_type(private,
319 							  struct nbt_name_socket);
320     if (nbtsock != NULL) {
321         if (flags & EVENT_FD_WRITE) {
322             nbt_name_socket_send(nbtsock);
323         }
324         if (flags & EVENT_FD_READ) {
325             nbt_name_socket_recv(nbtsock);
326         }
327 	}
328 	else {
329 	    DEBUG(9, ("Error condition in nbt_name_socket_handler: nbtsock was not of type struct nbt_name_socket"));
330 	}
331 }
332 
333 
334 /*
335   initialise a nbt_name_socket. The event_ctx is optional, if provided
336   then operations will use that event context
337 */
nbt_name_socket_init(TALLOC_CTX * mem_ctx,struct event_context * event_ctx)338 _PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
339 					     struct event_context *event_ctx)
340 {
341 	struct nbt_name_socket *nbtsock;
342 	NTSTATUS status;
343 
344 	nbtsock = talloc(mem_ctx, struct nbt_name_socket);
345 	if (nbtsock == NULL) goto failed;
346 
347 	if (event_ctx == NULL) {
348 		nbtsock->event_ctx = event_context_init(nbtsock);
349 	} else {
350 		nbtsock->event_ctx = talloc_reference(nbtsock, event_ctx);
351 	}
352 	if (nbtsock->event_ctx == NULL) goto failed;
353 
354 	status = socket_create("ip", SOCKET_TYPE_DGRAM, &nbtsock->sock, 0);
355 	if (!NT_STATUS_IS_OK(status)) goto failed;
356 
357 	socket_set_option(nbtsock->sock, "SO_BROADCAST", "1");
358 
359 	talloc_steal(nbtsock, nbtsock->sock);
360 
361 	nbtsock->idr = idr_init(nbtsock);
362 	if (nbtsock->idr == NULL) goto failed;
363 
364 	nbtsock->send_queue = NULL;
365 	nbtsock->num_pending = 0;
366 	nbtsock->incoming.handler = NULL;
367 	nbtsock->unexpected.handler = NULL;
368 
369 	nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock,
370 				    socket_get_fd(nbtsock->sock), 0,
371 				    nbt_name_socket_handler, nbtsock);
372 
373 	return nbtsock;
374 
375 failed:
376 	talloc_free(nbtsock);
377 	return NULL;
378 }
379 
380 /*
381   send off a nbt name request
382 */
nbt_name_request_send(struct nbt_name_socket * nbtsock,struct socket_address * dest,struct nbt_name_packet * request,int timeout,int retries,BOOL allow_multiple_replies)383 struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
384 					       struct socket_address *dest,
385 					       struct nbt_name_packet *request,
386 					       int timeout, int retries,
387 					       BOOL allow_multiple_replies)
388 {
389 	struct nbt_name_request *req;
390 	int id;
391 	NTSTATUS status;
392 
393 	req = talloc_zero(nbtsock, struct nbt_name_request);
394 	if (req == NULL) goto failed;
395 
396 	req->nbtsock                = nbtsock;
397 	req->allow_multiple_replies = allow_multiple_replies;
398 	req->state                  = NBT_REQUEST_SEND;
399 	req->is_reply               = False;
400 	req->timeout                = timeout;
401 	req->num_retries            = retries;
402 	req->dest                   = dest;
403 	if (talloc_reference(req, dest) == NULL) goto failed;
404 
405 	/* we select a random transaction id unless the user supplied one */
406 	if (request->name_trn_id == 0) {
407 		id = idr_get_new_random(req->nbtsock->idr, req, UINT16_MAX);
408 	} else {
409 		if (idr_find(req->nbtsock->idr, request->name_trn_id)) goto failed;
410 		id = idr_get_new_above(req->nbtsock->idr, req, request->name_trn_id,
411 				       UINT16_MAX);
412 	}
413 	if (id == -1) goto failed;
414 
415 	request->name_trn_id = id;
416 	req->name_trn_id     = id;
417 
418 	req->te = event_add_timed(nbtsock->event_ctx, req,
419 				  timeval_current_ofs(req->timeout, 0),
420 				  nbt_name_socket_timeout, req);
421 
422 	talloc_set_destructor(req, nbt_name_request_destructor);
423 
424 	status = ndr_push_struct_blob(&req->encoded, req, request,
425 				      (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
426 	if (!NT_STATUS_IS_OK(status)) goto failed;
427 
428 	DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
429 
430 	if (DEBUGLVL(10)) {
431 		DEBUG(10,("Queueing nbt packet to %s:%d\n",
432 			  req->dest->addr, req->dest->port));
433 		NDR_PRINT_DEBUG(nbt_name_packet, request);
434 	}
435 
436 	EVENT_FD_WRITEABLE(nbtsock->fde);
437 
438 	return req;
439 
440 failed:
441 	talloc_free(req);
442 	return NULL;
443 }
444 
445 
446 /*
447   send off a nbt name reply
448 */
nbt_name_reply_send(struct nbt_name_socket * nbtsock,struct socket_address * dest,struct nbt_name_packet * request)449 NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
450 			     struct socket_address *dest,
451 			     struct nbt_name_packet *request)
452 {
453 	struct nbt_name_request *req;
454 	NTSTATUS status;
455 
456 	req = talloc_zero(nbtsock, struct nbt_name_request);
457 	NT_STATUS_HAVE_NO_MEMORY(req);
458 
459 	req->nbtsock   = nbtsock;
460 	req->dest = dest;
461 	if (talloc_reference(req, dest) == NULL) goto failed;
462 	req->state     = NBT_REQUEST_SEND;
463 	req->is_reply = True;
464 
465 	talloc_set_destructor(req, nbt_name_request_destructor);
466 
467 	if (DEBUGLVL(10)) {
468 		NDR_PRINT_DEBUG(nbt_name_packet, request);
469 	}
470 
471 	status = ndr_push_struct_blob(&req->encoded, req, request,
472 				      (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
473 	if (!NT_STATUS_IS_OK(status)) {
474 		talloc_free(req);
475 		return status;
476 	}
477 
478 	DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
479 
480 	EVENT_FD_WRITEABLE(nbtsock->fde);
481 
482 	return NT_STATUS_OK;
483 
484 failed:
485 	talloc_free(req);
486 	return NT_STATUS_NO_MEMORY;
487 }
488 
489 /*
490   wait for a nbt request to complete
491 */
nbt_name_request_recv(struct nbt_name_request * req)492 NTSTATUS nbt_name_request_recv(struct nbt_name_request *req)
493 {
494 	if (!req) return NT_STATUS_NO_MEMORY;
495 
496 	while (req->state < NBT_REQUEST_DONE) {
497 		if (event_loop_once(req->nbtsock->event_ctx) != 0) {
498 			req->state = NBT_REQUEST_ERROR;
499 			req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
500 			if (req->async.fn) {
501 				req->async.fn(req);
502 			}
503 		}
504 	}
505 	return req->status;
506 }
507 
508 
509 /*
510   setup a handler for incoming requests
511 */
nbt_set_incoming_handler(struct nbt_name_socket * nbtsock,void (* handler)(struct nbt_name_socket *,struct nbt_name_packet *,struct socket_address *),void * private)512 NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock,
513 				  void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
514 						  struct socket_address *),
515 				  void *private)
516 {
517 	nbtsock->incoming.handler = handler;
518 	nbtsock->incoming.private = private;
519 	EVENT_FD_READABLE(nbtsock->fde);
520 	return NT_STATUS_OK;
521 }
522 
523 
524 /*
525   turn a NBT rcode into a NTSTATUS
526 */
nbt_rcode_to_ntstatus(uint8_t rcode)527 NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode)
528 {
529 	int i;
530 	struct {
531 		enum nbt_rcode rcode;
532 		NTSTATUS status;
533 	} map[] = {
534 		{ NBT_RCODE_FMT, NT_STATUS_INVALID_PARAMETER },
535 		{ NBT_RCODE_SVR, NT_STATUS_SERVER_DISABLED },
536 		{ NBT_RCODE_NAM, NT_STATUS_OBJECT_NAME_NOT_FOUND },
537 		{ NBT_RCODE_IMP, NT_STATUS_NOT_SUPPORTED },
538 		{ NBT_RCODE_RFS, NT_STATUS_ACCESS_DENIED },
539 		{ NBT_RCODE_ACT, NT_STATUS_ADDRESS_ALREADY_EXISTS },
540 		{ NBT_RCODE_CFT, NT_STATUS_CONFLICTING_ADDRESSES }
541 	};
542 	for (i=0;i<ARRAY_SIZE(map);i++) {
543 		if (map[i].rcode == rcode) {
544 			return map[i].status;
545 		}
546 	}
547 	return NT_STATUS_UNSUCCESSFUL;
548 }
549