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/>.
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
;
41 struct nb_packet_client
;
43 struct nb_packet_server
{
44 struct tevent_context
*ev
;
46 struct tevent_fd
*listen_fde
;
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
;
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
,
75 NTSTATUS
nb_packet_server_create(TALLOC_CTX
*mem_ctx
,
76 struct tevent_context
*ev
,
78 struct nb_packet_server
**presult
)
80 struct nb_packet_server
*result
;
84 result
= talloc_zero(mem_ctx
, struct nb_packet_server
);
86 status
= NT_STATUS_NO_MEMORY
;
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
);
98 rc
= listen(result
->listen_sock
, 5);
100 status
= map_nt_error_from_unix(errno
);
103 talloc_set_destructor(result
, nb_packet_server_destructor
);
105 result
->listen_fde
= tevent_add_fd(ev
, result
,
108 nb_packet_server_listener
,
110 if (result
->listen_fde
== NULL
) {
111 status
= NT_STATUS_NO_MEMORY
;
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
);
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
,
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
,
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
;
154 len
= sizeof(sunaddr
);
156 sock
= accept(server
->listen_sock
, (struct sockaddr
*)(void *)&sunaddr
,
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"));
170 ret
= tstream_bsd_existing_socket(client
, sock
, &client
->sock
);
172 DEBUG(10, ("tstream_bsd_existing_socket failed\n"));
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"));
188 req
= tstream_read_packet_send(client
, ev
, client
->sock
,
189 sizeof(struct nb_packet_query
),
190 nb_packet_client_more
, NULL
);
192 DEBUG(10, ("tstream_read_packet_send failed\n"));
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
,
214 struct nb_packet_query q
;
215 if (buflen
> sizeof(struct nb_packet_query
)) {
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
));
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;
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
;
247 nread
= tstream_read_packet_recv(req
, talloc_tos(), &buf
, &err
);
249 if (nread
< (ssize_t
)sizeof(struct nb_packet_query
)) {
250 DEBUG(10, ("read_packet_recv returned %d (%s)\n",
252 (nread
== -1) ? strerror(err
) : "wrong length"));
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"));
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
),
272 if (client
->mailslot_name
== NULL
) {
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
,
286 DEBUG(10, ("tstream_writev_queue_send failed\n"));
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
);
295 DEBUG(10, ("Could not activate reader for client exit "
300 tevent_req_set_callback(req
, nb_packet_client_read_done
,
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
);
311 nwritten
= tstream_writev_queue_recv(req
, &err
);
315 if (nwritten
== -1) {
316 DEBUG(10, ("tstream_writev_queue_recv failed: %s\n",
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
);
331 nread
= tstream_read_packet_recv(req
, talloc_tos(), &buf
, &err
);
334 DEBUG(10, ("Protocol error, received data on write-only "
335 "unexpected socket: 0x%2.2x\n", (*buf
)));
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
;
349 switch (p
->packet_type
) {
351 trn_id
= p
->packet
.nmb
.header
.name_trn_id
;
354 trn_id
= p
->packet
.dgram
.header
.dgm_id
;
357 DEBUG(10, ("Got invalid packet type %d\n",
358 (int)p
->packet_type
));
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
));
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",
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
)) {
390 nb_packet_client_send(c
, p
);
394 struct nb_packet_client_header
{
396 enum packet_type type
;
402 struct nb_packet_client_state
{
403 struct nb_packet_client
*client
;
405 struct nb_packet_client_header hdr
;
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
425 state
= talloc_zero(client
, struct nb_packet_client_state
);
427 DEBUG(10, ("talloc failed\n"));
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
,
449 DEBUG(10, ("tstream_writev_queue_send failed\n"));
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
;
463 nwritten
= tstream_writev_queue_recv(req
, &err
);
468 if (nwritten
== -1) {
469 DEBUG(10, ("tstream_writev_queue failed: %s\n", strerror(err
)));
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
;
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
,
496 const char *mailslot_name
)
498 struct tevent_req
*req
, *subreq
;
499 struct nb_packet_reader_state
*state
;
500 struct tsocket_address
*laddr
;
502 struct tsocket_address
*raddr
;
505 req
= tevent_req_create(mem_ctx
, &state
,
506 struct nb_packet_reader_state
);
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
);
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(),
531 if (tevent_req_nomem(rpath
, req
)) {
532 return tevent_req_post(req
, ev
);
534 ret
= tsocket_address_unix_from_path(state
, rpath
, &raddr
);
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
);
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
);
557 res
= tstream_unix_connect_recv(subreq
, &err
, state
->reader
,
558 &state
->reader
->sock
);
561 DEBUG(10, ("tstream_unix_connect failed: %s\n", strerror(err
)));
562 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
566 state
->iov
[0].iov_base
= (char *)&state
->query
;
567 state
->iov
[0].iov_len
= sizeof(state
->query
);
569 if (state
->mailslot_name
!= NULL
) {
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
)) {
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
);
593 written
= tstream_writev_recv(subreq
, &err
);
596 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
599 if (written
!= sizeof(state
->query
) + state
->query
.mailslot_namelen
) {
600 tevent_req_nterror(req
, NT_STATUS_UNEXPECTED_IO_ERROR
);
603 subreq
= tstream_read_packet_send(state
, state
->ev
,
605 sizeof(state
->c
), NULL
, NULL
);
606 if (tevent_req_nomem(subreq
, req
)) {
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
);
622 nread
= tstream_read_packet_recv(subreq
, state
, &buf
, &err
);
625 DEBUG(10, ("read_packet_recv returned %s\n",
627 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
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
);
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
);
646 if (tevent_req_is_nterror(req
, &status
)) {
647 tevent_req_received(req
);
650 *preader
= talloc_move(mem_ctx
, &state
->reader
);
651 tevent_req_received(req
);
655 struct nb_packet_read_state
{
656 struct nb_packet_client_header hdr
;
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
);
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
);
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
)) {
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
);
709 nread
= tstream_read_packet_recv(subreq
, state
, &state
->buf
, &err
);
711 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
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
;
727 if (tevent_req_is_nterror(req
, &status
)) {
728 tevent_req_received(req
);
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
;
743 tevent_req_received(req
);