libsmb: Give unexpected.c its own header
[Samba.git] / source3 / libsmb / unexpected.c
blob96de1445a677cfa92e67ad7c8183c7ec2df41402
1 /*
2 Unix SMB/CIFS implementation.
3 handle unexpected packets
4 Copyright (C) Andrew Tridgell 2000
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "libsmb/unexpected.h"
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "lib/util_tsock.h"
25 #include "libsmb/nmblib.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "lib/util/sys_rw.h"
29 static const char *nmbd_socket_dir(void)
31 return lp_parm_const_string(-1, "nmbd", "socket dir",
32 get_dyn_NMBDSOCKETDIR());
35 struct nb_packet_query {
36 enum packet_type type;
37 size_t mailslot_namelen;
38 int trn_id;
41 struct nb_packet_client;
43 struct nb_packet_server {
44 struct tevent_context *ev;
45 int listen_sock;
46 struct tevent_fd *listen_fde;
47 int max_clients;
48 int num_clients;
49 struct nb_packet_client *clients;
52 struct nb_packet_client {
53 struct nb_packet_client *prev, *next;
54 struct nb_packet_server *server;
56 enum packet_type type;
57 int trn_id;
58 char *mailslot_name;
60 struct {
61 uint8_t byte;
62 struct iovec iov[1];
63 } ack;
65 struct tstream_context *sock;
66 struct tevent_queue *out_queue;
69 static int nb_packet_server_destructor(struct nb_packet_server *s);
70 static void nb_packet_server_listener(struct tevent_context *ev,
71 struct tevent_fd *fde,
72 uint16_t flags,
73 void *private_data);
75 NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
76 struct tevent_context *ev,
77 int max_clients,
78 struct nb_packet_server **presult)
80 struct nb_packet_server *result;
81 NTSTATUS status;
82 int rc;
84 result = talloc_zero(mem_ctx, struct nb_packet_server);
85 if (result == NULL) {
86 status = NT_STATUS_NO_MEMORY;
87 goto fail;
89 result->ev = ev;
90 result->max_clients = max_clients;
92 result->listen_sock = create_pipe_sock(
93 nmbd_socket_dir(), "unexpected", 0755);
94 if (result->listen_sock == -1) {
95 status = map_nt_error_from_unix(errno);
96 goto fail;
98 rc = listen(result->listen_sock, 5);
99 if (rc < 0) {
100 status = map_nt_error_from_unix(errno);
101 goto fail;
103 talloc_set_destructor(result, nb_packet_server_destructor);
105 result->listen_fde = tevent_add_fd(ev, result,
106 result->listen_sock,
107 TEVENT_FD_READ,
108 nb_packet_server_listener,
109 result);
110 if (result->listen_fde == NULL) {
111 status = NT_STATUS_NO_MEMORY;
112 goto fail;
115 *presult = result;
116 return NT_STATUS_OK;
117 fail:
118 TALLOC_FREE(result);
119 return status;
122 static int nb_packet_server_destructor(struct nb_packet_server *s)
124 TALLOC_FREE(s->listen_fde);
126 if (s->listen_sock != -1) {
127 close(s->listen_sock);
128 s->listen_sock = -1;
130 return 0;
133 static int nb_packet_client_destructor(struct nb_packet_client *c);
134 static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
135 void *private_data);
136 static void nb_packet_got_query(struct tevent_req *req);
137 static void nb_packet_client_ack_done(struct tevent_req *req);
138 static void nb_packet_client_read_done(struct tevent_req *req);
140 static void nb_packet_server_listener(struct tevent_context *ev,
141 struct tevent_fd *fde,
142 uint16_t flags,
143 void *private_data)
145 struct nb_packet_server *server = talloc_get_type_abort(
146 private_data, struct nb_packet_server);
147 struct nb_packet_client *client;
148 struct tevent_req *req;
149 struct sockaddr_un sunaddr;
150 socklen_t len;
151 int sock;
152 int ret;
154 len = sizeof(sunaddr);
156 sock = accept(server->listen_sock, (struct sockaddr *)(void *)&sunaddr,
157 &len);
158 if (sock == -1) {
159 return;
161 smb_set_close_on_exec(sock);
162 DEBUG(6,("accepted socket %d\n", sock));
164 client = talloc_zero(server, struct nb_packet_client);
165 if (client == NULL) {
166 DEBUG(10, ("talloc failed\n"));
167 close(sock);
168 return;
170 ret = tstream_bsd_existing_socket(client, sock, &client->sock);
171 if (ret != 0) {
172 DEBUG(10, ("tstream_bsd_existing_socket failed\n"));
173 close(sock);
174 return;
177 client->server = server;
178 talloc_set_destructor(client, nb_packet_client_destructor);
180 client->out_queue = tevent_queue_create(
181 client, "unexpected packet output");
182 if (client->out_queue == NULL) {
183 DEBUG(10, ("tevent_queue_create failed\n"));
184 TALLOC_FREE(client);
185 return;
188 req = tstream_read_packet_send(client, ev, client->sock,
189 sizeof(struct nb_packet_query),
190 nb_packet_client_more, NULL);
191 if (req == NULL) {
192 DEBUG(10, ("tstream_read_packet_send failed\n"));
193 TALLOC_FREE(client);
194 return;
196 tevent_req_set_callback(req, nb_packet_got_query, client);
198 DLIST_ADD(server->clients, client);
199 server->num_clients += 1;
201 if (server->num_clients > server->max_clients) {
202 DEBUG(10, ("Too many clients, dropping oldest\n"));
205 * no TALLOC_FREE here, don't mess with the list structs
207 talloc_free(server->clients->prev);
211 static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
212 void *private_data)
214 struct nb_packet_query q;
215 if (buflen > sizeof(struct nb_packet_query)) {
216 return 0;
218 /* Take care of alignment */
219 memcpy(&q, buf, sizeof(q));
220 if (q.mailslot_namelen > 1024) {
221 DEBUG(10, ("Got invalid mailslot namelen %d\n",
222 (int)q.mailslot_namelen));
223 return -1;
225 return q.mailslot_namelen;
228 static int nb_packet_client_destructor(struct nb_packet_client *c)
230 tevent_queue_stop(c->out_queue);
231 TALLOC_FREE(c->sock);
233 DLIST_REMOVE(c->server->clients, c);
234 c->server->num_clients -= 1;
235 return 0;
238 static void nb_packet_got_query(struct tevent_req *req)
240 struct nb_packet_client *client = tevent_req_callback_data(
241 req, struct nb_packet_client);
242 struct nb_packet_query q;
243 uint8_t *buf;
244 ssize_t nread;
245 int err;
247 nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
248 TALLOC_FREE(req);
249 if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
250 DEBUG(10, ("read_packet_recv returned %d (%s)\n",
251 (int)nread,
252 (nread == -1) ? strerror(err) : "wrong length"));
253 TALLOC_FREE(client);
254 return;
257 /* Take care of alignment */
258 memcpy(&q, buf, sizeof(q));
260 if (nread != sizeof(struct nb_packet_query) + q.mailslot_namelen) {
261 DEBUG(10, ("nb_packet_got_query: Invalid mailslot namelength\n"));
262 TALLOC_FREE(client);
263 return;
266 client->trn_id = q.trn_id;
267 client->type = q.type;
268 if (q.mailslot_namelen > 0) {
269 client->mailslot_name = talloc_strndup(
270 client, (char *)buf + sizeof(q),
271 q.mailslot_namelen);
272 if (client->mailslot_name == NULL) {
273 TALLOC_FREE(client);
274 return;
278 client->ack.byte = 0;
279 client->ack.iov[0].iov_base = &client->ack.byte;
280 client->ack.iov[0].iov_len = 1;
281 req = tstream_writev_queue_send(client, client->server->ev,
282 client->sock,
283 client->out_queue,
284 client->ack.iov, 1);
285 if (req == NULL) {
286 DEBUG(10, ("tstream_writev_queue_send failed\n"));
287 TALLOC_FREE(client);
288 return;
290 tevent_req_set_callback(req, nb_packet_client_ack_done, client);
292 req = tstream_read_packet_send(client, client->server->ev,
293 client->sock, 1, NULL, NULL);
294 if (req == NULL) {
295 DEBUG(10, ("Could not activate reader for client exit "
296 "detection\n"));
297 TALLOC_FREE(client);
298 return;
300 tevent_req_set_callback(req, nb_packet_client_read_done,
301 client);
304 static void nb_packet_client_ack_done(struct tevent_req *req)
306 struct nb_packet_client *client = tevent_req_callback_data(
307 req, struct nb_packet_client);
308 ssize_t nwritten;
309 int err;
311 nwritten = tstream_writev_queue_recv(req, &err);
313 TALLOC_FREE(req);
315 if (nwritten == -1) {
316 DEBUG(10, ("tstream_writev_queue_recv failed: %s\n",
317 strerror(err)));
318 TALLOC_FREE(client);
319 return;
323 static void nb_packet_client_read_done(struct tevent_req *req)
325 struct nb_packet_client *client = tevent_req_callback_data(
326 req, struct nb_packet_client);
327 ssize_t nread;
328 uint8_t *buf;
329 int err;
331 nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
332 TALLOC_FREE(req);
333 if (nread == 1) {
334 DEBUG(10, ("Protocol error, received data on write-only "
335 "unexpected socket: 0x%2.2x\n", (*buf)));
337 TALLOC_FREE(client);
340 static void nb_packet_client_send(struct nb_packet_client *client,
341 struct packet_struct *p);
343 void nb_packet_dispatch(struct nb_packet_server *server,
344 struct packet_struct *p)
346 struct nb_packet_client *c;
347 uint16_t trn_id;
349 switch (p->packet_type) {
350 case NMB_PACKET:
351 trn_id = p->packet.nmb.header.name_trn_id;
352 break;
353 case DGRAM_PACKET:
354 trn_id = p->packet.dgram.header.dgm_id;
355 break;
356 default:
357 DEBUG(10, ("Got invalid packet type %d\n",
358 (int)p->packet_type));
359 return;
361 for (c = server->clients; c != NULL; c = c->next) {
363 if (c->type != p->packet_type) {
364 DEBUG(10, ("client expects packet %d, got %d\n",
365 c->type, p->packet_type));
366 continue;
369 if (p->packet_type == NMB_PACKET) {
371 * See if the client specified transaction
372 * ID. Filter if it did.
374 if ((c->trn_id != -1) &&
375 (c->trn_id != trn_id)) {
376 DEBUG(10, ("client expects trn %d, got %d\n",
377 c->trn_id, trn_id));
378 continue;
380 } else {
382 * See if the client specified a mailslot
383 * name. Filter if it did.
385 if ((c->mailslot_name != NULL) &&
386 !match_mailslot_name(p, c->mailslot_name)) {
387 continue;
390 nb_packet_client_send(c, p);
394 struct nb_packet_client_header {
395 size_t len;
396 enum packet_type type;
397 time_t timestamp;
398 struct in_addr ip;
399 int port;
402 struct nb_packet_client_state {
403 struct nb_packet_client *client;
404 struct iovec iov[2];
405 struct nb_packet_client_header hdr;
406 char buf[1024];
409 static void nb_packet_client_send_done(struct tevent_req *req);
411 static void nb_packet_client_send(struct nb_packet_client *client,
412 struct packet_struct *p)
414 struct nb_packet_client_state *state;
415 struct tevent_req *req;
417 if (tevent_queue_length(client->out_queue) > 10) {
419 * Skip clients that don't listen anyway, some form of DoS
420 * protection
422 return;
425 state = talloc_zero(client, struct nb_packet_client_state);
426 if (state == NULL) {
427 DEBUG(10, ("talloc failed\n"));
428 return;
431 state->client = client;
433 state->hdr.ip = p->ip;
434 state->hdr.port = p->port;
435 state->hdr.timestamp = p->timestamp;
436 state->hdr.type = p->packet_type;
437 state->hdr.len = build_packet(state->buf, sizeof(state->buf), p);
439 state->iov[0].iov_base = (char *)&state->hdr;
440 state->iov[0].iov_len = sizeof(state->hdr);
441 state->iov[1].iov_base = state->buf;
442 state->iov[1].iov_len = state->hdr.len;
444 req = tstream_writev_queue_send(state, client->server->ev,
445 client->sock,
446 client->out_queue,
447 state->iov, 2);
448 if (req == NULL) {
449 DEBUG(10, ("tstream_writev_queue_send failed\n"));
450 return;
452 tevent_req_set_callback(req, nb_packet_client_send_done, state);
455 static void nb_packet_client_send_done(struct tevent_req *req)
457 struct nb_packet_client_state *state = tevent_req_callback_data(
458 req, struct nb_packet_client_state);
459 struct nb_packet_client *client = state->client;
460 ssize_t nwritten;
461 int err;
463 nwritten = tstream_writev_queue_recv(req, &err);
465 TALLOC_FREE(req);
466 TALLOC_FREE(state);
468 if (nwritten == -1) {
469 DEBUG(10, ("tstream_writev_queue failed: %s\n", strerror(err)));
470 TALLOC_FREE(client);
471 return;
475 struct nb_packet_reader {
476 struct tstream_context *sock;
479 struct nb_packet_reader_state {
480 struct tevent_context *ev;
481 struct nb_packet_query query;
482 const char *mailslot_name;
483 struct iovec iov[2];
484 char c;
485 struct nb_packet_reader *reader;
488 static void nb_packet_reader_connected(struct tevent_req *subreq);
489 static void nb_packet_reader_sent_query(struct tevent_req *subreq);
490 static void nb_packet_reader_got_ack(struct tevent_req *subreq);
492 struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
493 struct tevent_context *ev,
494 enum packet_type type,
495 int trn_id,
496 const char *mailslot_name)
498 struct tevent_req *req, *subreq;
499 struct nb_packet_reader_state *state;
500 struct tsocket_address *laddr;
501 char *rpath;
502 struct tsocket_address *raddr;
503 int ret;
505 req = tevent_req_create(mem_ctx, &state,
506 struct nb_packet_reader_state);
507 if (req == NULL) {
508 return NULL;
510 state->ev = ev;
511 state->query.trn_id = trn_id;
512 state->query.type = type;
513 state->mailslot_name = mailslot_name;
515 if (mailslot_name != NULL) {
516 state->query.mailslot_namelen = strlen(mailslot_name);
519 state->reader = talloc_zero(state, struct nb_packet_reader);
520 if (tevent_req_nomem(state->reader, req)) {
521 return tevent_req_post(req, ev);
524 ret = tsocket_address_unix_from_path(state, "", &laddr);
525 if (ret != 0) {
526 tevent_req_nterror(req, map_nt_error_from_unix(errno));
527 return tevent_req_post(req, ev);
529 rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir(),
530 "unexpected");
531 if (tevent_req_nomem(rpath, req)) {
532 return tevent_req_post(req, ev);
534 ret = tsocket_address_unix_from_path(state, rpath, &raddr);
535 if (ret != 0) {
536 tevent_req_nterror(req, map_nt_error_from_unix(errno));
537 return tevent_req_post(req, ev);
540 subreq = tstream_unix_connect_send(state, ev, laddr, raddr);
541 if (tevent_req_nomem(subreq, req)) {
542 return tevent_req_post(req, ev);
544 tevent_req_set_callback(subreq, nb_packet_reader_connected, req);
545 return req;
548 static void nb_packet_reader_connected(struct tevent_req *subreq)
550 struct tevent_req *req = tevent_req_callback_data(
551 subreq, struct tevent_req);
552 struct nb_packet_reader_state *state = tevent_req_data(
553 req, struct nb_packet_reader_state);
554 int res, err;
555 int num_iovecs = 1;
557 res = tstream_unix_connect_recv(subreq, &err, state->reader,
558 &state->reader->sock);
559 TALLOC_FREE(subreq);
560 if (res == -1) {
561 DEBUG(10, ("tstream_unix_connect failed: %s\n", strerror(err)));
562 tevent_req_nterror(req, map_nt_error_from_unix(err));
563 return;
566 state->iov[0].iov_base = (char *)&state->query;
567 state->iov[0].iov_len = sizeof(state->query);
569 if (state->mailslot_name != NULL) {
570 num_iovecs = 2;
571 state->iov[1].iov_base = discard_const_p(
572 char, state->mailslot_name);
573 state->iov[1].iov_len = state->query.mailslot_namelen;
576 subreq = tstream_writev_send(state, state->ev, state->reader->sock,
577 state->iov, num_iovecs);
578 if (tevent_req_nomem(subreq, req)) {
579 return;
581 tevent_req_set_callback(subreq, nb_packet_reader_sent_query, req);
584 static void nb_packet_reader_sent_query(struct tevent_req *subreq)
586 struct tevent_req *req = tevent_req_callback_data(
587 subreq, struct tevent_req);
588 struct nb_packet_reader_state *state = tevent_req_data(
589 req, struct nb_packet_reader_state);
590 ssize_t written;
591 int err;
593 written = tstream_writev_recv(subreq, &err);
594 TALLOC_FREE(subreq);
595 if (written == -1) {
596 tevent_req_nterror(req, map_nt_error_from_unix(err));
597 return;
599 if (written != sizeof(state->query) + state->query.mailslot_namelen) {
600 tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
601 return;
603 subreq = tstream_read_packet_send(state, state->ev,
604 state->reader->sock,
605 sizeof(state->c), NULL, NULL);
606 if (tevent_req_nomem(subreq, req)) {
607 return;
609 tevent_req_set_callback(subreq, nb_packet_reader_got_ack, req);
612 static void nb_packet_reader_got_ack(struct tevent_req *subreq)
614 struct tevent_req *req = tevent_req_callback_data(
615 subreq, struct tevent_req);
616 struct nb_packet_reader_state *state = tevent_req_data(
617 req, struct nb_packet_reader_state);
618 ssize_t nread;
619 int err;
620 uint8_t *buf;
622 nread = tstream_read_packet_recv(subreq, state, &buf, &err);
623 TALLOC_FREE(subreq);
624 if (nread == -1) {
625 DEBUG(10, ("read_packet_recv returned %s\n",
626 strerror(err)));
627 tevent_req_nterror(req, map_nt_error_from_unix(err));
628 return;
630 if (nread != sizeof(state->c)) {
631 DEBUG(10, ("read = %d, expected %d\n", (int)nread,
632 (int)sizeof(state->c)));
633 tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
634 return;
636 tevent_req_done(req);
639 NTSTATUS nb_packet_reader_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
640 struct nb_packet_reader **preader)
642 struct nb_packet_reader_state *state = tevent_req_data(
643 req, struct nb_packet_reader_state);
644 NTSTATUS status;
646 if (tevent_req_is_nterror(req, &status)) {
647 tevent_req_received(req);
648 return status;
650 *preader = talloc_move(mem_ctx, &state->reader);
651 tevent_req_received(req);
652 return NT_STATUS_OK;
655 struct nb_packet_read_state {
656 struct nb_packet_client_header hdr;
657 uint8_t *buf;
658 size_t buflen;
661 static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p);
662 static void nb_packet_read_done(struct tevent_req *subreq);
664 struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
665 struct tevent_context *ev,
666 struct nb_packet_reader *reader)
668 struct tevent_req *req, *subreq;
669 struct nb_packet_read_state *state;
671 req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
672 if (req == NULL) {
673 return NULL;
675 subreq = tstream_read_packet_send(state, ev, reader->sock,
676 sizeof(struct nb_packet_client_header),
677 nb_packet_read_more, state);
678 if (tevent_req_nomem(subreq, req)) {
679 return tevent_req_post(req, ev);
681 tevent_req_set_callback(subreq, nb_packet_read_done, req);
682 return req;
685 static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
687 struct nb_packet_read_state *state = talloc_get_type_abort(
688 p, struct nb_packet_read_state);
690 if (buflen > sizeof(struct nb_packet_client_header)) {
692 * Been here, done
694 return 0;
696 memcpy(&state->hdr, buf, sizeof(struct nb_packet_client_header));
697 return state->hdr.len;
700 static void nb_packet_read_done(struct tevent_req *subreq)
702 struct tevent_req *req = tevent_req_callback_data(
703 subreq, struct tevent_req);
704 struct nb_packet_read_state *state = tevent_req_data(
705 req, struct nb_packet_read_state);
706 ssize_t nread;
707 int err;
709 nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
710 if (nread == -1) {
711 tevent_req_nterror(req, map_nt_error_from_unix(err));
712 return;
714 state->buflen = nread;
715 tevent_req_done(req);
718 NTSTATUS nb_packet_read_recv(struct tevent_req *req,
719 struct packet_struct **ppacket)
721 struct nb_packet_read_state *state = tevent_req_data(
722 req, struct nb_packet_read_state);
723 struct nb_packet_client_header hdr;
724 struct packet_struct *packet;
725 NTSTATUS status;
727 if (tevent_req_is_nterror(req, &status)) {
728 tevent_req_received(req);
729 return status;
732 memcpy(&hdr, state->buf, sizeof(hdr));
734 packet = parse_packet(
735 (char *)state->buf + sizeof(struct nb_packet_client_header),
736 state->buflen - sizeof(struct nb_packet_client_header),
737 state->hdr.type, state->hdr.ip, state->hdr.port);
738 if (packet == NULL) {
739 tevent_req_received(req);
740 return NT_STATUS_INVALID_NETWORK_RESPONSE;
742 *ppacket = packet;
743 tevent_req_received(req);
744 return NT_STATUS_OK;