2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "../lib/tsocket/tsocket.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "source3/smbd/smbXsrv_session.h"
27 #include "smbd/smbXsrv_open.h"
28 #include "librpc/gen_ndr/netlogon.h"
29 #include "../lib/async_req/async_sock.h"
30 #include "ctdbd_conn.h"
31 #include "../lib/util/select.h"
32 #include "printing/queue_process.h"
33 #include "system/select.h"
37 #include "lib/messages_ctdb.h"
38 #include "smbprofile.h"
39 #include "rpc_server/spoolss/srv_spoolss_nt.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "../libcli/security/dom_sid.h"
42 #include "../libcli/security/security_token.h"
43 #include "lib/id_cache.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "system/threads.h"
46 #include "lib/pthreadpool/pthreadpool_tevent.h"
47 #include "util_event.h"
48 #include "libcli/smb/smbXcli_base.h"
49 #include "lib/util/time_basic.h"
50 #include "source3/lib/substitute.h"
51 #include "lib/util/util_process.h"
53 /* Internal message queue for deferred opens. */
54 struct pending_message_list
{
55 struct pending_message_list
*next
, *prev
;
56 struct timeval request_time
; /* When was this first issued? */
57 struct smbd_server_connection
*sconn
;
58 struct smbXsrv_connection
*xconn
;
59 struct tevent_timer
*te
;
64 struct deferred_open_record
*open_rec
;
67 static bool smb_splice_chain(uint8_t **poutbuf
, const uint8_t *andx_buf
);
69 void smbd_echo_init(struct smbXsrv_connection
*xconn
)
71 xconn
->smb1
.echo_handler
.trusted_fd
= -1;
72 xconn
->smb1
.echo_handler
.socket_lock_fd
= -1;
73 #ifdef HAVE_ROBUST_MUTEXES
74 xconn
->smb1
.echo_handler
.socket_mutex
= NULL
;
78 static bool smbd_echo_active(struct smbXsrv_connection
*xconn
)
80 if (xconn
->smb1
.echo_handler
.socket_lock_fd
!= -1) {
84 #ifdef HAVE_ROBUST_MUTEXES
85 if (xconn
->smb1
.echo_handler
.socket_mutex
!= NULL
) {
93 static bool smbd_lock_socket_internal(struct smbXsrv_connection
*xconn
)
95 if (!smbd_echo_active(xconn
)) {
99 xconn
->smb1
.echo_handler
.ref_count
++;
101 if (xconn
->smb1
.echo_handler
.ref_count
> 1) {
105 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
107 #ifdef HAVE_ROBUST_MUTEXES
108 if (xconn
->smb1
.echo_handler
.socket_mutex
!= NULL
) {
111 while (ret
== EINTR
) {
112 ret
= pthread_mutex_lock(
113 xconn
->smb1
.echo_handler
.socket_mutex
);
119 DEBUG(1, ("pthread_mutex_lock failed: %s\n",
126 if (xconn
->smb1
.echo_handler
.socket_lock_fd
!= -1) {
131 xconn
->smb1
.echo_handler
.socket_lock_fd
,
132 F_SETLKW
, 0, 0, F_WRLCK
);
133 } while (!ok
&& (errno
== EINTR
));
136 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno
)));
141 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
146 void smbd_lock_socket(struct smbXsrv_connection
*xconn
)
148 if (!smbd_lock_socket_internal(xconn
)) {
149 exit_server_cleanly("failed to lock socket");
153 static bool smbd_unlock_socket_internal(struct smbXsrv_connection
*xconn
)
155 if (!smbd_echo_active(xconn
)) {
159 xconn
->smb1
.echo_handler
.ref_count
--;
161 if (xconn
->smb1
.echo_handler
.ref_count
> 0) {
165 #ifdef HAVE_ROBUST_MUTEXES
166 if (xconn
->smb1
.echo_handler
.socket_mutex
!= NULL
) {
168 ret
= pthread_mutex_unlock(
169 xconn
->smb1
.echo_handler
.socket_mutex
);
171 DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
178 if (xconn
->smb1
.echo_handler
.socket_lock_fd
!= -1) {
183 xconn
->smb1
.echo_handler
.socket_lock_fd
,
184 F_SETLKW
, 0, 0, F_UNLCK
);
185 } while (!ok
&& (errno
== EINTR
));
188 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno
)));
193 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
198 void smbd_unlock_socket(struct smbXsrv_connection
*xconn
)
200 if (!smbd_unlock_socket_internal(xconn
)) {
201 exit_server_cleanly("failed to unlock socket");
205 /* Accessor function for smb_read_error for smbd functions. */
207 /****************************************************************************
209 ****************************************************************************/
211 bool smb1_srv_send(struct smbXsrv_connection
*xconn
,
219 char *buf_out
= buffer
;
221 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
223 * we're not supposed to do any io
228 smbd_lock_socket(xconn
);
233 /* Sign the outgoing packet if required. */
234 status
= smb1_srv_calculate_sign_mac(xconn
, buf_out
, seqnum
);
235 if (!NT_STATUS_IS_OK(status
)) {
236 DBG_ERR("Failed to calculate signing mac: %s\n",
243 NTSTATUS status
= srv_encrypt_buffer(xconn
, buffer
, &buf_out
);
244 if (!NT_STATUS_IS_OK(status
)) {
245 DEBUG(0, ("send_smb: SMB encryption failed "
246 "on outgoing packet! Error %s\n",
247 nt_errstr(status
) ));
253 len
= smb_len_large(buf_out
) + 4;
255 ret
= write_data(xconn
->transport
.sock
, buf_out
, len
);
257 int saved_errno
= errno
;
259 * Try and give an error message saying what
262 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
263 (int)getpid(), (int)len
,
264 smbXsrv_connection_dbg(xconn
),
265 (int)ret
, strerror(saved_errno
)));
268 srv_free_enc_buffer(xconn
, buf_out
);
272 srv_free_enc_buffer(xconn
, buf_out
);
274 smbd_unlock_socket(xconn
);
278 /* Socket functions for smbd packet processing. */
280 static bool valid_packet_size(size_t len
)
283 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
284 * of header. Don't print the error if this fits.... JRA.
287 if (len
> (LARGE_WRITEX_BUFFER_SIZE
+ LARGE_WRITEX_HDR_SIZE
)) {
288 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
289 (unsigned long)len
));
295 /****************************************************************************
296 Attempt a zerocopy writeX read. We know here that len > smb_size-4
297 ****************************************************************************/
300 * Unfortunately, earlier versions of smbclient/libsmbclient
301 * don't send this "standard" writeX header. I've fixed this
302 * for 3.2 but we'll use the old method with earlier versions.
303 * Windows and CIFSFS at least use this standard size. Not
307 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
308 (2*14) + /* word count (including bcc) */ \
311 static NTSTATUS
receive_smb_raw_talloc_partial_read(TALLOC_CTX
*mem_ctx
,
312 const char lenbuf
[4],
313 struct smbXsrv_connection
*xconn
,
316 unsigned int timeout
,
320 /* Size of a WRITEX call (+4 byte len). */
321 char writeX_header
[4 + STANDARD_WRITE_AND_X_HEADER_SIZE
];
322 ssize_t len
= smb_len_large(lenbuf
); /* Could be a UNIX large writeX. */
326 memcpy(writeX_header
, lenbuf
, 4);
328 status
= read_fd_with_timeout(
329 sock
, writeX_header
+ 4,
330 STANDARD_WRITE_AND_X_HEADER_SIZE
,
331 STANDARD_WRITE_AND_X_HEADER_SIZE
,
334 if (!NT_STATUS_IS_OK(status
)) {
335 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
337 smbXsrv_connection_dbg(xconn
),
343 * Ok - now try and see if this is a possible
347 if (is_valid_writeX_buffer(xconn
, (uint8_t *)writeX_header
)) {
349 * If the data offset is beyond what
350 * we've read, drain the extra bytes.
352 uint16_t doff
= SVAL(writeX_header
,smb_vwv11
);
355 if (doff
> STANDARD_WRITE_AND_X_HEADER_SIZE
) {
356 size_t drain
= doff
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
357 if (drain_socket(sock
, drain
) != drain
) {
358 smb_panic("receive_smb_raw_talloc_partial_read:"
359 " failed to drain pending bytes");
362 doff
= STANDARD_WRITE_AND_X_HEADER_SIZE
;
365 /* Spoof down the length and null out the bcc. */
366 set_message_bcc(writeX_header
, 0);
367 newlen
= smb_len(writeX_header
);
369 /* Copy the header we've written. */
371 *buffer
= (char *)talloc_memdup(mem_ctx
,
373 sizeof(writeX_header
));
375 if (*buffer
== NULL
) {
376 DEBUG(0, ("Could not allocate inbuf of length %d\n",
377 (int)sizeof(writeX_header
)));
378 return NT_STATUS_NO_MEMORY
;
381 /* Work out the remaining bytes. */
382 *p_unread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
383 *len_ret
= newlen
+ 4;
387 if (!valid_packet_size(len
)) {
388 return NT_STATUS_INVALID_PARAMETER
;
392 * Not a valid writeX call. Just do the standard
396 *buffer
= talloc_array(mem_ctx
, char, len
+4);
398 if (*buffer
== NULL
) {
399 DEBUG(0, ("Could not allocate inbuf of length %d\n",
401 return NT_STATUS_NO_MEMORY
;
404 /* Copy in what we already read. */
407 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
);
408 toread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
411 status
= read_packet_remainder(
413 (*buffer
) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
,
416 if (!NT_STATUS_IS_OK(status
)) {
417 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
427 static NTSTATUS
receive_smb_raw_talloc(TALLOC_CTX
*mem_ctx
,
428 struct smbXsrv_connection
*xconn
,
430 char **buffer
, unsigned int timeout
,
431 size_t *p_unread
, size_t *plen
)
435 int min_recv_size
= lp_min_receive_file_size();
440 status
= read_smb_length_return_keepalive(sock
, lenbuf
, timeout
,
442 if (!NT_STATUS_IS_OK(status
)) {
446 if (CVAL(lenbuf
,0) == 0 && min_recv_size
&&
447 (smb_len_large(lenbuf
) > /* Could be a UNIX large writeX. */
448 (min_recv_size
+ STANDARD_WRITE_AND_X_HEADER_SIZE
)) &&
449 !smb1_srv_is_signing_active(xconn
) &&
450 xconn
->smb1
.echo_handler
.trusted_fde
== NULL
) {
452 return receive_smb_raw_talloc_partial_read(
453 mem_ctx
, lenbuf
, xconn
, sock
, buffer
, timeout
,
457 if (!valid_packet_size(len
)) {
458 return NT_STATUS_INVALID_PARAMETER
;
462 * The +4 here can't wrap, we've checked the length above already.
465 *buffer
= talloc_array(mem_ctx
, char, len
+4);
467 if (*buffer
== NULL
) {
468 DEBUG(0, ("Could not allocate inbuf of length %d\n",
470 return NT_STATUS_NO_MEMORY
;
473 memcpy(*buffer
, lenbuf
, sizeof(lenbuf
));
475 status
= read_packet_remainder(sock
, (*buffer
)+4, timeout
, len
);
476 if (!NT_STATUS_IS_OK(status
)) {
484 NTSTATUS
smb1_receive_talloc(TALLOC_CTX
*mem_ctx
,
485 struct smbXsrv_connection
*xconn
,
487 char **buffer
, unsigned int timeout
,
488 size_t *p_unread
, bool *p_encrypted
,
491 bool trusted_channel
)
496 *p_encrypted
= false;
498 status
= receive_smb_raw_talloc(mem_ctx
, xconn
, sock
, buffer
, timeout
,
500 if (!NT_STATUS_IS_OK(status
)) {
501 DEBUG(NT_STATUS_EQUAL(status
, NT_STATUS_END_OF_FILE
)?5:1,
502 ("receive_smb_raw_talloc failed for client %s "
503 "read error = %s.\n",
504 smbXsrv_connection_dbg(xconn
),
505 nt_errstr(status
)) );
509 if (is_encrypted_packet((uint8_t *)*buffer
)) {
510 status
= srv_decrypt_buffer(xconn
, *buffer
);
511 if (!NT_STATUS_IS_OK(status
)) {
512 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
513 "incoming packet! Error %s\n",
514 nt_errstr(status
) ));
520 /* Check the incoming SMB signature. */
521 if (!smb1_srv_check_sign_mac(xconn
, *buffer
, seqnum
, trusted_channel
)) {
522 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
523 "incoming packet!\n"));
524 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
531 /****************************************************************************
532 Function to push a message onto the tail of a linked list of smb messages ready
534 ****************************************************************************/
536 static bool push_queued_message(struct smb_request
*req
,
537 struct timeval request_time
,
538 struct timeval end_time
,
539 struct deferred_open_record
*open_rec
)
541 int msg_len
= smb_len(req
->inbuf
) + 4;
542 struct pending_message_list
*msg
;
544 msg
= talloc_zero(NULL
, struct pending_message_list
);
547 DEBUG(0,("push_message: malloc fail (1)\n"));
550 msg
->sconn
= req
->sconn
;
551 msg
->xconn
= req
->xconn
;
553 msg
->buf
= data_blob_talloc(msg
, req
->inbuf
, msg_len
);
554 if(msg
->buf
.data
== NULL
) {
555 DEBUG(0,("push_message: malloc fail (2)\n"));
560 msg
->request_time
= request_time
;
561 msg
->seqnum
= req
->seqnum
;
562 msg
->encrypted
= req
->encrypted
;
563 msg
->processed
= false;
566 msg
->open_rec
= talloc_move(msg
, &open_rec
);
570 msg
->te
= tevent_add_timer(msg
->sconn
->ev_ctx
,
573 smbd_deferred_open_timer
,
576 DEBUG(0,("push_message: event_add_timed failed\n"));
582 DLIST_ADD_END(req
->sconn
->deferred_open_queue
, msg
);
584 DEBUG(10,("push_message: pushed message length %u on "
585 "deferred_open_queue\n", (unsigned int)msg_len
));
590 /****************************************************************************
591 Function to push a deferred open smb message onto a linked list of local smb
592 messages ready for processing.
593 ****************************************************************************/
595 bool push_deferred_open_message_smb1(struct smb_request
*req
,
596 struct timeval timeout
,
598 struct deferred_open_record
*open_rec
)
600 struct timeval_buf tvbuf
;
601 struct timeval end_time
;
603 if (req
->unread_bytes
) {
604 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
605 "unread_bytes = %u\n",
606 (unsigned int)req
->unread_bytes
));
607 smb_panic("push_deferred_open_message_smb: "
608 "logic error unread_bytes != 0" );
611 end_time
= timeval_sum(&req
->request_time
, &timeout
);
613 DBG_DEBUG("pushing message len %u mid %"PRIu64
" timeout time [%s]\n",
614 (unsigned int) smb_len(req
->inbuf
)+4,
616 timeval_str_buf(&end_time
, false, true, &tvbuf
));
618 return push_queued_message(req
, req
->request_time
, end_time
, open_rec
);
622 * Only allow 5 outstanding trans requests. We're allocating memory, so
626 NTSTATUS
allow_new_trans(struct trans_state
*list
, uint64_t mid
)
629 for (; list
!= NULL
; list
= list
->next
) {
631 if (list
->mid
== mid
) {
632 return NT_STATUS_INVALID_PARAMETER
;
638 return NT_STATUS_INSUFFICIENT_RESOURCES
;
645 These flags determine some of the permissions required to do an operation
647 Note that I don't set NEED_WRITE on some write operations because they
648 are used by some brain-dead clients when printing, and I don't want to
649 force write permissions on print services.
651 #define AS_USER (1<<0)
652 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
653 #define TIME_INIT (1<<2)
654 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
655 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
656 #define DO_CHDIR (1<<6)
659 define a list of possible SMB messages and their corresponding
660 functions. Any message that has a NULL function is unimplemented -
661 please feel free to contribute implementations!
663 static const struct smb_message_struct
{
665 void (*fn
)(struct smb_request
*req
);
667 } smb_messages
[256] = {
669 /* 0x00 */ { "SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
670 /* 0x01 */ { "SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
671 /* 0x02 */ { "SMBopen",reply_open
,AS_USER
},
672 /* 0x03 */ { "SMBcreate",reply_mknew
,AS_USER
},
673 /* 0x04 */ { "SMBclose",reply_close
,AS_USER
| CAN_IPC
},
674 /* 0x05 */ { "SMBflush",reply_flush
,AS_USER
},
675 /* 0x06 */ { "SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
676 /* 0x07 */ { "SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
677 /* 0x08 */ { "SMBgetatr",reply_getatr
,AS_USER
},
678 /* 0x09 */ { "SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
679 /* 0x0a */ { "SMBread",reply_read
,AS_USER
},
680 /* 0x0b */ { "SMBwrite",reply_write
,AS_USER
| CAN_IPC
},
681 /* 0x0c */ { "SMBlock",reply_lock
,AS_USER
},
682 /* 0x0d */ { "SMBunlock",reply_unlock
,AS_USER
},
683 /* 0x0e */ { "SMBctemp",reply_ctemp
,AS_USER
},
684 /* 0x0f */ { "SMBmknew",reply_mknew
,AS_USER
},
685 /* 0x10 */ { "SMBcheckpath",reply_checkpath
,AS_USER
},
686 /* 0x11 */ { "SMBexit",reply_exit
,DO_CHDIR
},
687 /* 0x12 */ { "SMBlseek",reply_lseek
,AS_USER
},
688 /* 0x13 */ { "SMBlockread",reply_lockread
,AS_USER
},
689 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock
,AS_USER
},
690 /* 0x15 */ { NULL
, NULL
, 0 },
691 /* 0x16 */ { NULL
, NULL
, 0 },
692 /* 0x17 */ { NULL
, NULL
, 0 },
693 /* 0x18 */ { NULL
, NULL
, 0 },
694 /* 0x19 */ { NULL
, NULL
, 0 },
695 /* 0x1a */ { "SMBreadbraw",reply_readbraw
,AS_USER
},
696 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx
,AS_USER
},
697 /* 0x1c */ { "SMBreadBs",reply_readbs
,AS_USER
},
698 /* 0x1d */ { "SMBwritebraw",reply_writebraw
,AS_USER
},
699 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx
,AS_USER
},
700 /* 0x1f */ { "SMBwriteBs",reply_writebs
,AS_USER
},
701 /* 0x20 */ { "SMBwritec", NULL
,0},
702 /* 0x21 */ { NULL
, NULL
, 0 },
703 /* 0x22 */ { "SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
704 /* 0x23 */ { "SMBgetattrE",reply_getattrE
,AS_USER
},
705 /* 0x24 */ { "SMBlockingX",reply_lockingX
,AS_USER
},
706 /* 0x25 */ { "SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
707 /* 0x26 */ { "SMBtranss",reply_transs
,AS_USER
| CAN_IPC
},
708 /* 0x27 */ { "SMBioctl",reply_ioctl
,0},
709 /* 0x28 */ { "SMBioctls", NULL
,AS_USER
},
710 /* 0x29 */ { "SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
711 /* 0x2a */ { "SMBmove", NULL
,AS_USER
| NEED_WRITE
},
712 /* 0x2b */ { "SMBecho",reply_echo
,0},
713 /* 0x2c */ { "SMBwriteclose",reply_writeclose
,AS_USER
},
714 /* 0x2d */ { "SMBopenX",reply_open_and_X
,AS_USER
| CAN_IPC
},
715 /* 0x2e */ { "SMBreadX",reply_read_and_X
,AS_USER
| CAN_IPC
},
716 /* 0x2f */ { "SMBwriteX",reply_write_and_X
,AS_USER
| CAN_IPC
},
717 /* 0x30 */ { NULL
, NULL
, 0 },
718 /* 0x31 */ { NULL
, NULL
, 0 },
719 /* 0x32 */ { "SMBtrans2",reply_trans2
, AS_USER
| CAN_IPC
},
720 /* 0x33 */ { "SMBtranss2",reply_transs2
, AS_USER
| CAN_IPC
},
721 /* 0x34 */ { "SMBfindclose",reply_findclose
,AS_USER
},
722 /* 0x35 */ { "SMBfindnclose",reply_findnclose
,AS_USER
},
723 /* 0x36 */ { NULL
, NULL
, 0 },
724 /* 0x37 */ { NULL
, NULL
, 0 },
725 /* 0x38 */ { NULL
, NULL
, 0 },
726 /* 0x39 */ { NULL
, NULL
, 0 },
727 /* 0x3a */ { NULL
, NULL
, 0 },
728 /* 0x3b */ { NULL
, NULL
, 0 },
729 /* 0x3c */ { NULL
, NULL
, 0 },
730 /* 0x3d */ { NULL
, NULL
, 0 },
731 /* 0x3e */ { NULL
, NULL
, 0 },
732 /* 0x3f */ { NULL
, NULL
, 0 },
733 /* 0x40 */ { NULL
, NULL
, 0 },
734 /* 0x41 */ { NULL
, NULL
, 0 },
735 /* 0x42 */ { NULL
, NULL
, 0 },
736 /* 0x43 */ { NULL
, NULL
, 0 },
737 /* 0x44 */ { NULL
, NULL
, 0 },
738 /* 0x45 */ { NULL
, NULL
, 0 },
739 /* 0x46 */ { NULL
, NULL
, 0 },
740 /* 0x47 */ { NULL
, NULL
, 0 },
741 /* 0x48 */ { NULL
, NULL
, 0 },
742 /* 0x49 */ { NULL
, NULL
, 0 },
743 /* 0x4a */ { NULL
, NULL
, 0 },
744 /* 0x4b */ { NULL
, NULL
, 0 },
745 /* 0x4c */ { NULL
, NULL
, 0 },
746 /* 0x4d */ { NULL
, NULL
, 0 },
747 /* 0x4e */ { NULL
, NULL
, 0 },
748 /* 0x4f */ { NULL
, NULL
, 0 },
749 /* 0x50 */ { NULL
, NULL
, 0 },
750 /* 0x51 */ { NULL
, NULL
, 0 },
751 /* 0x52 */ { NULL
, NULL
, 0 },
752 /* 0x53 */ { NULL
, NULL
, 0 },
753 /* 0x54 */ { NULL
, NULL
, 0 },
754 /* 0x55 */ { NULL
, NULL
, 0 },
755 /* 0x56 */ { NULL
, NULL
, 0 },
756 /* 0x57 */ { NULL
, NULL
, 0 },
757 /* 0x58 */ { NULL
, NULL
, 0 },
758 /* 0x59 */ { NULL
, NULL
, 0 },
759 /* 0x5a */ { NULL
, NULL
, 0 },
760 /* 0x5b */ { NULL
, NULL
, 0 },
761 /* 0x5c */ { NULL
, NULL
, 0 },
762 /* 0x5d */ { NULL
, NULL
, 0 },
763 /* 0x5e */ { NULL
, NULL
, 0 },
764 /* 0x5f */ { NULL
, NULL
, 0 },
765 /* 0x60 */ { NULL
, NULL
, 0 },
766 /* 0x61 */ { NULL
, NULL
, 0 },
767 /* 0x62 */ { NULL
, NULL
, 0 },
768 /* 0x63 */ { NULL
, NULL
, 0 },
769 /* 0x64 */ { NULL
, NULL
, 0 },
770 /* 0x65 */ { NULL
, NULL
, 0 },
771 /* 0x66 */ { NULL
, NULL
, 0 },
772 /* 0x67 */ { NULL
, NULL
, 0 },
773 /* 0x68 */ { NULL
, NULL
, 0 },
774 /* 0x69 */ { NULL
, NULL
, 0 },
775 /* 0x6a */ { NULL
, NULL
, 0 },
776 /* 0x6b */ { NULL
, NULL
, 0 },
777 /* 0x6c */ { NULL
, NULL
, 0 },
778 /* 0x6d */ { NULL
, NULL
, 0 },
779 /* 0x6e */ { NULL
, NULL
, 0 },
780 /* 0x6f */ { NULL
, NULL
, 0 },
781 /* 0x70 */ { "SMBtcon",reply_tcon
,0},
782 /* 0x71 */ { "SMBtdis",reply_tdis
,DO_CHDIR
},
783 /* 0x72 */ { "SMBnegprot",reply_negprot
,0},
784 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X
,0},
785 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX
, 0}, /* ulogoff doesn't give a valid TID */
786 /* 0x75 */ { "SMBtconX",reply_tcon_and_X
,0},
787 /* 0x76 */ { NULL
, NULL
, 0 },
788 /* 0x77 */ { NULL
, NULL
, 0 },
789 /* 0x78 */ { NULL
, NULL
, 0 },
790 /* 0x79 */ { NULL
, NULL
, 0 },
791 /* 0x7a */ { NULL
, NULL
, 0 },
792 /* 0x7b */ { NULL
, NULL
, 0 },
793 /* 0x7c */ { NULL
, NULL
, 0 },
794 /* 0x7d */ { NULL
, NULL
, 0 },
795 /* 0x7e */ { NULL
, NULL
, 0 },
796 /* 0x7f */ { NULL
, NULL
, 0 },
797 /* 0x80 */ { "SMBdskattr",reply_dskattr
,AS_USER
},
798 /* 0x81 */ { "SMBsearch",reply_search
,AS_USER
},
799 /* 0x82 */ { "SMBffirst",reply_search
,AS_USER
},
800 /* 0x83 */ { "SMBfunique",reply_search
,AS_USER
},
801 /* 0x84 */ { "SMBfclose",reply_fclose
,AS_USER
},
802 /* 0x85 */ { NULL
, NULL
, 0 },
803 /* 0x86 */ { NULL
, NULL
, 0 },
804 /* 0x87 */ { NULL
, NULL
, 0 },
805 /* 0x88 */ { NULL
, NULL
, 0 },
806 /* 0x89 */ { NULL
, NULL
, 0 },
807 /* 0x8a */ { NULL
, NULL
, 0 },
808 /* 0x8b */ { NULL
, NULL
, 0 },
809 /* 0x8c */ { NULL
, NULL
, 0 },
810 /* 0x8d */ { NULL
, NULL
, 0 },
811 /* 0x8e */ { NULL
, NULL
, 0 },
812 /* 0x8f */ { NULL
, NULL
, 0 },
813 /* 0x90 */ { NULL
, NULL
, 0 },
814 /* 0x91 */ { NULL
, NULL
, 0 },
815 /* 0x92 */ { NULL
, NULL
, 0 },
816 /* 0x93 */ { NULL
, NULL
, 0 },
817 /* 0x94 */ { NULL
, NULL
, 0 },
818 /* 0x95 */ { NULL
, NULL
, 0 },
819 /* 0x96 */ { NULL
, NULL
, 0 },
820 /* 0x97 */ { NULL
, NULL
, 0 },
821 /* 0x98 */ { NULL
, NULL
, 0 },
822 /* 0x99 */ { NULL
, NULL
, 0 },
823 /* 0x9a */ { NULL
, NULL
, 0 },
824 /* 0x9b */ { NULL
, NULL
, 0 },
825 /* 0x9c */ { NULL
, NULL
, 0 },
826 /* 0x9d */ { NULL
, NULL
, 0 },
827 /* 0x9e */ { NULL
, NULL
, 0 },
828 /* 0x9f */ { NULL
, NULL
, 0 },
829 /* 0xa0 */ { "SMBnttrans",reply_nttrans
, AS_USER
| CAN_IPC
},
830 /* 0xa1 */ { "SMBnttranss",reply_nttranss
, AS_USER
| CAN_IPC
},
831 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X
, AS_USER
| CAN_IPC
},
832 /* 0xa3 */ { NULL
, NULL
, 0 },
833 /* 0xa4 */ { "SMBntcancel",reply_ntcancel
, 0 },
834 /* 0xa5 */ { "SMBntrename",reply_ntrename
, AS_USER
| NEED_WRITE
},
835 /* 0xa6 */ { NULL
, NULL
, 0 },
836 /* 0xa7 */ { NULL
, NULL
, 0 },
837 /* 0xa8 */ { NULL
, NULL
, 0 },
838 /* 0xa9 */ { NULL
, NULL
, 0 },
839 /* 0xaa */ { NULL
, NULL
, 0 },
840 /* 0xab */ { NULL
, NULL
, 0 },
841 /* 0xac */ { NULL
, NULL
, 0 },
842 /* 0xad */ { NULL
, NULL
, 0 },
843 /* 0xae */ { NULL
, NULL
, 0 },
844 /* 0xaf */ { NULL
, NULL
, 0 },
845 /* 0xb0 */ { NULL
, NULL
, 0 },
846 /* 0xb1 */ { NULL
, NULL
, 0 },
847 /* 0xb2 */ { NULL
, NULL
, 0 },
848 /* 0xb3 */ { NULL
, NULL
, 0 },
849 /* 0xb4 */ { NULL
, NULL
, 0 },
850 /* 0xb5 */ { NULL
, NULL
, 0 },
851 /* 0xb6 */ { NULL
, NULL
, 0 },
852 /* 0xb7 */ { NULL
, NULL
, 0 },
853 /* 0xb8 */ { NULL
, NULL
, 0 },
854 /* 0xb9 */ { NULL
, NULL
, 0 },
855 /* 0xba */ { NULL
, NULL
, 0 },
856 /* 0xbb */ { NULL
, NULL
, 0 },
857 /* 0xbc */ { NULL
, NULL
, 0 },
858 /* 0xbd */ { NULL
, NULL
, 0 },
859 /* 0xbe */ { NULL
, NULL
, 0 },
860 /* 0xbf */ { NULL
, NULL
, 0 },
861 /* 0xc0 */ { "SMBsplopen",reply_printopen
,AS_USER
},
862 /* 0xc1 */ { "SMBsplwr",reply_printwrite
,AS_USER
},
863 /* 0xc2 */ { "SMBsplclose",reply_printclose
,AS_USER
},
864 /* 0xc3 */ { "SMBsplretq",reply_printqueue
,AS_USER
},
865 /* 0xc4 */ { NULL
, NULL
, 0 },
866 /* 0xc5 */ { NULL
, NULL
, 0 },
867 /* 0xc6 */ { NULL
, NULL
, 0 },
868 /* 0xc7 */ { NULL
, NULL
, 0 },
869 /* 0xc8 */ { NULL
, NULL
, 0 },
870 /* 0xc9 */ { NULL
, NULL
, 0 },
871 /* 0xca */ { NULL
, NULL
, 0 },
872 /* 0xcb */ { NULL
, NULL
, 0 },
873 /* 0xcc */ { NULL
, NULL
, 0 },
874 /* 0xcd */ { NULL
, NULL
, 0 },
875 /* 0xce */ { NULL
, NULL
, 0 },
876 /* 0xcf */ { NULL
, NULL
, 0 },
877 /* 0xd0 */ { "SMBsends",reply_sends
,AS_GUEST
},
878 /* 0xd1 */ { "SMBsendb", NULL
,AS_GUEST
},
879 /* 0xd2 */ { "SMBfwdname", NULL
,AS_GUEST
},
880 /* 0xd3 */ { "SMBcancelf", NULL
,AS_GUEST
},
881 /* 0xd4 */ { "SMBgetmac", NULL
,AS_GUEST
},
882 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt
,AS_GUEST
},
883 /* 0xd6 */ { "SMBsendend",reply_sendend
,AS_GUEST
},
884 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt
,AS_GUEST
},
885 /* 0xd8 */ { NULL
, NULL
, 0 },
886 /* 0xd9 */ { NULL
, NULL
, 0 },
887 /* 0xda */ { NULL
, NULL
, 0 },
888 /* 0xdb */ { NULL
, NULL
, 0 },
889 /* 0xdc */ { NULL
, NULL
, 0 },
890 /* 0xdd */ { NULL
, NULL
, 0 },
891 /* 0xde */ { NULL
, NULL
, 0 },
892 /* 0xdf */ { NULL
, NULL
, 0 },
893 /* 0xe0 */ { NULL
, NULL
, 0 },
894 /* 0xe1 */ { NULL
, NULL
, 0 },
895 /* 0xe2 */ { NULL
, NULL
, 0 },
896 /* 0xe3 */ { NULL
, NULL
, 0 },
897 /* 0xe4 */ { NULL
, NULL
, 0 },
898 /* 0xe5 */ { NULL
, NULL
, 0 },
899 /* 0xe6 */ { NULL
, NULL
, 0 },
900 /* 0xe7 */ { NULL
, NULL
, 0 },
901 /* 0xe8 */ { NULL
, NULL
, 0 },
902 /* 0xe9 */ { NULL
, NULL
, 0 },
903 /* 0xea */ { NULL
, NULL
, 0 },
904 /* 0xeb */ { NULL
, NULL
, 0 },
905 /* 0xec */ { NULL
, NULL
, 0 },
906 /* 0xed */ { NULL
, NULL
, 0 },
907 /* 0xee */ { NULL
, NULL
, 0 },
908 /* 0xef */ { NULL
, NULL
, 0 },
909 /* 0xf0 */ { NULL
, NULL
, 0 },
910 /* 0xf1 */ { NULL
, NULL
, 0 },
911 /* 0xf2 */ { NULL
, NULL
, 0 },
912 /* 0xf3 */ { NULL
, NULL
, 0 },
913 /* 0xf4 */ { NULL
, NULL
, 0 },
914 /* 0xf5 */ { NULL
, NULL
, 0 },
915 /* 0xf6 */ { NULL
, NULL
, 0 },
916 /* 0xf7 */ { NULL
, NULL
, 0 },
917 /* 0xf8 */ { NULL
, NULL
, 0 },
918 /* 0xf9 */ { NULL
, NULL
, 0 },
919 /* 0xfa */ { NULL
, NULL
, 0 },
920 /* 0xfb */ { NULL
, NULL
, 0 },
921 /* 0xfc */ { NULL
, NULL
, 0 },
922 /* 0xfd */ { NULL
, NULL
, 0 },
923 /* 0xfe */ { NULL
, NULL
, 0 },
924 /* 0xff */ { NULL
, NULL
, 0 }
929 /*******************************************************************
930 Dump a packet to a file.
931 ********************************************************************/
933 static void smb_dump(const char *name
, int type
, const char *data
)
938 if (DEBUGLEVEL
< 50) {
942 len
= smb_len_tcp(data
)+4;
943 for (i
=1;i
<100;i
++) {
944 fname
= talloc_asprintf(talloc_tos(),
948 type
? "req" : "resp");
952 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644);
953 if (fd
!= -1 || errno
!= EEXIST
) break;
957 ssize_t ret
= write(fd
, data
, len
);
959 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret
));
961 DEBUG(0,("created %s len %lu\n", fname
, (unsigned long)len
));
966 static void smb1srv_update_crypto_flags(struct smbXsrv_session
*session
,
967 struct smb_request
*req
,
969 bool *update_session_globalp
,
970 bool *update_tcon_globalp
)
972 connection_struct
*conn
= req
->conn
;
973 struct smbXsrv_tcon
*tcon
= conn
? conn
->tcon
: NULL
;
974 uint8_t encrypt_flag
= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
;
975 uint8_t sign_flag
= SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
976 bool update_session
= false;
977 bool update_tcon
= false;
979 if (req
->encrypted
) {
980 encrypt_flag
= SMBXSRV_PROCESSED_ENCRYPTED_PACKET
;
983 if (smb1_srv_is_signing_active(req
->xconn
)) {
984 sign_flag
= SMBXSRV_PROCESSED_SIGNED_PACKET
;
985 } else if ((type
== SMBecho
) || (type
== SMBsesssetupX
)) {
987 * echo can be unsigned. Session setup except final
988 * session setup response too
990 sign_flag
&= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
993 update_session
|= smbXsrv_set_crypto_flag(
994 &session
->global
->encryption_flags
, encrypt_flag
);
995 update_session
|= smbXsrv_set_crypto_flag(
996 &session
->global
->signing_flags
, sign_flag
);
999 update_tcon
|= smbXsrv_set_crypto_flag(
1000 &tcon
->global
->encryption_flags
, encrypt_flag
);
1001 update_tcon
|= smbXsrv_set_crypto_flag(
1002 &tcon
->global
->signing_flags
, sign_flag
);
1005 if (update_session
) {
1006 session
->global
->channels
[0].encryption_cipher
= SMB_ENCRYPTION_GSSAPI
;
1009 *update_session_globalp
= update_session
;
1010 *update_tcon_globalp
= update_tcon
;
1014 static void set_current_case_sensitive(connection_struct
*conn
, uint16_t flags
)
1017 enum remote_arch_types ra_type
;
1019 SMB_ASSERT(conn
!= NULL
);
1020 SMB_ASSERT(!conn_using_smb2(conn
->sconn
));
1025 * Obey the client case sensitivity requests - only for clients that
1027 switch (lp_case_sensitive(snum
)) {
1030 * We need this ugliness due to DOS/Win9x clients that lie
1031 * about case insensitivity. */
1032 ra_type
= get_remote_arch();
1033 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
1035 * Client can't support per-packet case sensitive
1037 conn
->case_sensitive
= false;
1039 conn
->case_sensitive
=
1040 !(flags
& FLAG_CASELESS_PATHNAMES
);
1044 conn
->case_sensitive
= true;
1047 conn
->case_sensitive
= false;
1052 /****************************************************************************
1053 Prepare everything for calling the actual request function, and potentially
1054 call the request function via the "new" interface.
1056 Return False if the "legacy" function needs to be called, everything is
1059 Return True if we're done.
1061 I know this API sucks, but it is the one with the least code change I could
1063 ****************************************************************************/
1065 static connection_struct
*switch_message(uint8_t type
, struct smb_request
*req
)
1067 const struct loadparm_substitution
*lp_sub
=
1068 loadparm_s3_global_substitution();
1070 uint64_t session_tag
;
1071 connection_struct
*conn
= NULL
;
1072 struct smbXsrv_connection
*xconn
= req
->xconn
;
1073 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1074 struct smbXsrv_session
*session
= NULL
;
1079 if (!xconn
->smb1
.negprot
.done
) {
1082 * Without a negprot the request must
1083 * either be a negprot, or one of the
1084 * evil old SMB mailslot messaging types.
1092 exit_server_cleanly("The first request "
1093 "should be a negprot");
1097 if (smb_messages
[type
].fn
== NULL
) {
1098 DEBUG(0,("Unknown message type %d!\n",type
));
1099 smb_dump("Unknown", 1, (const char *)req
->inbuf
);
1100 reply_unknown_new(req
, type
);
1104 flags
= smb_messages
[type
].flags
;
1106 /* In share mode security we must ignore the vuid. */
1107 session_tag
= req
->vuid
;
1110 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type
),
1111 (int)getpid(), (unsigned long)conn
));
1113 smb_dump(smb_fn_name(type
), 1, (const char *)req
->inbuf
);
1115 /* Ensure this value is replaced in the incoming packet. */
1116 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_uid
,session_tag
);
1119 * Ensure the correct username is in current_user_info. This is a
1120 * really ugly bugfix for problems with multiple session_setup_and_X's
1121 * being done and allowing %U and %G substitutions to work correctly.
1122 * There is a reason this code is done here, don't move it unless you
1123 * know what you're doing... :-).
1128 * lookup an existing session
1130 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1131 * here, the main check is still in change_to_user()
1133 status
= smb1srv_session_lookup(xconn
,
1137 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1140 status
= NT_STATUS_OK
;
1143 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1144 (unsigned long long)session_tag
,
1145 (unsigned long long)req
->mid
));
1146 reply_nterror(req
, NT_STATUS_NETWORK_SESSION_EXPIRED
);
1151 if (session
!= NULL
&&
1152 session
->global
->auth_session_info
!= NULL
&&
1156 * change_to_user() implies set_current_user_info()
1157 * and chdir_connect_service().
1159 * So we only call set_current_user_info if
1160 * we don't have AS_USER specified.
1162 set_current_user_info(
1163 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
1164 session
->global
->auth_session_info
->unix_info
->unix_name
,
1165 session
->global
->auth_session_info
->info
->domain_name
);
1168 /* Does this call need to be run as the connected user? */
1169 if (flags
& AS_USER
) {
1171 /* Does this call need a valid tree connection? */
1174 * Amazingly, the error code depends on the command
1177 if (type
== SMBntcreateX
) {
1178 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1180 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
1185 set_current_case_sensitive(conn
, SVAL(req
->inbuf
,smb_flg
));
1188 * change_to_user() implies set_current_user_info()
1189 * and chdir_connect_service().
1191 if (!change_to_user_and_service(conn
,session_tag
)) {
1192 DEBUG(0, ("Error: Could not change to user. Removing "
1193 "deferred open, mid=%llu.\n",
1194 (unsigned long long)req
->mid
));
1195 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
1199 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1201 /* Does it need write permission? */
1202 if ((flags
& NEED_WRITE
) && !CAN_WRITE(conn
)) {
1203 reply_nterror(req
, NT_STATUS_MEDIA_WRITE_PROTECTED
);
1207 /* IPC services are limited */
1208 if (IS_IPC(conn
) && !(flags
& CAN_IPC
)) {
1209 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1212 } else if (flags
& AS_GUEST
) {
1214 * Does this protocol need to be run as guest? (Only archane
1215 * messenger service requests have this...)
1217 if (!change_to_guest()) {
1218 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1222 /* This call needs to be run as root */
1223 change_to_root_user();
1226 /* load service specific parameters */
1228 if (req
->encrypted
) {
1229 conn
->encrypted_tid
= true;
1230 /* encrypted required from now on. */
1231 conn
->encrypt_level
= SMB_SIGNING_REQUIRED
;
1232 } else if (ENCRYPTION_REQUIRED(conn
)) {
1233 if (req
->cmd
!= SMBtrans2
&& req
->cmd
!= SMBtranss2
) {
1234 DEBUG(1,("service[%s] requires encryption"
1235 "%s ACCESS_DENIED. mid=%llu\n",
1236 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
1238 (unsigned long long)req
->mid
));
1239 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1244 if (flags
& DO_CHDIR
) {
1247 ok
= chdir_current_service(conn
);
1249 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1253 conn
->num_smb_operations
++;
1257 * Update encryption and signing state tracking flags that are
1258 * used by smbstatus to display signing and encryption status.
1260 if (session
!= NULL
) {
1261 bool update_session_global
= false;
1262 bool update_tcon_global
= false;
1264 req
->session
= session
;
1266 smb1srv_update_crypto_flags(session
, req
, type
,
1267 &update_session_global
,
1268 &update_tcon_global
);
1270 if (update_session_global
) {
1271 status
= smbXsrv_session_update(session
);
1272 if (!NT_STATUS_IS_OK(status
)) {
1273 reply_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1278 if (update_tcon_global
) {
1279 status
= smbXsrv_tcon_update(req
->conn
->tcon
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 reply_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1287 smb_messages
[type
].fn(req
);
1291 /****************************************************************************
1292 Construct a reply to the incoming packet.
1293 ****************************************************************************/
1295 void construct_reply(struct smbXsrv_connection
*xconn
,
1298 size_t unread_bytes
,
1302 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
1303 struct smb_request
*req
;
1305 if (!(req
= talloc(talloc_tos(), struct smb_request
))) {
1306 smb_panic("could not allocate smb_request");
1309 if (!init_smb1_request(req
, sconn
, xconn
, (uint8_t *)inbuf
, unread_bytes
,
1310 encrypted
, seqnum
)) {
1311 exit_server_cleanly("Invalid SMB request");
1314 req
->inbuf
= (uint8_t *)talloc_move(req
, &inbuf
);
1316 req
->conn
= switch_message(req
->cmd
, req
);
1318 if (req
->outbuf
== NULL
) {
1320 * Request has suspended itself, will come
1325 if (CVAL(req
->outbuf
,0) == 0) {
1326 show_msg((char *)req
->outbuf
);
1328 smb_request_done(req
);
1331 static void construct_reply_chain(struct smbXsrv_connection
*xconn
,
1337 struct smb_request
**reqs
= NULL
;
1338 struct smb_request
*req
;
1342 ok
= smb1_parse_chain(xconn
, (uint8_t *)inbuf
, xconn
, encrypted
,
1343 seqnum
, &reqs
, &num_reqs
);
1345 char errbuf
[smb_size
];
1346 error_packet(errbuf
, 0, 0, NT_STATUS_INVALID_PARAMETER
,
1347 __LINE__
, __FILE__
);
1348 if (!smb1_srv_send(xconn
, errbuf
, true, seqnum
, encrypted
)) {
1349 exit_server_cleanly("construct_reply_chain: "
1350 "smb1_srv_send failed.");
1356 req
->inbuf
= (uint8_t *)talloc_move(reqs
, &inbuf
);
1358 req
->conn
= switch_message(req
->cmd
, req
);
1360 if (req
->outbuf
== NULL
) {
1362 * Request has suspended itself, will come
1367 smb_request_done(req
);
1371 * To be called from an async SMB handler that is potentially chained
1372 * when it is finished for shipping.
1375 void smb_request_done(struct smb_request
*req
)
1377 struct smb_request
**reqs
= NULL
;
1378 struct smb_request
*first_req
;
1379 size_t i
, num_reqs
, next_index
;
1382 if (req
->chain
== NULL
) {
1388 num_reqs
= talloc_array_length(reqs
);
1390 for (i
=0; i
<num_reqs
; i
++) {
1391 if (reqs
[i
] == req
) {
1395 if (i
== num_reqs
) {
1397 * Invalid chain, should not happen
1399 status
= NT_STATUS_INTERNAL_ERROR
;
1404 while ((next_index
< num_reqs
) && (IVAL(req
->outbuf
, smb_rcls
) == 0)) {
1405 struct smb_request
*next
= reqs
[next_index
];
1406 struct smbXsrv_tcon
*tcon
;
1407 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1409 next
->vuid
= SVAL(req
->outbuf
, smb_uid
);
1410 next
->tid
= SVAL(req
->outbuf
, smb_tid
);
1411 status
= smb1srv_tcon_lookup(req
->xconn
, next
->tid
,
1414 if (NT_STATUS_IS_OK(status
)) {
1415 next
->conn
= tcon
->compat
;
1419 next
->chain_fsp
= req
->chain_fsp
;
1420 next
->inbuf
= req
->inbuf
;
1423 req
->conn
= switch_message(req
->cmd
, req
);
1425 if (req
->outbuf
== NULL
) {
1427 * Request has suspended itself, will come
1435 first_req
= reqs
[0];
1437 for (i
=1; i
<next_index
; i
++) {
1440 ok
= smb_splice_chain(&first_req
->outbuf
, reqs
[i
]->outbuf
);
1442 status
= NT_STATUS_INTERNAL_ERROR
;
1447 SSVAL(first_req
->outbuf
, smb_uid
, SVAL(req
->outbuf
, smb_uid
));
1448 SSVAL(first_req
->outbuf
, smb_tid
, SVAL(req
->outbuf
, smb_tid
));
1451 * This scary statement intends to set the
1452 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1453 * to the value last_req->outbuf carries
1455 SSVAL(first_req
->outbuf
, smb_flg2
,
1456 (SVAL(first_req
->outbuf
, smb_flg2
) & ~FLAGS2_32_BIT_ERROR_CODES
)
1457 |(SVAL(req
->outbuf
, smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
));
1460 * Transfer the error codes from the subrequest to the main one
1462 SSVAL(first_req
->outbuf
, smb_rcls
, SVAL(req
->outbuf
, smb_rcls
));
1463 SSVAL(first_req
->outbuf
, smb_err
, SVAL(req
->outbuf
, smb_err
));
1466 first_req
->outbuf
, talloc_get_size(first_req
->outbuf
) - 4);
1469 if (!smb1_srv_send(first_req
->xconn
,
1470 (char *)first_req
->outbuf
,
1472 first_req
->seqnum
+ 1,
1473 IS_CONN_ENCRYPTED(req
->conn
) ||
1474 first_req
->encrypted
)) {
1475 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1478 TALLOC_FREE(req
); /* non-chained case */
1479 TALLOC_FREE(reqs
); /* chained case */
1484 char errbuf
[smb_size
];
1485 error_packet(errbuf
, 0, 0, status
, __LINE__
, __FILE__
);
1486 if (!smb1_srv_send(req
->xconn
,
1491 exit_server_cleanly("construct_reply_chain: "
1492 "smb1_srv_send failed.");
1495 TALLOC_FREE(req
); /* non-chained case */
1496 TALLOC_FREE(reqs
); /* chained case */
1499 /****************************************************************************
1500 Process an smb from the client
1501 ****************************************************************************/
1503 void process_smb1(struct smbXsrv_connection
*xconn
,
1506 size_t unread_bytes
,
1510 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
1512 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1513 * so subtract 4 from it. */
1514 if ((nread
< (smb_size
- 4)) || !valid_smb1_header(inbuf
)) {
1515 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1518 /* special magic for immediate exit */
1520 (IVAL(inbuf
, 4) == SMB_SUICIDE_PACKET
) &&
1521 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1522 uint8_t exitcode
= CVAL(inbuf
, 8);
1523 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1528 exit_server_cleanly("Non-SMB packet");
1531 show_msg((char *)inbuf
);
1533 if ((unread_bytes
== 0) && smb1_is_chain(inbuf
)) {
1534 construct_reply_chain(xconn
,
1540 construct_reply(xconn
,
1551 /****************************************************************************
1552 Return a string containing the function name of a SMB command.
1553 ****************************************************************************/
1555 const char *smb_fn_name(int type
)
1557 const char *unknown_name
= "SMBunknown";
1559 if (smb_messages
[type
].name
== NULL
)
1560 return(unknown_name
);
1562 return(smb_messages
[type
].name
);
1565 /****************************************************************************
1566 Helper functions for contruct_reply.
1567 ****************************************************************************/
1569 void add_to_common_flags2(uint32_t v
)
1574 void remove_from_common_flags2(uint32_t v
)
1576 common_flags2
&= ~v
;
1580 * @brief Find the smb_cmd offset of the last command pushed
1581 * @param[in] buf The buffer we're building up
1582 * @retval Where can we put our next andx cmd?
1584 * While chaining requests, the "next" request we're looking at needs to put
1585 * its SMB_Command before the data the previous request already built up added
1586 * to the chain. Find the offset to the place where we have to put our cmd.
1589 static bool find_andx_cmd_ofs(uint8_t *buf
, size_t *pofs
)
1594 cmd
= CVAL(buf
, smb_com
);
1596 if (!smb1cli_is_andx_req(cmd
)) {
1602 while (CVAL(buf
, ofs
) != 0xff) {
1604 if (!smb1cli_is_andx_req(CVAL(buf
, ofs
))) {
1609 * ofs is from start of smb header, so add the 4 length
1610 * bytes. The next cmd is right after the wct field.
1612 ofs
= SVAL(buf
, ofs
+2) + 4 + 1;
1614 if (ofs
+4 >= talloc_get_size(buf
)) {
1624 * @brief Do the smb chaining at a buffer level
1625 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1626 * @param[in] andx_buf Buffer to be appended
1629 static bool smb_splice_chain(uint8_t **poutbuf
, const uint8_t *andx_buf
)
1631 uint8_t smb_command
= CVAL(andx_buf
, smb_com
);
1632 uint8_t wct
= CVAL(andx_buf
, smb_wct
);
1633 const uint16_t *vwv
= (const uint16_t *)(andx_buf
+ smb_vwv
);
1634 uint32_t num_bytes
= smb_buflen(andx_buf
);
1635 const uint8_t *bytes
= (const uint8_t *)smb_buf_const(andx_buf
);
1638 size_t old_size
, new_size
;
1640 size_t chain_padding
= 0;
1641 size_t andx_cmd_ofs
;
1644 old_size
= talloc_get_size(*poutbuf
);
1646 if ((old_size
% 4) != 0) {
1648 * Align the wct field of subsequent requests to a 4-byte
1651 chain_padding
= 4 - (old_size
% 4);
1655 * After the old request comes the new wct field (1 byte), the vwv's
1656 * and the num_bytes field.
1659 new_size
= old_size
+ chain_padding
+ 1 + wct
* sizeof(uint16_t) + 2;
1660 new_size
+= num_bytes
;
1662 if ((smb_command
!= SMBwriteX
) && (new_size
> 0xffff)) {
1663 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1664 (unsigned)new_size
));
1668 outbuf
= talloc_realloc(NULL
, *poutbuf
, uint8_t, new_size
);
1669 if (outbuf
== NULL
) {
1670 DEBUG(0, ("talloc failed\n"));
1675 if (!find_andx_cmd_ofs(outbuf
, &andx_cmd_ofs
)) {
1676 DEBUG(1, ("invalid command chain\n"));
1677 *poutbuf
= talloc_realloc(NULL
, *poutbuf
, uint8_t, old_size
);
1681 if (chain_padding
!= 0) {
1682 memset(outbuf
+ old_size
, 0, chain_padding
);
1683 old_size
+= chain_padding
;
1686 SCVAL(outbuf
, andx_cmd_ofs
, smb_command
);
1687 SSVAL(outbuf
, andx_cmd_ofs
+ 2, old_size
- 4);
1692 * Push the chained request:
1697 SCVAL(outbuf
, ofs
, wct
);
1704 memcpy(outbuf
+ ofs
, vwv
, sizeof(uint16_t) * wct
);
1709 * Read&X has an offset into its data buffer at
1710 * vwv[6]. reply_read_andx has no idea anymore that it's
1711 * running from within a chain, so we have to fix up the
1714 * Although it looks disgusting at this place, I want to keep
1715 * it here. The alternative would be to push knowledge about
1716 * the andx chain down into read&x again.
1719 if (smb_command
== SMBreadX
) {
1720 uint8_t *bytes_addr
;
1724 * Invalid read&x response
1729 bytes_addr
= outbuf
+ ofs
/* vwv start */
1730 + sizeof(uint16_t) * wct
/* vwv array */
1731 + sizeof(uint16_t) /* bcc */
1732 + 1; /* padding byte */
1734 SSVAL(outbuf
+ ofs
, 6 * sizeof(uint16_t),
1735 bytes_addr
- outbuf
- 4);
1738 ofs
+= sizeof(uint16_t) * wct
;
1744 SSVAL(outbuf
, ofs
, num_bytes
);
1745 ofs
+= sizeof(uint16_t);
1751 memcpy(outbuf
+ ofs
, bytes
, num_bytes
);
1756 bool smb1_is_chain(const uint8_t *buf
)
1758 uint8_t cmd
, wct
, andx_cmd
;
1760 cmd
= CVAL(buf
, smb_com
);
1761 if (!smb1cli_is_andx_req(cmd
)) {
1764 wct
= CVAL(buf
, smb_wct
);
1768 andx_cmd
= CVAL(buf
, smb_vwv
);
1769 return (andx_cmd
!= 0xFF);
1772 bool smb1_walk_chain(const uint8_t *buf
,
1773 bool (*fn
)(uint8_t cmd
,
1774 uint8_t wct
, const uint16_t *vwv
,
1775 uint16_t num_bytes
, const uint8_t *bytes
,
1776 void *private_data
),
1779 size_t smblen
= smb_len(buf
);
1780 const char *smb_buf
= smb_base(buf
);
1781 uint8_t cmd
, chain_cmd
;
1783 const uint16_t *vwv
;
1785 const uint8_t *bytes
;
1787 cmd
= CVAL(buf
, smb_com
);
1788 wct
= CVAL(buf
, smb_wct
);
1789 vwv
= (const uint16_t *)(buf
+ smb_vwv
);
1790 num_bytes
= smb_buflen(buf
);
1791 bytes
= (const uint8_t *)smb_buf_const(buf
);
1793 if (!fn(cmd
, wct
, vwv
, num_bytes
, bytes
, private_data
)) {
1797 if (!smb1cli_is_andx_req(cmd
)) {
1804 chain_cmd
= CVAL(vwv
, 0);
1806 while (chain_cmd
!= 0xff) {
1807 uint32_t chain_offset
; /* uint32_t to avoid overflow */
1808 size_t length_needed
;
1809 ptrdiff_t vwv_offset
;
1811 chain_offset
= SVAL(vwv
+1, 0);
1814 * Check if the client tries to fool us. The chain
1815 * offset needs to point beyond the current request in
1816 * the chain, it needs to strictly grow. Otherwise we
1817 * might be tricked into an endless loop always
1818 * processing the same request over and over again. We
1819 * used to assume that vwv and the byte buffer array
1820 * in a chain are always attached, but OS/2 the
1821 * Write&X/Read&X chain puts the Read&X vwv array
1822 * right behind the Write&X vwv chain. The Write&X bcc
1823 * array is put behind the Read&X vwv array. So now we
1824 * check whether the chain offset points strictly
1825 * behind the previous vwv array. req->buf points
1826 * right after the vwv array of the previous
1828 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1832 vwv_offset
= ((const char *)vwv
- smb_buf
);
1833 if (chain_offset
<= vwv_offset
) {
1838 * Next check: Make sure the chain offset does not
1839 * point beyond the overall smb request length.
1842 length_needed
= chain_offset
+1; /* wct */
1843 if (length_needed
> smblen
) {
1848 * Now comes the pointer magic. Goal here is to set up
1849 * vwv and buf correctly again. The chain offset (the
1850 * former vwv[1]) points at the new wct field.
1853 wct
= CVAL(smb_buf
, chain_offset
);
1855 if (smb1cli_is_andx_req(chain_cmd
) && (wct
< 2)) {
1860 * Next consistency check: Make the new vwv array fits
1861 * in the overall smb request.
1864 length_needed
+= (wct
+1)*sizeof(uint16_t); /* vwv+buflen */
1865 if (length_needed
> smblen
) {
1868 vwv
= (const uint16_t *)(smb_buf
+ chain_offset
+ 1);
1871 * Now grab the new byte buffer....
1874 num_bytes
= SVAL(vwv
+wct
, 0);
1877 * .. and check that it fits.
1880 length_needed
+= num_bytes
;
1881 if (length_needed
> smblen
) {
1884 bytes
= (const uint8_t *)(vwv
+wct
+1);
1886 if (!fn(chain_cmd
, wct
, vwv
, num_bytes
, bytes
, private_data
)) {
1890 if (!smb1cli_is_andx_req(chain_cmd
)) {
1893 chain_cmd
= CVAL(vwv
, 0);
1898 static bool smb1_chain_length_cb(uint8_t cmd
,
1899 uint8_t wct
, const uint16_t *vwv
,
1900 uint16_t num_bytes
, const uint8_t *bytes
,
1903 unsigned *count
= (unsigned *)private_data
;
1908 unsigned smb1_chain_length(const uint8_t *buf
)
1912 if (!smb1_walk_chain(buf
, smb1_chain_length_cb
, &count
)) {
1918 struct smb1_parse_chain_state
{
1919 TALLOC_CTX
*mem_ctx
;
1921 struct smbd_server_connection
*sconn
;
1922 struct smbXsrv_connection
*xconn
;
1926 struct smb_request
**reqs
;
1930 static bool smb1_parse_chain_cb(uint8_t cmd
,
1931 uint8_t wct
, const uint16_t *vwv
,
1932 uint16_t num_bytes
, const uint8_t *bytes
,
1935 struct smb1_parse_chain_state
*state
=
1936 (struct smb1_parse_chain_state
*)private_data
;
1937 struct smb_request
**reqs
;
1938 struct smb_request
*req
;
1941 reqs
= talloc_realloc(state
->mem_ctx
, state
->reqs
,
1942 struct smb_request
*, state
->num_reqs
+1);
1948 req
= talloc(reqs
, struct smb_request
);
1953 ok
= init_smb1_request(req
, state
->sconn
, state
->xconn
, state
->buf
, 0,
1954 state
->encrypted
, state
->seqnum
);
1961 req
->buflen
= num_bytes
;
1964 reqs
[state
->num_reqs
] = req
;
1965 state
->num_reqs
+= 1;
1969 bool smb1_parse_chain(TALLOC_CTX
*mem_ctx
, const uint8_t *buf
,
1970 struct smbXsrv_connection
*xconn
,
1971 bool encrypted
, uint32_t seqnum
,
1972 struct smb_request
***reqs
, unsigned *num_reqs
)
1974 struct smbd_server_connection
*sconn
= NULL
;
1975 struct smb1_parse_chain_state state
;
1978 if (xconn
!= NULL
) {
1979 sconn
= xconn
->client
->sconn
;
1982 state
.mem_ctx
= mem_ctx
;
1984 state
.sconn
= sconn
;
1985 state
.xconn
= xconn
;
1986 state
.encrypted
= encrypted
;
1987 state
.seqnum
= seqnum
;
1991 if (!smb1_walk_chain(buf
, smb1_parse_chain_cb
, &state
)) {
1992 TALLOC_FREE(state
.reqs
);
1995 for (i
=0; i
<state
.num_reqs
; i
++) {
1996 state
.reqs
[i
]->chain
= state
.reqs
;
1999 *num_reqs
= state
.num_reqs
;
2003 static bool fd_is_readable(int fd
)
2007 ret
= poll_one_fd(fd
, POLLIN
|POLLHUP
, 0, &revents
);
2009 return ((ret
> 0) && ((revents
& (POLLIN
|POLLHUP
|POLLERR
)) != 0));
2013 static void smbd_server_connection_write_handler(
2014 struct smbXsrv_connection
*xconn
)
2016 /* TODO: make write nonblocking */
2019 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection
*xconn
,
2022 uint8_t *inbuf
= NULL
;
2023 size_t inbuf_len
= 0;
2024 size_t unread_bytes
= 0;
2025 bool encrypted
= false;
2026 TALLOC_CTX
*mem_ctx
= talloc_tos();
2030 bool async_echo
= lp_async_smb_echo_handler();
2031 bool from_client
= false;
2034 if (fd_is_readable(xconn
->smb1
.echo_handler
.trusted_fd
)) {
2036 * This is the super-ugly hack to prefer the packets
2037 * forwarded by the echo handler over the ones by the
2040 fd
= xconn
->smb1
.echo_handler
.trusted_fd
;
2044 from_client
= (xconn
->transport
.sock
== fd
);
2046 if (async_echo
&& from_client
) {
2047 smbd_lock_socket(xconn
);
2049 if (!fd_is_readable(fd
)) {
2050 DEBUG(10,("the echo listener was faster\n"));
2051 smbd_unlock_socket(xconn
);
2056 /* TODO: make this completely nonblocking */
2057 status
= receive_smb_talloc(mem_ctx
, xconn
, fd
,
2058 (char **)(void *)&inbuf
,
2062 &inbuf_len
, &seqnum
,
2063 !from_client
/* trusted channel */);
2065 if (async_echo
&& from_client
) {
2066 smbd_unlock_socket(xconn
);
2069 if (NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
2072 if (NT_STATUS_IS_ERR(status
)) {
2073 exit_server_cleanly("failed to receive smb request");
2075 if (!NT_STATUS_IS_OK(status
)) {
2080 process_smb(xconn
, inbuf
, inbuf_len
, unread_bytes
, seqnum
, encrypted
);
2083 static void smbd_server_echo_handler(struct tevent_context
*ev
,
2084 struct tevent_fd
*fde
,
2088 struct smbXsrv_connection
*xconn
=
2089 talloc_get_type_abort(private_data
,
2090 struct smbXsrv_connection
);
2092 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
2094 * we're not supposed to do any io
2096 TEVENT_FD_NOT_READABLE(xconn
->smb1
.echo_handler
.trusted_fde
);
2097 TEVENT_FD_NOT_WRITEABLE(xconn
->smb1
.echo_handler
.trusted_fde
);
2101 if (flags
& TEVENT_FD_WRITE
) {
2102 smbd_server_connection_write_handler(xconn
);
2105 if (flags
& TEVENT_FD_READ
) {
2106 smbd_smb1_server_connection_read_handler(
2107 xconn
, xconn
->smb1
.echo_handler
.trusted_fd
);
2113 * Send keepalive packets to our client
2115 bool keepalive_fn(const struct timeval
*now
, void *private_data
)
2117 struct smbd_server_connection
*sconn
= talloc_get_type_abort(
2118 private_data
, struct smbd_server_connection
);
2119 struct smbXsrv_connection
*xconn
= NULL
;
2122 if (conn_using_smb2(sconn
)) {
2123 /* Don't do keepalives on an SMB2 connection. */
2128 * With SMB1 we only have 1 connection
2130 xconn
= sconn
->client
->connections
;
2131 smbd_lock_socket(xconn
);
2132 ret
= send_keepalive(xconn
->transport
.sock
);
2133 smbd_unlock_socket(xconn
);
2136 int saved_errno
= errno
;
2138 * Try and give an error message saying what
2141 DEBUG(0, ("send_keepalive failed for client %s. "
2142 "Error %s - exiting\n",
2143 smbXsrv_connection_dbg(xconn
),
2144 strerror(saved_errno
)));
2145 errno
= saved_errno
;
2152 * Read an smb packet in the echo handler child, giving the parent
2153 * smbd one second to react once the socket becomes readable.
2156 struct smbd_echo_read_state
{
2157 struct tevent_context
*ev
;
2158 struct smbXsrv_connection
*xconn
;
2165 static void smbd_echo_read_readable(struct tevent_req
*subreq
);
2166 static void smbd_echo_read_waited(struct tevent_req
*subreq
);
2168 static struct tevent_req
*smbd_echo_read_send(
2169 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2170 struct smbXsrv_connection
*xconn
)
2172 struct tevent_req
*req
, *subreq
;
2173 struct smbd_echo_read_state
*state
;
2175 req
= tevent_req_create(mem_ctx
, &state
,
2176 struct smbd_echo_read_state
);
2181 state
->xconn
= xconn
;
2183 subreq
= wait_for_read_send(state
, ev
, xconn
->transport
.sock
, false);
2184 if (tevent_req_nomem(subreq
, req
)) {
2185 return tevent_req_post(req
, ev
);
2187 tevent_req_set_callback(subreq
, smbd_echo_read_readable
, req
);
2191 static void smbd_echo_read_readable(struct tevent_req
*subreq
)
2193 struct tevent_req
*req
= tevent_req_callback_data(
2194 subreq
, struct tevent_req
);
2195 struct smbd_echo_read_state
*state
= tevent_req_data(
2196 req
, struct smbd_echo_read_state
);
2200 ok
= wait_for_read_recv(subreq
, &err
);
2201 TALLOC_FREE(subreq
);
2203 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
2208 * Give the parent smbd one second to step in
2211 subreq
= tevent_wakeup_send(
2212 state
, state
->ev
, timeval_current_ofs(1, 0));
2213 if (tevent_req_nomem(subreq
, req
)) {
2216 tevent_req_set_callback(subreq
, smbd_echo_read_waited
, req
);
2219 static void smbd_echo_read_waited(struct tevent_req
*subreq
)
2221 struct tevent_req
*req
= tevent_req_callback_data(
2222 subreq
, struct tevent_req
);
2223 struct smbd_echo_read_state
*state
= tevent_req_data(
2224 req
, struct smbd_echo_read_state
);
2225 struct smbXsrv_connection
*xconn
= state
->xconn
;
2231 ok
= tevent_wakeup_recv(subreq
);
2232 TALLOC_FREE(subreq
);
2234 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2238 ok
= smbd_lock_socket_internal(xconn
);
2240 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2241 DEBUG(0, ("%s: failed to lock socket\n", __location__
));
2245 if (!fd_is_readable(xconn
->transport
.sock
)) {
2246 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2249 ok
= smbd_unlock_socket_internal(xconn
);
2251 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2252 DEBUG(1, ("%s: failed to unlock socket\n",
2257 subreq
= wait_for_read_send(state
, state
->ev
,
2258 xconn
->transport
.sock
, false);
2259 if (tevent_req_nomem(subreq
, req
)) {
2262 tevent_req_set_callback(subreq
, smbd_echo_read_readable
, req
);
2266 status
= receive_smb_talloc(state
, xconn
,
2267 xconn
->transport
.sock
,
2274 false /* trusted_channel*/);
2276 if (tevent_req_nterror(req
, status
)) {
2277 tevent_req_nterror(req
, status
);
2278 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2279 (int)getpid(), nt_errstr(status
)));
2283 ok
= smbd_unlock_socket_internal(xconn
);
2285 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2286 DEBUG(1, ("%s: failed to unlock socket\n", __location__
));
2289 tevent_req_done(req
);
2292 static NTSTATUS
smbd_echo_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
2293 char **pbuf
, size_t *pbuflen
, uint32_t *pseqnum
)
2295 struct smbd_echo_read_state
*state
= tevent_req_data(
2296 req
, struct smbd_echo_read_state
);
2299 if (tevent_req_is_nterror(req
, &status
)) {
2302 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
2303 *pbuflen
= state
->buflen
;
2304 *pseqnum
= state
->seqnum
;
2305 return NT_STATUS_OK
;
2308 struct smbd_echo_state
{
2309 struct tevent_context
*ev
;
2310 struct iovec
*pending
;
2311 struct smbd_server_connection
*sconn
;
2312 struct smbXsrv_connection
*xconn
;
2315 struct tevent_fd
*parent_fde
;
2317 struct tevent_req
*write_req
;
2320 static void smbd_echo_writer_done(struct tevent_req
*req
);
2322 static void smbd_echo_activate_writer(struct smbd_echo_state
*state
)
2326 if (state
->write_req
!= NULL
) {
2330 num_pending
= talloc_array_length(state
->pending
);
2331 if (num_pending
== 0) {
2335 state
->write_req
= writev_send(state
, state
->ev
, NULL
,
2336 state
->parent_pipe
, false,
2337 state
->pending
, num_pending
);
2338 if (state
->write_req
== NULL
) {
2339 DEBUG(1, ("writev_send failed\n"));
2343 talloc_steal(state
->write_req
, state
->pending
);
2344 state
->pending
= NULL
;
2346 tevent_req_set_callback(state
->write_req
, smbd_echo_writer_done
,
2350 static void smbd_echo_writer_done(struct tevent_req
*req
)
2352 struct smbd_echo_state
*state
= tevent_req_callback_data(
2353 req
, struct smbd_echo_state
);
2357 written
= writev_recv(req
, &err
);
2359 state
->write_req
= NULL
;
2360 if (written
== -1) {
2361 DEBUG(1, ("writev to parent failed: %s\n", strerror(err
)));
2364 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2365 smbd_echo_activate_writer(state
);
2368 static bool smbd_echo_reply(struct smbd_echo_state
*state
,
2369 uint8_t *inbuf
, size_t inbuf_len
,
2372 struct smb_request req
;
2373 uint16_t num_replies
;
2377 if ((inbuf_len
== 4) && (CVAL(inbuf
, 0) == NBSSkeepalive
)) {
2378 DEBUG(10, ("Got netbios keepalive\n"));
2385 if (inbuf_len
< smb_size
) {
2386 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len
));
2389 if (!valid_smb1_header(inbuf
)) {
2390 DEBUG(10, ("Got invalid SMB header\n"));
2394 if (!init_smb1_request(&req
, state
->sconn
, state
->xconn
, inbuf
, 0, false,
2400 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req
.cmd
,
2401 smb_fn_name(req
.cmd
)));
2403 if (req
.cmd
!= SMBecho
) {
2410 num_replies
= SVAL(req
.vwv
+0, 0);
2411 if (num_replies
!= 1) {
2412 /* Not a Windows "Hey, you're still there?" request */
2416 if (!create_smb1_outbuf(talloc_tos(), &req
, req
.inbuf
, &outbuf
,
2418 DEBUG(10, ("create_smb1_outbuf failed\n"));
2421 req
.outbuf
= (uint8_t *)outbuf
;
2423 SSVAL(req
.outbuf
, smb_vwv0
, num_replies
);
2425 if (req
.buflen
> 0) {
2426 memcpy(smb_buf(req
.outbuf
), req
.buf
, req
.buflen
);
2429 ok
= smb1_srv_send(req
.xconn
, (char *)outbuf
, true, seqnum
+ 1, false);
2430 TALLOC_FREE(outbuf
);
2438 static void smbd_echo_exit(struct tevent_context
*ev
,
2439 struct tevent_fd
*fde
, uint16_t flags
,
2442 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2446 static void smbd_echo_got_packet(struct tevent_req
*req
);
2448 static void smbd_echo_loop(struct smbXsrv_connection
*xconn
,
2451 struct smbd_echo_state
*state
;
2452 struct tevent_req
*read_req
;
2454 state
= talloc_zero(xconn
, struct smbd_echo_state
);
2455 if (state
== NULL
) {
2456 DEBUG(1, ("talloc failed\n"));
2459 state
->xconn
= xconn
;
2460 state
->parent_pipe
= parent_pipe
;
2461 state
->ev
= samba_tevent_context_init(state
);
2462 if (state
->ev
== NULL
) {
2463 DEBUG(1, ("samba_tevent_context_init failed\n"));
2467 state
->parent_fde
= tevent_add_fd(state
->ev
, state
, parent_pipe
,
2468 TEVENT_FD_READ
, smbd_echo_exit
,
2470 if (state
->parent_fde
== NULL
) {
2471 DEBUG(1, ("tevent_add_fd failed\n"));
2476 read_req
= smbd_echo_read_send(state
, state
->ev
, xconn
);
2477 if (read_req
== NULL
) {
2478 DEBUG(1, ("smbd_echo_read_send failed\n"));
2482 tevent_req_set_callback(read_req
, smbd_echo_got_packet
, state
);
2485 if (tevent_loop_once(state
->ev
) == -1) {
2486 DEBUG(1, ("tevent_loop_once failed: %s\n",
2494 static void smbd_echo_got_packet(struct tevent_req
*req
)
2496 struct smbd_echo_state
*state
= tevent_req_callback_data(
2497 req
, struct smbd_echo_state
);
2501 uint32_t seqnum
= 0;
2504 status
= smbd_echo_read_recv(req
, state
, &buf
, &buflen
, &seqnum
);
2506 if (!NT_STATUS_IS_OK(status
)) {
2507 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2508 nt_errstr(status
)));
2512 reply
= smbd_echo_reply(state
, (uint8_t *)buf
, buflen
, seqnum
);
2518 num_pending
= talloc_array_length(state
->pending
);
2519 tmp
= talloc_realloc(state
, state
->pending
, struct iovec
,
2522 DEBUG(1, ("talloc_realloc failed\n"));
2525 state
->pending
= tmp
;
2527 if (buflen
>= smb_size
) {
2529 * place the seqnum in the packet so that the main process
2530 * can reply with signing
2532 SIVAL(buf
, smb_ss_field
, seqnum
);
2533 SIVAL(buf
, smb_ss_field
+4, NT_STATUS_V(NT_STATUS_OK
));
2536 iov
= &state
->pending
[num_pending
];
2537 iov
->iov_base
= talloc_move(state
->pending
, &buf
);
2538 iov
->iov_len
= buflen
;
2540 DEBUG(10,("echo_handler[%d]: forward to main\n",
2542 smbd_echo_activate_writer(state
);
2545 req
= smbd_echo_read_send(state
, state
->ev
, state
->xconn
);
2547 DEBUG(1, ("smbd_echo_read_send failed\n"));
2550 tevent_req_set_callback(req
, smbd_echo_got_packet
, state
);
2555 * Handle SMBecho requests in a forked child process
2557 bool fork_echo_handler(struct smbXsrv_connection
*xconn
)
2559 int listener_pipe
[2];
2562 bool use_mutex
= false;
2564 res
= pipe(listener_pipe
);
2566 DEBUG(1, ("pipe() failed: %s\n", strerror(errno
)));
2570 #ifdef HAVE_ROBUST_MUTEXES
2571 use_mutex
= tdb_runtime_check_for_robust_mutexes();
2574 pthread_mutexattr_t a
;
2576 xconn
->smb1
.echo_handler
.socket_mutex
=
2577 anonymous_shared_allocate(sizeof(pthread_mutex_t
));
2578 if (xconn
->smb1
.echo_handler
.socket_mutex
== NULL
) {
2579 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2584 res
= pthread_mutexattr_init(&a
);
2586 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2590 res
= pthread_mutexattr_settype(&a
, PTHREAD_MUTEX_ERRORCHECK
);
2592 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2594 pthread_mutexattr_destroy(&a
);
2597 res
= pthread_mutexattr_setpshared(&a
, PTHREAD_PROCESS_SHARED
);
2599 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2601 pthread_mutexattr_destroy(&a
);
2604 res
= pthread_mutexattr_setrobust(&a
, PTHREAD_MUTEX_ROBUST
);
2606 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2607 "%s\n", strerror(res
)));
2608 pthread_mutexattr_destroy(&a
);
2611 res
= pthread_mutex_init(xconn
->smb1
.echo_handler
.socket_mutex
,
2613 pthread_mutexattr_destroy(&a
);
2615 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2623 xconn
->smb1
.echo_handler
.socket_lock_fd
=
2624 create_unlink_tmp(lp_lock_directory());
2625 if (xconn
->smb1
.echo_handler
.socket_lock_fd
== -1) {
2626 DEBUG(1, ("Could not create lock fd: %s\n",
2636 close(listener_pipe
[0]);
2637 set_blocking(listener_pipe
[1], false);
2639 status
= smbd_reinit_after_fork(xconn
->client
->msg_ctx
,
2640 xconn
->client
->raw_ev_ctx
,
2642 if (!NT_STATUS_IS_OK(status
)) {
2643 DEBUG(1, ("reinit_after_fork failed: %s\n",
2644 nt_errstr(status
)));
2647 process_set_title("smbd-echo", "echo handler");
2648 initialize_password_db(true, xconn
->client
->raw_ev_ctx
);
2649 smbd_echo_loop(xconn
, listener_pipe
[1]);
2652 close(listener_pipe
[1]);
2653 listener_pipe
[1] = -1;
2654 xconn
->smb1
.echo_handler
.trusted_fd
= listener_pipe
[0];
2656 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child
));
2659 * Without smb signing this is the same as the normal smbd
2660 * listener. This needs to change once signing comes in.
2662 xconn
->smb1
.echo_handler
.trusted_fde
= tevent_add_fd(
2663 xconn
->client
->raw_ev_ctx
,
2665 xconn
->smb1
.echo_handler
.trusted_fd
,
2667 smbd_server_echo_handler
,
2669 if (xconn
->smb1
.echo_handler
.trusted_fde
== NULL
) {
2670 DEBUG(1, ("event_add_fd failed\n"));
2677 if (listener_pipe
[0] != -1) {
2678 close(listener_pipe
[0]);
2680 if (listener_pipe
[1] != -1) {
2681 close(listener_pipe
[1]);
2683 if (xconn
->smb1
.echo_handler
.socket_lock_fd
!= -1) {
2684 close(xconn
->smb1
.echo_handler
.socket_lock_fd
);
2686 #ifdef HAVE_ROBUST_MUTEXES
2687 if (xconn
->smb1
.echo_handler
.socket_mutex
!= NULL
) {
2688 pthread_mutex_destroy(xconn
->smb1
.echo_handler
.socket_mutex
);
2689 anonymous_shared_free(xconn
->smb1
.echo_handler
.socket_mutex
);
2692 smbd_echo_init(xconn
);
2697 bool req_is_in_chain(const struct smb_request
*req
)
2699 if (req
->vwv
!= (const uint16_t *)(req
->inbuf
+smb_vwv
)) {
2701 * We're right now handling a subsequent request, so we must
2707 if (!smb1cli_is_andx_req(req
->cmd
)) {
2713 * Okay, an illegal request, but definitely not chained :-)
2718 return (CVAL(req
->vwv
+0, 0) != 0xFF);