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 "../lib/util/tevent_ntstatus.h"
23 #include "lib/async_req/async_sock.h"
24 #include "libsmb/nmblib.h"
25 #include "lib/sys_rw.h"
27 static const char *nmbd_socket_dir(void)
29 return lp_parm_const_string(-1, "nmbd", "socket dir",
30 get_dyn_NMBDSOCKETDIR());
33 struct nb_packet_query
{
34 enum packet_type type
;
35 size_t mailslot_namelen
;
39 struct nb_packet_client
;
41 struct nb_packet_server
{
42 struct tevent_context
*ev
;
46 struct nb_packet_client
*clients
;
49 struct nb_packet_client
{
50 struct nb_packet_client
*prev
, *next
;
51 struct nb_packet_server
*server
;
53 enum packet_type type
;
58 struct tevent_req
*read_req
;
59 struct tevent_queue
*out_queue
;
62 static int nb_packet_server_destructor(struct nb_packet_server
*s
);
63 static void nb_packet_server_listener(struct tevent_context
*ev
,
64 struct tevent_fd
*fde
,
68 NTSTATUS
nb_packet_server_create(TALLOC_CTX
*mem_ctx
,
69 struct tevent_context
*ev
,
71 struct nb_packet_server
**presult
)
73 struct nb_packet_server
*result
;
74 struct tevent_fd
*fde
;
78 result
= talloc_zero(mem_ctx
, struct nb_packet_server
);
80 status
= NT_STATUS_NO_MEMORY
;
84 result
->max_clients
= max_clients
;
86 result
->listen_sock
= create_pipe_sock(
87 nmbd_socket_dir(), "unexpected", 0755);
88 if (result
->listen_sock
== -1) {
89 status
= map_nt_error_from_unix(errno
);
92 rc
= listen(result
->listen_sock
, 5);
94 status
= map_nt_error_from_unix(errno
);
97 talloc_set_destructor(result
, nb_packet_server_destructor
);
99 fde
= tevent_add_fd(ev
, result
, result
->listen_sock
, TEVENT_FD_READ
,
100 nb_packet_server_listener
, result
);
102 status
= NT_STATUS_NO_MEMORY
;
113 static int nb_packet_server_destructor(struct nb_packet_server
*s
)
115 if (s
->listen_sock
!= -1) {
116 close(s
->listen_sock
);
122 static int nb_packet_client_destructor(struct nb_packet_client
*c
);
123 static ssize_t
nb_packet_client_more(uint8_t *buf
, size_t buflen
,
125 static void nb_packet_got_query(struct tevent_req
*req
);
126 static void nb_packet_client_read_done(struct tevent_req
*req
);
128 static void nb_packet_server_listener(struct tevent_context
*ev
,
129 struct tevent_fd
*fde
,
133 struct nb_packet_server
*server
= talloc_get_type_abort(
134 private_data
, struct nb_packet_server
);
135 struct nb_packet_client
*client
;
136 struct tevent_req
*req
;
137 struct sockaddr_un sunaddr
;
141 len
= sizeof(sunaddr
);
143 sock
= accept(server
->listen_sock
, (struct sockaddr
*)(void *)&sunaddr
,
148 DEBUG(6,("accepted socket %d\n", sock
));
150 client
= talloc_zero(server
, struct nb_packet_client
);
151 if (client
== NULL
) {
152 DEBUG(10, ("talloc failed\n"));
157 client
->server
= server
;
158 talloc_set_destructor(client
, nb_packet_client_destructor
);
160 client
->out_queue
= tevent_queue_create(
161 client
, "unexpected packet output");
162 if (client
->out_queue
== NULL
) {
163 DEBUG(10, ("tevent_queue_create failed\n"));
168 req
= read_packet_send(client
, ev
, client
->sock
,
169 sizeof(struct nb_packet_query
),
170 nb_packet_client_more
, NULL
);
172 DEBUG(10, ("read_packet_send failed\n"));
176 tevent_req_set_callback(req
, nb_packet_got_query
, client
);
178 DLIST_ADD(server
->clients
, client
);
179 server
->num_clients
+= 1;
181 if (server
->num_clients
> server
->max_clients
) {
182 DEBUG(10, ("Too many clients, dropping oldest\n"));
185 * no TALLOC_FREE here, don't mess with the list structs
187 talloc_free(server
->clients
->prev
);
191 static ssize_t
nb_packet_client_more(uint8_t *buf
, size_t buflen
,
194 struct nb_packet_query q
;
195 if (buflen
> sizeof(struct nb_packet_query
)) {
198 /* Take care of alignment */
199 memcpy(&q
, buf
, sizeof(q
));
200 if (q
.mailslot_namelen
> 1024) {
201 DEBUG(10, ("Got invalid mailslot namelen %d\n",
202 (int)q
.mailslot_namelen
));
205 return q
.mailslot_namelen
;
208 static int nb_packet_client_destructor(struct nb_packet_client
*c
)
214 DLIST_REMOVE(c
->server
->clients
, c
);
215 c
->server
->num_clients
-= 1;
219 static void nb_packet_got_query(struct tevent_req
*req
)
221 struct nb_packet_client
*client
= tevent_req_callback_data(
222 req
, struct nb_packet_client
);
223 struct nb_packet_query q
;
225 ssize_t nread
, nwritten
;
229 nread
= read_packet_recv(req
, talloc_tos(), &buf
, &err
);
231 if (nread
< (ssize_t
)sizeof(struct nb_packet_query
)) {
232 DEBUG(10, ("read_packet_recv returned %d (%s)\n",
234 (nread
== -1) ? strerror(err
) : "wrong length"));
239 /* Take care of alignment */
240 memcpy(&q
, buf
, sizeof(q
));
242 if (nread
!= sizeof(struct nb_packet_query
) + q
.mailslot_namelen
) {
243 DEBUG(10, ("nb_packet_got_query: Invalid mailslot namelength\n"));
248 client
->trn_id
= q
.trn_id
;
249 client
->type
= q
.type
;
250 if (q
.mailslot_namelen
> 0) {
251 client
->mailslot_name
= talloc_strndup(
252 client
, (char *)buf
+ sizeof(q
),
254 if (client
->mailslot_name
== NULL
) {
261 * Yes, this is a blocking write of 1 byte into a unix
262 * domain socket that has never been written to. Highly
263 * unlikely that this actually blocks.
266 nwritten
= sys_write(client
->sock
, &c
, sizeof(c
));
267 if (nwritten
!= sizeof(c
)) {
268 DEBUG(10, ("Could not write success indicator to client: %s\n",
274 client
->read_req
= read_packet_send(client
, client
->server
->ev
,
275 client
->sock
, 1, NULL
, NULL
);
276 if (client
->read_req
== NULL
) {
277 DEBUG(10, ("Could not activate reader for client exit "
282 tevent_req_set_callback(client
->read_req
, nb_packet_client_read_done
,
286 static void nb_packet_client_read_done(struct tevent_req
*req
)
288 struct nb_packet_client
*client
= tevent_req_callback_data(
289 req
, struct nb_packet_client
);
294 nread
= read_packet_recv(req
, talloc_tos(), &buf
, &err
);
297 DEBUG(10, ("Protocol error, received data on write-only "
298 "unexpected socket: 0x%2.2x\n", (*buf
)));
303 static void nb_packet_client_send(struct nb_packet_client
*client
,
304 struct packet_struct
*p
);
306 void nb_packet_dispatch(struct nb_packet_server
*server
,
307 struct packet_struct
*p
)
309 struct nb_packet_client
*c
;
312 switch (p
->packet_type
) {
314 trn_id
= p
->packet
.nmb
.header
.name_trn_id
;
317 trn_id
= p
->packet
.dgram
.header
.dgm_id
;
320 DEBUG(10, ("Got invalid packet type %d\n",
321 (int)p
->packet_type
));
324 for (c
= server
->clients
; c
!= NULL
; c
= c
->next
) {
326 if (c
->type
!= p
->packet_type
) {
327 DEBUG(10, ("client expects packet %d, got %d\n",
328 c
->type
, p
->packet_type
));
332 if (p
->packet_type
== NMB_PACKET
) {
334 * See if the client specified transaction
335 * ID. Filter if it did.
337 if ((c
->trn_id
!= -1) &&
338 (c
->trn_id
!= trn_id
)) {
339 DEBUG(10, ("client expects trn %d, got %d\n",
345 * See if the client specified a mailslot
346 * name. Filter if it did.
348 if ((c
->mailslot_name
!= NULL
) &&
349 !match_mailslot_name(p
, c
->mailslot_name
)) {
353 nb_packet_client_send(c
, p
);
357 struct nb_packet_client_header
{
359 enum packet_type type
;
365 struct nb_packet_client_state
{
366 struct nb_packet_client
*client
;
368 struct nb_packet_client_header hdr
;
372 static void nb_packet_client_send_done(struct tevent_req
*req
);
374 static void nb_packet_client_send(struct nb_packet_client
*client
,
375 struct packet_struct
*p
)
377 struct nb_packet_client_state
*state
;
378 struct tevent_req
*req
;
380 if (tevent_queue_length(client
->out_queue
) > 10) {
382 * Skip clients that don't listen anyway, some form of DoS
388 state
= talloc_zero(client
, struct nb_packet_client_state
);
390 DEBUG(10, ("talloc failed\n"));
394 state
->client
= client
;
396 state
->hdr
.ip
= p
->ip
;
397 state
->hdr
.port
= p
->port
;
398 state
->hdr
.timestamp
= p
->timestamp
;
399 state
->hdr
.type
= p
->packet_type
;
400 state
->hdr
.len
= build_packet(state
->buf
, sizeof(state
->buf
), p
);
402 state
->iov
[0].iov_base
= (char *)&state
->hdr
;
403 state
->iov
[0].iov_len
= sizeof(state
->hdr
);
404 state
->iov
[1].iov_base
= state
->buf
;
405 state
->iov
[1].iov_len
= state
->hdr
.len
;
407 TALLOC_FREE(client
->read_req
);
409 req
= writev_send(client
, client
->server
->ev
, client
->out_queue
,
410 client
->sock
, true, state
->iov
, 2);
412 DEBUG(10, ("writev_send failed\n"));
415 tevent_req_set_callback(req
, nb_packet_client_send_done
, state
);
418 static void nb_packet_client_send_done(struct tevent_req
*req
)
420 struct nb_packet_client_state
*state
= tevent_req_callback_data(
421 req
, struct nb_packet_client_state
);
422 struct nb_packet_client
*client
= state
->client
;
426 nwritten
= writev_recv(req
, &err
);
431 if (nwritten
== -1) {
432 DEBUG(10, ("writev failed: %s\n", strerror(err
)));
436 if (tevent_queue_length(client
->out_queue
) == 0) {
437 client
->read_req
= read_packet_send(client
, client
->server
->ev
,
440 if (client
->read_req
== NULL
) {
441 DEBUG(10, ("Could not activate reader for client exit "
446 tevent_req_set_callback(client
->read_req
,
447 nb_packet_client_read_done
,
452 struct nb_packet_reader
{
456 struct nb_packet_reader_state
{
457 struct tevent_context
*ev
;
458 struct sockaddr_un addr
;
459 struct nb_packet_query query
;
460 const char *mailslot_name
;
463 struct nb_packet_reader
*reader
;
466 static int nb_packet_reader_destructor(struct nb_packet_reader
*r
);
467 static void nb_packet_reader_connected(struct tevent_req
*subreq
);
468 static void nb_packet_reader_sent_query(struct tevent_req
*subreq
);
469 static void nb_packet_reader_got_ack(struct tevent_req
*subreq
);
471 struct tevent_req
*nb_packet_reader_send(TALLOC_CTX
*mem_ctx
,
472 struct tevent_context
*ev
,
473 enum packet_type type
,
475 const char *mailslot_name
)
477 struct tevent_req
*req
, *subreq
;
478 struct nb_packet_reader_state
*state
;
481 req
= tevent_req_create(mem_ctx
, &state
,
482 struct nb_packet_reader_state
);
487 state
->query
.trn_id
= trn_id
;
488 state
->query
.type
= type
;
489 state
->mailslot_name
= mailslot_name
;
491 if (mailslot_name
!= NULL
) {
492 state
->query
.mailslot_namelen
= strlen(mailslot_name
);
495 state
->reader
= talloc_zero(state
, struct nb_packet_reader
);
496 if (tevent_req_nomem(state
->reader
, req
)) {
497 return tevent_req_post(req
, ev
);
500 path
= talloc_asprintf(talloc_tos(), "%s/%s", nmbd_socket_dir(),
502 if (tevent_req_nomem(path
, req
)) {
503 return tevent_req_post(req
, ev
);
505 state
->addr
.sun_family
= AF_UNIX
;
506 strlcpy(state
->addr
.sun_path
, path
, sizeof(state
->addr
.sun_path
));
509 state
->reader
->sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
510 if (state
->reader
->sock
== -1) {
511 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
512 return tevent_req_post(req
, ev
);
514 talloc_set_destructor(state
->reader
, nb_packet_reader_destructor
);
516 subreq
= async_connect_send(state
, ev
, state
->reader
->sock
,
517 (struct sockaddr
*)(void *)&state
->addr
,
518 sizeof(state
->addr
), NULL
, NULL
, NULL
);
519 if (tevent_req_nomem(subreq
, req
)) {
520 return tevent_req_post(req
, ev
);
522 tevent_req_set_callback(subreq
, nb_packet_reader_connected
, req
);
526 static int nb_packet_reader_destructor(struct nb_packet_reader
*r
)
535 static void nb_packet_reader_connected(struct tevent_req
*subreq
)
537 struct tevent_req
*req
= tevent_req_callback_data(
538 subreq
, struct tevent_req
);
539 struct nb_packet_reader_state
*state
= tevent_req_data(
540 req
, struct nb_packet_reader_state
);
544 res
= async_connect_recv(subreq
, &err
);
547 DEBUG(10, ("async_connect failed: %s\n", strerror(err
)));
548 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
552 state
->iov
[0].iov_base
= (char *)&state
->query
;
553 state
->iov
[0].iov_len
= sizeof(state
->query
);
555 if (state
->mailslot_name
!= NULL
) {
557 state
->iov
[1].iov_base
= discard_const_p(
558 char, state
->mailslot_name
);
559 state
->iov
[1].iov_len
= state
->query
.mailslot_namelen
;
562 subreq
= writev_send(state
, state
->ev
, NULL
, state
->reader
->sock
,
563 true, state
->iov
, num_iovecs
);
564 if (tevent_req_nomem(subreq
, req
)) {
567 tevent_req_set_callback(subreq
, nb_packet_reader_sent_query
, req
);
570 static void nb_packet_reader_sent_query(struct tevent_req
*subreq
)
572 struct tevent_req
*req
= tevent_req_callback_data(
573 subreq
, struct tevent_req
);
574 struct nb_packet_reader_state
*state
= tevent_req_data(
575 req
, struct nb_packet_reader_state
);
579 written
= writev_recv(subreq
, &err
);
582 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
585 if (written
!= sizeof(state
->query
) + state
->query
.mailslot_namelen
) {
586 tevent_req_nterror(req
, NT_STATUS_UNEXPECTED_IO_ERROR
);
589 subreq
= read_packet_send(state
, state
->ev
, state
->reader
->sock
,
590 sizeof(state
->c
), NULL
, NULL
);
591 if (tevent_req_nomem(subreq
, req
)) {
594 tevent_req_set_callback(subreq
, nb_packet_reader_got_ack
, req
);
597 static void nb_packet_reader_got_ack(struct tevent_req
*subreq
)
599 struct tevent_req
*req
= tevent_req_callback_data(
600 subreq
, struct tevent_req
);
601 struct nb_packet_reader_state
*state
= tevent_req_data(
602 req
, struct nb_packet_reader_state
);
607 nread
= read_packet_recv(subreq
, state
, &buf
, &err
);
610 DEBUG(10, ("read_packet_recv returned %s\n",
612 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
615 if (nread
!= sizeof(state
->c
)) {
616 DEBUG(10, ("read = %d, expected %d\n", (int)nread
,
617 (int)sizeof(state
->c
)));
618 tevent_req_nterror(req
, NT_STATUS_UNEXPECTED_IO_ERROR
);
621 tevent_req_done(req
);
624 NTSTATUS
nb_packet_reader_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
625 struct nb_packet_reader
**preader
)
627 struct nb_packet_reader_state
*state
= tevent_req_data(
628 req
, struct nb_packet_reader_state
);
631 if (tevent_req_is_nterror(req
, &status
)) {
634 *preader
= talloc_move(mem_ctx
, &state
->reader
);
638 struct nb_packet_read_state
{
639 struct nb_packet_client_header hdr
;
644 static ssize_t
nb_packet_read_more(uint8_t *buf
, size_t buflen
, void *p
);
645 static void nb_packet_read_done(struct tevent_req
*subreq
);
647 struct tevent_req
*nb_packet_read_send(TALLOC_CTX
*mem_ctx
,
648 struct tevent_context
*ev
,
649 struct nb_packet_reader
*reader
)
651 struct tevent_req
*req
, *subreq
;
652 struct nb_packet_read_state
*state
;
654 req
= tevent_req_create(mem_ctx
, &state
, struct nb_packet_read_state
);
658 subreq
= read_packet_send(state
, ev
, reader
->sock
,
659 sizeof(struct nb_packet_client_header
),
660 nb_packet_read_more
, state
);
661 if (tevent_req_nomem(subreq
, req
)) {
662 return tevent_req_post(req
, ev
);
664 tevent_req_set_callback(subreq
, nb_packet_read_done
, req
);
668 static ssize_t
nb_packet_read_more(uint8_t *buf
, size_t buflen
, void *p
)
670 struct nb_packet_read_state
*state
= talloc_get_type_abort(
671 p
, struct nb_packet_read_state
);
673 if (buflen
> sizeof(struct nb_packet_client_header
)) {
679 memcpy(&state
->hdr
, buf
, sizeof(struct nb_packet_client_header
));
680 return state
->hdr
.len
;
683 static void nb_packet_read_done(struct tevent_req
*subreq
)
685 struct tevent_req
*req
= tevent_req_callback_data(
686 subreq
, struct tevent_req
);
687 struct nb_packet_read_state
*state
= tevent_req_data(
688 req
, struct nb_packet_read_state
);
692 nread
= read_packet_recv(subreq
, state
, &state
->buf
, &err
);
694 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
697 state
->buflen
= nread
;
698 tevent_req_done(req
);
701 NTSTATUS
nb_packet_read_recv(struct tevent_req
*req
,
702 struct packet_struct
**ppacket
)
704 struct nb_packet_read_state
*state
= tevent_req_data(
705 req
, struct nb_packet_read_state
);
706 struct nb_packet_client_header hdr
;
707 struct packet_struct
*packet
;
710 if (tevent_req_is_nterror(req
, &status
)) {
714 memcpy(&hdr
, state
->buf
, sizeof(hdr
));
716 packet
= parse_packet(
717 (char *)state
->buf
+ sizeof(struct nb_packet_client_header
),
718 state
->buflen
- sizeof(struct nb_packet_client_header
),
719 state
->hdr
.type
, state
->hdr
.ip
, state
->hdr
.port
);
720 if (packet
== NULL
) {
721 return NT_STATUS_INVALID_NETWORK_RESPONSE
;