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 "smbd/smbXsrv_open.h"
27 #include "librpc/gen_ndr/netlogon.h"
28 #include "../lib/async_req/async_sock.h"
29 #include "ctdbd_conn.h"
30 #include "../lib/util/select.h"
31 #include "printing/queue_process.h"
32 #include "system/select.h"
36 #include "lib/messages_ctdb.h"
37 #include "smbprofile.h"
38 #include "rpc_server/spoolss/srv_spoolss_nt.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "../libcli/security/dom_sid.h"
41 #include "../libcli/security/security_token.h"
42 #include "lib/id_cache.h"
43 #include "lib/util/sys_rw_data.h"
44 #include "system/threads.h"
45 #include "lib/pthreadpool/pthreadpool_tevent.h"
46 #include "util_event.h"
47 #include "libcli/smb/smbXcli_base.h"
48 #include "lib/util/time_basic.h"
49 #include "source3/lib/substitute.h"
50 #include "lib/util/util_process.h"
52 /* Internal message queue for deferred opens. */
53 struct pending_message_list {
54 struct pending_message_list *next, *prev;
55 struct timeval request_time; /* When was this first issued? */
56 struct smbd_server_connection *sconn;
57 struct smbXsrv_connection *xconn;
58 struct tevent_timer *te;
59 struct smb_perfcount_data pcd;
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, char *buffer,
212 bool do_signing, uint32_t seqnum,
214 struct smb_perfcount_data *pcd)
218 char *buf_out = buffer;
220 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
222 * we're not supposed to do any io
227 smbd_lock_socket(xconn);
232 /* Sign the outgoing packet if required. */
233 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
234 if (!NT_STATUS_IS_OK(status)) {
235 DBG_ERR("Failed to calculate signing mac: %s\n",
243 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &enc);
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) ));
255 len = smb_len_large(buf_out) + 4;
257 ret = write_data(xconn->transport.sock, buf_out, len);
259 int saved_errno = errno;
261 * Try and give an error message saying what
264 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
265 (int)getpid(), (int)len,
266 smbXsrv_connection_dbg(xconn),
267 (int)ret, strerror(saved_errno)));
270 srv_free_enc_buffer(xconn, buf_out);
274 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
275 srv_free_enc_buffer(xconn, buf_out);
277 SMB_PERFCOUNT_END(pcd);
279 smbd_unlock_socket(xconn);
283 /* Socket functions for smbd packet processing. */
285 static bool valid_packet_size(size_t len)
288 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
289 * of header. Don't print the error if this fits.... JRA.
292 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
293 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
294 (unsigned long)len));
300 /****************************************************************************
301 Attempt a zerocopy writeX read. We know here that len > smb_size-4
302 ****************************************************************************/
305 * Unfortunately, earlier versions of smbclient/libsmbclient
306 * don't send this "standard" writeX header. I've fixed this
307 * for 3.2 but we'll use the old method with earlier versions.
308 * Windows and CIFSFS at least use this standard size. Not
312 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
313 (2*14) + /* word count (including bcc) */ \
316 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
317 const char lenbuf[4],
318 struct smbXsrv_connection *xconn,
321 unsigned int timeout,
325 /* Size of a WRITEX call (+4 byte len). */
326 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
327 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
331 memcpy(writeX_header, lenbuf, 4);
333 status = read_fd_with_timeout(
334 sock, writeX_header + 4,
335 STANDARD_WRITE_AND_X_HEADER_SIZE,
336 STANDARD_WRITE_AND_X_HEADER_SIZE,
339 if (!NT_STATUS_IS_OK(status)) {
340 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
342 smbXsrv_connection_dbg(xconn),
348 * Ok - now try and see if this is a possible
352 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
354 * If the data offset is beyond what
355 * we've read, drain the extra bytes.
357 uint16_t doff = SVAL(writeX_header,smb_vwv11);
360 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
361 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
362 if (drain_socket(sock, drain) != drain) {
363 smb_panic("receive_smb_raw_talloc_partial_read:"
364 " failed to drain pending bytes");
367 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
370 /* Spoof down the length and null out the bcc. */
371 set_message_bcc(writeX_header, 0);
372 newlen = smb_len(writeX_header);
374 /* Copy the header we've written. */
376 *buffer = (char *)talloc_memdup(mem_ctx,
378 sizeof(writeX_header));
380 if (*buffer == NULL) {
381 DEBUG(0, ("Could not allocate inbuf of length %d\n",
382 (int)sizeof(writeX_header)));
383 return NT_STATUS_NO_MEMORY;
386 /* Work out the remaining bytes. */
387 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
388 *len_ret = newlen + 4;
392 if (!valid_packet_size(len)) {
393 return NT_STATUS_INVALID_PARAMETER;
397 * Not a valid writeX call. Just do the standard
401 *buffer = talloc_array(mem_ctx, char, len+4);
403 if (*buffer == NULL) {
404 DEBUG(0, ("Could not allocate inbuf of length %d\n",
406 return NT_STATUS_NO_MEMORY;
409 /* Copy in what we already read. */
412 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
413 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
416 status = read_packet_remainder(
418 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
421 if (!NT_STATUS_IS_OK(status)) {
422 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
432 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
433 struct smbXsrv_connection *xconn,
435 char **buffer, unsigned int timeout,
436 size_t *p_unread, size_t *plen)
440 int min_recv_size = lp_min_receive_file_size();
445 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
447 if (!NT_STATUS_IS_OK(status)) {
451 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
452 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
453 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
454 !smb1_srv_is_signing_active(xconn) &&
455 xconn->smb1.echo_handler.trusted_fde == NULL) {
457 return receive_smb_raw_talloc_partial_read(
458 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
462 if (!valid_packet_size(len)) {
463 return NT_STATUS_INVALID_PARAMETER;
467 * The +4 here can't wrap, we've checked the length above already.
470 *buffer = talloc_array(mem_ctx, char, len+4);
472 if (*buffer == NULL) {
473 DEBUG(0, ("Could not allocate inbuf of length %d\n",
475 return NT_STATUS_NO_MEMORY;
478 memcpy(*buffer, lenbuf, sizeof(lenbuf));
480 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
481 if (!NT_STATUS_IS_OK(status)) {
489 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
490 struct smbXsrv_connection *xconn,
492 char **buffer, unsigned int timeout,
493 size_t *p_unread, bool *p_encrypted,
496 bool trusted_channel)
501 *p_encrypted = false;
503 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
505 if (!NT_STATUS_IS_OK(status)) {
506 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
507 ("receive_smb_raw_talloc failed for client %s "
508 "read error = %s.\n",
509 smbXsrv_connection_dbg(xconn),
510 nt_errstr(status)) );
514 if (is_encrypted_packet((uint8_t *)*buffer)) {
515 status = srv_decrypt_buffer(xconn, *buffer);
516 if (!NT_STATUS_IS_OK(status)) {
517 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
518 "incoming packet! Error %s\n",
519 nt_errstr(status) ));
525 /* Check the incoming SMB signature. */
526 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
527 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
528 "incoming packet!\n"));
529 return NT_STATUS_INVALID_NETWORK_RESPONSE;
536 /****************************************************************************
537 Function to push a message onto the tail of a linked list of smb messages ready
539 ****************************************************************************/
541 static bool push_queued_message(struct smb_request *req,
542 struct timeval request_time,
543 struct timeval end_time,
544 struct deferred_open_record *open_rec)
546 int msg_len = smb_len(req->inbuf) + 4;
547 struct pending_message_list *msg;
549 msg = talloc_zero(NULL, struct pending_message_list);
552 DEBUG(0,("push_message: malloc fail (1)\n"));
555 msg->sconn = req->sconn;
556 msg->xconn = req->xconn;
558 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
559 if(msg->buf.data == NULL) {
560 DEBUG(0,("push_message: malloc fail (2)\n"));
565 msg->request_time = request_time;
566 msg->seqnum = req->seqnum;
567 msg->encrypted = req->encrypted;
568 msg->processed = false;
569 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
572 msg->open_rec = talloc_move(msg, &open_rec);
576 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
579 smbd_deferred_open_timer,
582 DEBUG(0,("push_message: event_add_timed failed\n"));
588 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
590 DEBUG(10,("push_message: pushed message length %u on "
591 "deferred_open_queue\n", (unsigned int)msg_len));
596 /****************************************************************************
597 Function to push a deferred open smb message onto a linked list of local smb
598 messages ready for processing.
599 ****************************************************************************/
601 bool push_deferred_open_message_smb1(struct smb_request *req,
602 struct timeval timeout,
604 struct deferred_open_record *open_rec)
606 struct timeval_buf tvbuf;
607 struct timeval end_time;
609 if (req->unread_bytes) {
610 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
611 "unread_bytes = %u\n",
612 (unsigned int)req->unread_bytes ));
613 smb_panic("push_deferred_open_message_smb: "
614 "logic error unread_bytes != 0" );
617 end_time = timeval_sum(&req->request_time, &timeout);
619 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
620 (unsigned int) smb_len(req->inbuf)+4,
622 timeval_str_buf(&end_time, false, true, &tvbuf));
624 return push_queued_message(req, req->request_time, end_time, open_rec);
628 * Only allow 5 outstanding trans requests. We're allocating memory, so
632 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
635 for (; list != NULL; list = list->next) {
637 if (list->mid == mid) {
638 return NT_STATUS_INVALID_PARAMETER;
644 return NT_STATUS_INSUFFICIENT_RESOURCES;
651 These flags determine some of the permissions required to do an operation
653 Note that I don't set NEED_WRITE on some write operations because they
654 are used by some brain-dead clients when printing, and I don't want to
655 force write permissions on print services.
657 #define AS_USER (1<<0)
658 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
659 #define TIME_INIT (1<<2)
660 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
661 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
662 #define DO_CHDIR (1<<6)
665 define a list of possible SMB messages and their corresponding
666 functions. Any message that has a NULL function is unimplemented -
667 please feel free to contribute implementations!
669 static const struct smb_message_struct {
671 void (*fn)(struct smb_request *req);
673 } smb_messages[256] = {
675 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
676 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
677 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
678 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
679 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
680 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
681 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
682 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
683 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
684 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
685 /* 0x0a */ { "SMBread",reply_read,AS_USER},
686 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
687 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
688 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
689 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
690 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
691 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
692 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
693 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
694 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
695 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
696 /* 0x15 */ { NULL, NULL, 0 },
697 /* 0x16 */ { NULL, NULL, 0 },
698 /* 0x17 */ { NULL, NULL, 0 },
699 /* 0x18 */ { NULL, NULL, 0 },
700 /* 0x19 */ { NULL, NULL, 0 },
701 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
702 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
703 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
704 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
705 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
706 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
707 /* 0x20 */ { "SMBwritec", NULL,0},
708 /* 0x21 */ { NULL, NULL, 0 },
709 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
710 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
711 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
712 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
713 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
714 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
715 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
716 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
717 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
718 /* 0x2b */ { "SMBecho",reply_echo,0},
719 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
720 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
721 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
722 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
723 /* 0x30 */ { NULL, NULL, 0 },
724 /* 0x31 */ { NULL, NULL, 0 },
725 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
726 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
727 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
728 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
729 /* 0x36 */ { NULL, NULL, 0 },
730 /* 0x37 */ { NULL, NULL, 0 },
731 /* 0x38 */ { NULL, NULL, 0 },
732 /* 0x39 */ { NULL, NULL, 0 },
733 /* 0x3a */ { NULL, NULL, 0 },
734 /* 0x3b */ { NULL, NULL, 0 },
735 /* 0x3c */ { NULL, NULL, 0 },
736 /* 0x3d */ { NULL, NULL, 0 },
737 /* 0x3e */ { NULL, NULL, 0 },
738 /* 0x3f */ { NULL, NULL, 0 },
739 /* 0x40 */ { NULL, NULL, 0 },
740 /* 0x41 */ { NULL, NULL, 0 },
741 /* 0x42 */ { NULL, NULL, 0 },
742 /* 0x43 */ { NULL, NULL, 0 },
743 /* 0x44 */ { NULL, NULL, 0 },
744 /* 0x45 */ { NULL, NULL, 0 },
745 /* 0x46 */ { NULL, NULL, 0 },
746 /* 0x47 */ { NULL, NULL, 0 },
747 /* 0x48 */ { NULL, NULL, 0 },
748 /* 0x49 */ { NULL, NULL, 0 },
749 /* 0x4a */ { NULL, NULL, 0 },
750 /* 0x4b */ { NULL, NULL, 0 },
751 /* 0x4c */ { NULL, NULL, 0 },
752 /* 0x4d */ { NULL, NULL, 0 },
753 /* 0x4e */ { NULL, NULL, 0 },
754 /* 0x4f */ { NULL, NULL, 0 },
755 /* 0x50 */ { NULL, NULL, 0 },
756 /* 0x51 */ { NULL, NULL, 0 },
757 /* 0x52 */ { NULL, NULL, 0 },
758 /* 0x53 */ { NULL, NULL, 0 },
759 /* 0x54 */ { NULL, NULL, 0 },
760 /* 0x55 */ { NULL, NULL, 0 },
761 /* 0x56 */ { NULL, NULL, 0 },
762 /* 0x57 */ { NULL, NULL, 0 },
763 /* 0x58 */ { NULL, NULL, 0 },
764 /* 0x59 */ { NULL, NULL, 0 },
765 /* 0x5a */ { NULL, NULL, 0 },
766 /* 0x5b */ { NULL, NULL, 0 },
767 /* 0x5c */ { NULL, NULL, 0 },
768 /* 0x5d */ { NULL, NULL, 0 },
769 /* 0x5e */ { NULL, NULL, 0 },
770 /* 0x5f */ { NULL, NULL, 0 },
771 /* 0x60 */ { NULL, NULL, 0 },
772 /* 0x61 */ { NULL, NULL, 0 },
773 /* 0x62 */ { NULL, NULL, 0 },
774 /* 0x63 */ { NULL, NULL, 0 },
775 /* 0x64 */ { NULL, NULL, 0 },
776 /* 0x65 */ { NULL, NULL, 0 },
777 /* 0x66 */ { NULL, NULL, 0 },
778 /* 0x67 */ { NULL, NULL, 0 },
779 /* 0x68 */ { NULL, NULL, 0 },
780 /* 0x69 */ { NULL, NULL, 0 },
781 /* 0x6a */ { NULL, NULL, 0 },
782 /* 0x6b */ { NULL, NULL, 0 },
783 /* 0x6c */ { NULL, NULL, 0 },
784 /* 0x6d */ { NULL, NULL, 0 },
785 /* 0x6e */ { NULL, NULL, 0 },
786 /* 0x6f */ { NULL, NULL, 0 },
787 /* 0x70 */ { "SMBtcon",reply_tcon,0},
788 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
789 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
790 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
791 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
792 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
793 /* 0x76 */ { NULL, NULL, 0 },
794 /* 0x77 */ { NULL, NULL, 0 },
795 /* 0x78 */ { NULL, NULL, 0 },
796 /* 0x79 */ { NULL, NULL, 0 },
797 /* 0x7a */ { NULL, NULL, 0 },
798 /* 0x7b */ { NULL, NULL, 0 },
799 /* 0x7c */ { NULL, NULL, 0 },
800 /* 0x7d */ { NULL, NULL, 0 },
801 /* 0x7e */ { NULL, NULL, 0 },
802 /* 0x7f */ { NULL, NULL, 0 },
803 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
804 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
805 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
806 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
807 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
808 /* 0x85 */ { NULL, NULL, 0 },
809 /* 0x86 */ { NULL, NULL, 0 },
810 /* 0x87 */ { NULL, NULL, 0 },
811 /* 0x88 */ { NULL, NULL, 0 },
812 /* 0x89 */ { NULL, NULL, 0 },
813 /* 0x8a */ { NULL, NULL, 0 },
814 /* 0x8b */ { NULL, NULL, 0 },
815 /* 0x8c */ { NULL, NULL, 0 },
816 /* 0x8d */ { NULL, NULL, 0 },
817 /* 0x8e */ { NULL, NULL, 0 },
818 /* 0x8f */ { NULL, NULL, 0 },
819 /* 0x90 */ { NULL, NULL, 0 },
820 /* 0x91 */ { NULL, NULL, 0 },
821 /* 0x92 */ { NULL, NULL, 0 },
822 /* 0x93 */ { NULL, NULL, 0 },
823 /* 0x94 */ { NULL, NULL, 0 },
824 /* 0x95 */ { NULL, NULL, 0 },
825 /* 0x96 */ { NULL, NULL, 0 },
826 /* 0x97 */ { NULL, NULL, 0 },
827 /* 0x98 */ { NULL, NULL, 0 },
828 /* 0x99 */ { NULL, NULL, 0 },
829 /* 0x9a */ { NULL, NULL, 0 },
830 /* 0x9b */ { NULL, NULL, 0 },
831 /* 0x9c */ { NULL, NULL, 0 },
832 /* 0x9d */ { NULL, NULL, 0 },
833 /* 0x9e */ { NULL, NULL, 0 },
834 /* 0x9f */ { NULL, NULL, 0 },
835 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
836 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
837 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
838 /* 0xa3 */ { NULL, NULL, 0 },
839 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
840 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
841 /* 0xa6 */ { NULL, NULL, 0 },
842 /* 0xa7 */ { NULL, NULL, 0 },
843 /* 0xa8 */ { NULL, NULL, 0 },
844 /* 0xa9 */ { NULL, NULL, 0 },
845 /* 0xaa */ { NULL, NULL, 0 },
846 /* 0xab */ { NULL, NULL, 0 },
847 /* 0xac */ { NULL, NULL, 0 },
848 /* 0xad */ { NULL, NULL, 0 },
849 /* 0xae */ { NULL, NULL, 0 },
850 /* 0xaf */ { NULL, NULL, 0 },
851 /* 0xb0 */ { NULL, NULL, 0 },
852 /* 0xb1 */ { NULL, NULL, 0 },
853 /* 0xb2 */ { NULL, NULL, 0 },
854 /* 0xb3 */ { NULL, NULL, 0 },
855 /* 0xb4 */ { NULL, NULL, 0 },
856 /* 0xb5 */ { NULL, NULL, 0 },
857 /* 0xb6 */ { NULL, NULL, 0 },
858 /* 0xb7 */ { NULL, NULL, 0 },
859 /* 0xb8 */ { NULL, NULL, 0 },
860 /* 0xb9 */ { NULL, NULL, 0 },
861 /* 0xba */ { NULL, NULL, 0 },
862 /* 0xbb */ { NULL, NULL, 0 },
863 /* 0xbc */ { NULL, NULL, 0 },
864 /* 0xbd */ { NULL, NULL, 0 },
865 /* 0xbe */ { NULL, NULL, 0 },
866 /* 0xbf */ { NULL, NULL, 0 },
867 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
868 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
869 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
870 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
871 /* 0xc4 */ { NULL, NULL, 0 },
872 /* 0xc5 */ { NULL, NULL, 0 },
873 /* 0xc6 */ { NULL, NULL, 0 },
874 /* 0xc7 */ { NULL, NULL, 0 },
875 /* 0xc8 */ { NULL, NULL, 0 },
876 /* 0xc9 */ { NULL, NULL, 0 },
877 /* 0xca */ { NULL, NULL, 0 },
878 /* 0xcb */ { NULL, NULL, 0 },
879 /* 0xcc */ { NULL, NULL, 0 },
880 /* 0xcd */ { NULL, NULL, 0 },
881 /* 0xce */ { NULL, NULL, 0 },
882 /* 0xcf */ { NULL, NULL, 0 },
883 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
884 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
885 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
886 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
887 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
888 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
889 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
890 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
891 /* 0xd8 */ { NULL, NULL, 0 },
892 /* 0xd9 */ { NULL, NULL, 0 },
893 /* 0xda */ { NULL, NULL, 0 },
894 /* 0xdb */ { NULL, NULL, 0 },
895 /* 0xdc */ { NULL, NULL, 0 },
896 /* 0xdd */ { NULL, NULL, 0 },
897 /* 0xde */ { NULL, NULL, 0 },
898 /* 0xdf */ { NULL, NULL, 0 },
899 /* 0xe0 */ { NULL, NULL, 0 },
900 /* 0xe1 */ { NULL, NULL, 0 },
901 /* 0xe2 */ { NULL, NULL, 0 },
902 /* 0xe3 */ { NULL, NULL, 0 },
903 /* 0xe4 */ { NULL, NULL, 0 },
904 /* 0xe5 */ { NULL, NULL, 0 },
905 /* 0xe6 */ { NULL, NULL, 0 },
906 /* 0xe7 */ { NULL, NULL, 0 },
907 /* 0xe8 */ { NULL, NULL, 0 },
908 /* 0xe9 */ { NULL, NULL, 0 },
909 /* 0xea */ { NULL, NULL, 0 },
910 /* 0xeb */ { NULL, NULL, 0 },
911 /* 0xec */ { NULL, NULL, 0 },
912 /* 0xed */ { NULL, NULL, 0 },
913 /* 0xee */ { NULL, NULL, 0 },
914 /* 0xef */ { NULL, NULL, 0 },
915 /* 0xf0 */ { NULL, NULL, 0 },
916 /* 0xf1 */ { NULL, NULL, 0 },
917 /* 0xf2 */ { NULL, NULL, 0 },
918 /* 0xf3 */ { NULL, NULL, 0 },
919 /* 0xf4 */ { NULL, NULL, 0 },
920 /* 0xf5 */ { NULL, NULL, 0 },
921 /* 0xf6 */ { NULL, NULL, 0 },
922 /* 0xf7 */ { NULL, NULL, 0 },
923 /* 0xf8 */ { NULL, NULL, 0 },
924 /* 0xf9 */ { NULL, NULL, 0 },
925 /* 0xfa */ { NULL, NULL, 0 },
926 /* 0xfb */ { NULL, NULL, 0 },
927 /* 0xfc */ { NULL, NULL, 0 },
928 /* 0xfd */ { NULL, NULL, 0 },
929 /* 0xfe */ { NULL, NULL, 0 },
930 /* 0xff */ { NULL, NULL, 0 }
935 /*******************************************************************
936 Dump a packet to a file.
937 ********************************************************************/
939 static void smb_dump(const char *name, int type, const char *data)
944 if (DEBUGLEVEL < 50) {
948 len = smb_len_tcp(data)+4;
949 for (i=1;i<100;i++) {
950 fname = talloc_asprintf(talloc_tos(),
954 type ? "req" : "resp");
958 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
959 if (fd != -1 || errno != EEXIST) break;
963 ssize_t ret = write(fd, data, len);
965 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
967 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
972 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
973 struct smb_request *req,
975 bool *update_session_globalp,
976 bool *update_tcon_globalp)
978 connection_struct *conn = req->conn;
979 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
980 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
981 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
982 bool update_session = false;
983 bool update_tcon = false;
985 if (req->encrypted) {
986 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
989 if (smb1_srv_is_signing_active(req->xconn)) {
990 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
991 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
993 * echo can be unsigned. Sesssion setup except final
994 * session setup response too
996 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
999 update_session |= smbXsrv_set_crypto_flag(
1000 &session->global->encryption_flags, encrypt_flag);
1001 update_session |= smbXsrv_set_crypto_flag(
1002 &session->global->signing_flags, sign_flag);
1005 update_tcon |= smbXsrv_set_crypto_flag(
1006 &tcon->global->encryption_flags, encrypt_flag);
1007 update_tcon |= smbXsrv_set_crypto_flag(
1008 &tcon->global->signing_flags, sign_flag);
1011 if (update_session) {
1012 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1015 *update_session_globalp = update_session;
1016 *update_tcon_globalp = update_tcon;
1020 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1023 enum remote_arch_types ra_type;
1025 SMB_ASSERT(conn != NULL);
1026 SMB_ASSERT(!conn->sconn->using_smb2);
1030 if ((conn == last_conn) && (last_flags == flags)) {
1038 * Obey the client case sensitivity requests - only for clients that
1040 switch (lp_case_sensitive(snum)) {
1043 * We need this uglyness due to DOS/Win9x clients that lie
1044 * about case insensitivity. */
1045 ra_type = get_remote_arch();
1046 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1048 * Client can't support per-packet case sensitive
1050 conn->case_sensitive = false;
1052 conn->case_sensitive =
1053 !(flags & FLAG_CASELESS_PATHNAMES);
1057 conn->case_sensitive = true;
1060 conn->case_sensitive = false;
1066 /****************************************************************************
1067 Prepare everything for calling the actual request function, and potentially
1068 call the request function via the "new" interface.
1070 Return False if the "legacy" function needs to be called, everything is
1073 Return True if we're done.
1075 I know this API sucks, but it is the one with the least code change I could
1077 ****************************************************************************/
1079 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1081 const struct loadparm_substitution *lp_sub =
1082 loadparm_s3_global_substitution();
1084 uint64_t session_tag;
1085 connection_struct *conn = NULL;
1086 struct smbXsrv_connection *xconn = req->xconn;
1087 NTTIME now = timeval_to_nttime(&req->request_time);
1088 struct smbXsrv_session *session = NULL;
1093 if (!xconn->smb1.negprot.done) {
1096 * Without a negprot the request must
1097 * either be a negprot, or one of the
1098 * evil old SMB mailslot messaging types.
1106 exit_server_cleanly("The first request "
1107 "should be a negprot");
1111 if (smb_messages[type].fn == NULL) {
1112 DEBUG(0,("Unknown message type %d!\n",type));
1113 smb_dump("Unknown", 1, (const char *)req->inbuf);
1114 reply_unknown_new(req, type);
1118 flags = smb_messages[type].flags;
1120 /* In share mode security we must ignore the vuid. */
1121 session_tag = req->vuid;
1124 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1125 (int)getpid(), (unsigned long)conn));
1127 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1129 /* Ensure this value is replaced in the incoming packet. */
1130 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1133 * Ensure the correct username is in current_user_info. This is a
1134 * really ugly bugfix for problems with multiple session_setup_and_X's
1135 * being done and allowing %U and %G substitutions to work correctly.
1136 * There is a reason this code is done here, don't move it unless you
1137 * know what you're doing... :-).
1142 * lookup an existing session
1144 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1145 * here, the main check is still in change_to_user()
1147 status = smb1srv_session_lookup(xconn,
1151 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1154 status = NT_STATUS_OK;
1157 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1158 (unsigned long long)session_tag,
1159 (unsigned long long)req->mid));
1160 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1165 if (session != NULL &&
1166 session->global->auth_session_info != NULL &&
1170 * change_to_user() implies set_current_user_info()
1171 * and chdir_connect_service().
1173 * So we only call set_current_user_info if
1174 * we don't have AS_USER specified.
1176 set_current_user_info(
1177 session->global->auth_session_info->unix_info->sanitized_username,
1178 session->global->auth_session_info->unix_info->unix_name,
1179 session->global->auth_session_info->info->domain_name);
1182 /* Does this call need to be run as the connected user? */
1183 if (flags & AS_USER) {
1185 /* Does this call need a valid tree connection? */
1188 * Amazingly, the error code depends on the command
1191 if (type == SMBntcreateX) {
1192 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1194 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1199 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1202 * change_to_user() implies set_current_user_info()
1203 * and chdir_connect_service().
1205 if (!change_to_user_and_service(conn,session_tag)) {
1206 DEBUG(0, ("Error: Could not change to user. Removing "
1207 "deferred open, mid=%llu.\n",
1208 (unsigned long long)req->mid));
1209 reply_force_doserror(req, ERRSRV, ERRbaduid);
1213 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1215 /* Does it need write permission? */
1216 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1217 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1221 /* IPC services are limited */
1222 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1223 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1226 } else if (flags & AS_GUEST) {
1228 * Does this protocol need to be run as guest? (Only archane
1229 * messenger service requests have this...)
1231 if (!change_to_guest()) {
1232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1236 /* This call needs to be run as root */
1237 change_to_root_user();
1240 /* load service specific parameters */
1242 if (req->encrypted) {
1243 conn->encrypted_tid = true;
1244 /* encrypted required from now on. */
1245 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1246 } else if (ENCRYPTION_REQUIRED(conn)) {
1247 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1248 DEBUG(1,("service[%s] requires encryption"
1249 "%s ACCESS_DENIED. mid=%llu\n",
1250 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1252 (unsigned long long)req->mid));
1253 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1258 if (flags & DO_CHDIR) {
1261 ok = chdir_current_service(conn);
1263 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1267 conn->num_smb_operations++;
1271 * Update encryption and signing state tracking flags that are
1272 * used by smbstatus to display signing and encryption status.
1274 if (session != NULL) {
1275 bool update_session_global = false;
1276 bool update_tcon_global = false;
1278 req->session = session;
1280 smb1srv_update_crypto_flags(session, req, type,
1281 &update_session_global,
1282 &update_tcon_global);
1284 if (update_session_global) {
1285 status = smbXsrv_session_update(session);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1292 if (update_tcon_global) {
1293 status = smbXsrv_tcon_update(req->conn->tcon);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1301 smb_messages[type].fn(req);
1305 /****************************************************************************
1306 Construct a reply to the incoming packet.
1307 ****************************************************************************/
1309 void construct_reply(struct smbXsrv_connection *xconn,
1310 char *inbuf, int size, size_t unread_bytes,
1311 uint32_t seqnum, bool encrypted,
1312 struct smb_perfcount_data *deferred_pcd)
1314 struct smbd_server_connection *sconn = xconn->client->sconn;
1315 struct smb_request *req;
1317 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1318 smb_panic("could not allocate smb_request");
1321 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1322 encrypted, seqnum)) {
1323 exit_server_cleanly("Invalid SMB request");
1326 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1328 /* we popped this message off the queue - keep original perf data */
1330 req->pcd = *deferred_pcd;
1332 SMB_PERFCOUNT_START(&req->pcd);
1333 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1334 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1337 req->conn = switch_message(req->cmd, req);
1339 if (req->outbuf == NULL) {
1341 * Request has suspended itself, will come
1346 if (CVAL(req->outbuf,0) == 0) {
1347 show_msg((char *)req->outbuf);
1349 smb_request_done(req);
1352 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1353 char *inbuf, int size, uint32_t seqnum,
1355 struct smb_perfcount_data *deferred_pcd)
1357 struct smb_request **reqs = NULL;
1358 struct smb_request *req;
1362 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1363 seqnum, &reqs, &num_reqs);
1365 char errbuf[smb_size];
1366 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1367 __LINE__, __FILE__);
1368 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted,
1370 exit_server_cleanly("construct_reply_chain: "
1371 "smb1_srv_send failed.");
1377 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1379 req->conn = switch_message(req->cmd, req);
1381 if (req->outbuf == NULL) {
1383 * Request has suspended itself, will come
1388 smb_request_done(req);
1392 * To be called from an async SMB handler that is potentially chained
1393 * when it is finished for shipping.
1396 void smb_request_done(struct smb_request *req)
1398 struct smb_request **reqs = NULL;
1399 struct smb_request *first_req;
1400 size_t i, num_reqs, next_index;
1403 if (req->chain == NULL) {
1409 num_reqs = talloc_array_length(reqs);
1411 for (i=0; i<num_reqs; i++) {
1412 if (reqs[i] == req) {
1416 if (i == num_reqs) {
1418 * Invalid chain, should not happen
1420 status = NT_STATUS_INTERNAL_ERROR;
1425 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1426 struct smb_request *next = reqs[next_index];
1427 struct smbXsrv_tcon *tcon;
1428 NTTIME now = timeval_to_nttime(&req->request_time);
1430 next->vuid = SVAL(req->outbuf, smb_uid);
1431 next->tid = SVAL(req->outbuf, smb_tid);
1432 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1435 if (NT_STATUS_IS_OK(status)) {
1436 next->conn = tcon->compat;
1440 next->chain_fsp = req->chain_fsp;
1441 next->inbuf = req->inbuf;
1444 req->conn = switch_message(req->cmd, req);
1446 if (req->outbuf == NULL) {
1448 * Request has suspended itself, will come
1456 first_req = reqs[0];
1458 for (i=1; i<next_index; i++) {
1461 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1463 status = NT_STATUS_INTERNAL_ERROR;
1468 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1469 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1472 * This scary statement intends to set the
1473 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1474 * to the value last_req->outbuf carries
1476 SSVAL(first_req->outbuf, smb_flg2,
1477 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1478 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1481 * Transfer the error codes from the subrequest to the main one
1483 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1484 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1487 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1490 if (!smb1_srv_send(first_req->xconn,
1491 (char *)first_req->outbuf,
1492 true, first_req->seqnum+1,
1493 IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
1495 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1498 TALLOC_FREE(req); /* non-chained case */
1499 TALLOC_FREE(reqs); /* chained case */
1504 char errbuf[smb_size];
1505 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1506 if (!smb1_srv_send(req->xconn, errbuf, true,
1507 req->seqnum+1, req->encrypted,
1509 exit_server_cleanly("construct_reply_chain: "
1510 "smb1_srv_send failed.");
1513 TALLOC_FREE(req); /* non-chained case */
1514 TALLOC_FREE(reqs); /* chained case */
1517 /****************************************************************************
1518 Process an smb from the client
1519 ****************************************************************************/
1521 void process_smb1(struct smbXsrv_connection *xconn,
1522 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1523 uint32_t seqnum, bool encrypted,
1524 struct smb_perfcount_data *deferred_pcd)
1526 struct smbd_server_connection *sconn = xconn->client->sconn;
1528 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1529 * so subtract 4 from it. */
1530 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1531 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1534 /* special magic for immediate exit */
1536 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1537 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1538 uint8_t exitcode = CVAL(inbuf, 8);
1539 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1544 exit_server_cleanly("Non-SMB packet");
1547 show_msg((char *)inbuf);
1549 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1550 construct_reply_chain(xconn, (char *)inbuf, nread,
1551 seqnum, encrypted, deferred_pcd);
1553 construct_reply(xconn, (char *)inbuf, nread, unread_bytes,
1554 seqnum, encrypted, deferred_pcd);
1560 /****************************************************************************
1561 Return a string containing the function name of a SMB command.
1562 ****************************************************************************/
1564 const char *smb_fn_name(int type)
1566 const char *unknown_name = "SMBunknown";
1568 if (smb_messages[type].name == NULL)
1569 return(unknown_name);
1571 return(smb_messages[type].name);
1574 /****************************************************************************
1575 Helper functions for contruct_reply.
1576 ****************************************************************************/
1578 void add_to_common_flags2(uint32_t v)
1583 void remove_from_common_flags2(uint32_t v)
1585 common_flags2 &= ~v;
1589 * @brief Find the smb_cmd offset of the last command pushed
1590 * @param[in] buf The buffer we're building up
1591 * @retval Where can we put our next andx cmd?
1593 * While chaining requests, the "next" request we're looking at needs to put
1594 * its SMB_Command before the data the previous request already built up added
1595 * to the chain. Find the offset to the place where we have to put our cmd.
1598 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1603 cmd = CVAL(buf, smb_com);
1605 if (!smb1cli_is_andx_req(cmd)) {
1611 while (CVAL(buf, ofs) != 0xff) {
1613 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1618 * ofs is from start of smb header, so add the 4 length
1619 * bytes. The next cmd is right after the wct field.
1621 ofs = SVAL(buf, ofs+2) + 4 + 1;
1623 if (ofs+4 >= talloc_get_size(buf)) {
1633 * @brief Do the smb chaining at a buffer level
1634 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1635 * @param[in] andx_buf Buffer to be appended
1638 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1640 uint8_t smb_command = CVAL(andx_buf, smb_com);
1641 uint8_t wct = CVAL(andx_buf, smb_wct);
1642 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1643 uint32_t num_bytes = smb_buflen(andx_buf);
1644 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1647 size_t old_size, new_size;
1649 size_t chain_padding = 0;
1650 size_t andx_cmd_ofs;
1653 old_size = talloc_get_size(*poutbuf);
1655 if ((old_size % 4) != 0) {
1657 * Align the wct field of subsequent requests to a 4-byte
1660 chain_padding = 4 - (old_size % 4);
1664 * After the old request comes the new wct field (1 byte), the vwv's
1665 * and the num_bytes field.
1668 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1669 new_size += num_bytes;
1671 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1672 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1673 (unsigned)new_size));
1677 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1678 if (outbuf == NULL) {
1679 DEBUG(0, ("talloc failed\n"));
1684 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1685 DEBUG(1, ("invalid command chain\n"));
1686 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1690 if (chain_padding != 0) {
1691 memset(outbuf + old_size, 0, chain_padding);
1692 old_size += chain_padding;
1695 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1696 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1701 * Push the chained request:
1706 SCVAL(outbuf, ofs, wct);
1713 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1718 * Read&X has an offset into its data buffer at
1719 * vwv[6]. reply_read_andx has no idea anymore that it's
1720 * running from within a chain, so we have to fix up the
1723 * Although it looks disgusting at this place, I want to keep
1724 * it here. The alternative would be to push knowledge about
1725 * the andx chain down into read&x again.
1728 if (smb_command == SMBreadX) {
1729 uint8_t *bytes_addr;
1733 * Invalid read&x response
1738 bytes_addr = outbuf + ofs /* vwv start */
1739 + sizeof(uint16_t) * wct /* vwv array */
1740 + sizeof(uint16_t) /* bcc */
1741 + 1; /* padding byte */
1743 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1744 bytes_addr - outbuf - 4);
1747 ofs += sizeof(uint16_t) * wct;
1753 SSVAL(outbuf, ofs, num_bytes);
1754 ofs += sizeof(uint16_t);
1760 memcpy(outbuf + ofs, bytes, num_bytes);
1765 bool smb1_is_chain(const uint8_t *buf)
1767 uint8_t cmd, wct, andx_cmd;
1769 cmd = CVAL(buf, smb_com);
1770 if (!smb1cli_is_andx_req(cmd)) {
1773 wct = CVAL(buf, smb_wct);
1777 andx_cmd = CVAL(buf, smb_vwv);
1778 return (andx_cmd != 0xFF);
1781 bool smb1_walk_chain(const uint8_t *buf,
1782 bool (*fn)(uint8_t cmd,
1783 uint8_t wct, const uint16_t *vwv,
1784 uint16_t num_bytes, const uint8_t *bytes,
1785 void *private_data),
1788 size_t smblen = smb_len(buf);
1789 const char *smb_buf = smb_base(buf);
1790 uint8_t cmd, chain_cmd;
1792 const uint16_t *vwv;
1794 const uint8_t *bytes;
1796 cmd = CVAL(buf, smb_com);
1797 wct = CVAL(buf, smb_wct);
1798 vwv = (const uint16_t *)(buf + smb_vwv);
1799 num_bytes = smb_buflen(buf);
1800 bytes = (const uint8_t *)smb_buf_const(buf);
1802 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1806 if (!smb1cli_is_andx_req(cmd)) {
1813 chain_cmd = CVAL(vwv, 0);
1815 while (chain_cmd != 0xff) {
1816 uint32_t chain_offset; /* uint32_t to avoid overflow */
1817 size_t length_needed;
1818 ptrdiff_t vwv_offset;
1820 chain_offset = SVAL(vwv+1, 0);
1823 * Check if the client tries to fool us. The chain
1824 * offset needs to point beyond the current request in
1825 * the chain, it needs to strictly grow. Otherwise we
1826 * might be tricked into an endless loop always
1827 * processing the same request over and over again. We
1828 * used to assume that vwv and the byte buffer array
1829 * in a chain are always attached, but OS/2 the
1830 * Write&X/Read&X chain puts the Read&X vwv array
1831 * right behind the Write&X vwv chain. The Write&X bcc
1832 * array is put behind the Read&X vwv array. So now we
1833 * check whether the chain offset points strictly
1834 * behind the previous vwv array. req->buf points
1835 * right after the vwv array of the previous
1837 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1841 vwv_offset = ((const char *)vwv - smb_buf);
1842 if (chain_offset <= vwv_offset) {
1847 * Next check: Make sure the chain offset does not
1848 * point beyond the overall smb request length.
1851 length_needed = chain_offset+1; /* wct */
1852 if (length_needed > smblen) {
1857 * Now comes the pointer magic. Goal here is to set up
1858 * vwv and buf correctly again. The chain offset (the
1859 * former vwv[1]) points at the new wct field.
1862 wct = CVAL(smb_buf, chain_offset);
1864 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1869 * Next consistency check: Make the new vwv array fits
1870 * in the overall smb request.
1873 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1874 if (length_needed > smblen) {
1877 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1880 * Now grab the new byte buffer....
1883 num_bytes = SVAL(vwv+wct, 0);
1886 * .. and check that it fits.
1889 length_needed += num_bytes;
1890 if (length_needed > smblen) {
1893 bytes = (const uint8_t *)(vwv+wct+1);
1895 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1899 if (!smb1cli_is_andx_req(chain_cmd)) {
1902 chain_cmd = CVAL(vwv, 0);
1907 static bool smb1_chain_length_cb(uint8_t cmd,
1908 uint8_t wct, const uint16_t *vwv,
1909 uint16_t num_bytes, const uint8_t *bytes,
1912 unsigned *count = (unsigned *)private_data;
1917 unsigned smb1_chain_length(const uint8_t *buf)
1921 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1927 struct smb1_parse_chain_state {
1928 TALLOC_CTX *mem_ctx;
1930 struct smbd_server_connection *sconn;
1931 struct smbXsrv_connection *xconn;
1935 struct smb_request **reqs;
1939 static bool smb1_parse_chain_cb(uint8_t cmd,
1940 uint8_t wct, const uint16_t *vwv,
1941 uint16_t num_bytes, const uint8_t *bytes,
1944 struct smb1_parse_chain_state *state =
1945 (struct smb1_parse_chain_state *)private_data;
1946 struct smb_request **reqs;
1947 struct smb_request *req;
1950 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1951 struct smb_request *, state->num_reqs+1);
1957 req = talloc(reqs, struct smb_request);
1962 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1963 state->encrypted, state->seqnum);
1970 req->buflen = num_bytes;
1973 reqs[state->num_reqs] = req;
1974 state->num_reqs += 1;
1978 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1979 struct smbXsrv_connection *xconn,
1980 bool encrypted, uint32_t seqnum,
1981 struct smb_request ***reqs, unsigned *num_reqs)
1983 struct smbd_server_connection *sconn = NULL;
1984 struct smb1_parse_chain_state state;
1987 if (xconn != NULL) {
1988 sconn = xconn->client->sconn;
1991 state.mem_ctx = mem_ctx;
1993 state.sconn = sconn;
1994 state.xconn = xconn;
1995 state.encrypted = encrypted;
1996 state.seqnum = seqnum;
2000 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
2001 TALLOC_FREE(state.reqs);
2004 for (i=0; i<state.num_reqs; i++) {
2005 state.reqs[i]->chain = state.reqs;
2008 *num_reqs = state.num_reqs;
2012 static bool fd_is_readable(int fd)
2016 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2018 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2022 static void smbd_server_connection_write_handler(
2023 struct smbXsrv_connection *xconn)
2025 /* TODO: make write nonblocking */
2028 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2031 uint8_t *inbuf = NULL;
2032 size_t inbuf_len = 0;
2033 size_t unread_bytes = 0;
2034 bool encrypted = false;
2035 TALLOC_CTX *mem_ctx = talloc_tos();
2039 bool async_echo = lp_async_smb_echo_handler();
2040 bool from_client = false;
2043 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
2045 * This is the super-ugly hack to prefer the packets
2046 * forwarded by the echo handler over the ones by the
2049 fd = xconn->smb1.echo_handler.trusted_fd;
2053 from_client = (xconn->transport.sock == fd);
2055 if (async_echo && from_client) {
2056 smbd_lock_socket(xconn);
2058 if (!fd_is_readable(fd)) {
2059 DEBUG(10,("the echo listener was faster\n"));
2060 smbd_unlock_socket(xconn);
2065 /* TODO: make this completely nonblocking */
2066 status = receive_smb_talloc(mem_ctx, xconn, fd,
2067 (char **)(void *)&inbuf,
2071 &inbuf_len, &seqnum,
2072 !from_client /* trusted channel */);
2074 if (async_echo && from_client) {
2075 smbd_unlock_socket(xconn);
2078 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2081 if (NT_STATUS_IS_ERR(status)) {
2082 exit_server_cleanly("failed to receive smb request");
2084 if (!NT_STATUS_IS_OK(status)) {
2089 process_smb(xconn, inbuf, inbuf_len, unread_bytes,
2090 seqnum, encrypted, NULL);
2093 static void smbd_server_echo_handler(struct tevent_context *ev,
2094 struct tevent_fd *fde,
2098 struct smbXsrv_connection *xconn =
2099 talloc_get_type_abort(private_data,
2100 struct smbXsrv_connection);
2102 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2104 * we're not supposed to do any io
2106 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2107 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2111 if (flags & TEVENT_FD_WRITE) {
2112 smbd_server_connection_write_handler(xconn);
2115 if (flags & TEVENT_FD_READ) {
2116 smbd_smb1_server_connection_read_handler(
2117 xconn, xconn->smb1.echo_handler.trusted_fd);
2123 * Send keepalive packets to our client
2125 bool keepalive_fn(const struct timeval *now, void *private_data)
2127 struct smbd_server_connection *sconn = talloc_get_type_abort(
2128 private_data, struct smbd_server_connection);
2129 struct smbXsrv_connection *xconn = NULL;
2132 if (sconn->using_smb2) {
2133 /* Don't do keepalives on an SMB2 connection. */
2138 * With SMB1 we only have 1 connection
2140 xconn = sconn->client->connections;
2141 smbd_lock_socket(xconn);
2142 ret = send_keepalive(xconn->transport.sock);
2143 smbd_unlock_socket(xconn);
2146 int saved_errno = errno;
2148 * Try and give an error message saying what
2151 DEBUG(0, ("send_keepalive failed for client %s. "
2152 "Error %s - exiting\n",
2153 smbXsrv_connection_dbg(xconn),
2154 strerror(saved_errno)));
2155 errno = saved_errno;
2162 * Read an smb packet in the echo handler child, giving the parent
2163 * smbd one second to react once the socket becomes readable.
2166 struct smbd_echo_read_state {
2167 struct tevent_context *ev;
2168 struct smbXsrv_connection *xconn;
2175 static void smbd_echo_read_readable(struct tevent_req *subreq);
2176 static void smbd_echo_read_waited(struct tevent_req *subreq);
2178 static struct tevent_req *smbd_echo_read_send(
2179 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2180 struct smbXsrv_connection *xconn)
2182 struct tevent_req *req, *subreq;
2183 struct smbd_echo_read_state *state;
2185 req = tevent_req_create(mem_ctx, &state,
2186 struct smbd_echo_read_state);
2191 state->xconn = xconn;
2193 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2194 if (tevent_req_nomem(subreq, req)) {
2195 return tevent_req_post(req, ev);
2197 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2201 static void smbd_echo_read_readable(struct tevent_req *subreq)
2203 struct tevent_req *req = tevent_req_callback_data(
2204 subreq, struct tevent_req);
2205 struct smbd_echo_read_state *state = tevent_req_data(
2206 req, struct smbd_echo_read_state);
2210 ok = wait_for_read_recv(subreq, &err);
2211 TALLOC_FREE(subreq);
2213 tevent_req_nterror(req, map_nt_error_from_unix(err));
2218 * Give the parent smbd one second to step in
2221 subreq = tevent_wakeup_send(
2222 state, state->ev, timeval_current_ofs(1, 0));
2223 if (tevent_req_nomem(subreq, req)) {
2226 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2229 static void smbd_echo_read_waited(struct tevent_req *subreq)
2231 struct tevent_req *req = tevent_req_callback_data(
2232 subreq, struct tevent_req);
2233 struct smbd_echo_read_state *state = tevent_req_data(
2234 req, struct smbd_echo_read_state);
2235 struct smbXsrv_connection *xconn = state->xconn;
2241 ok = tevent_wakeup_recv(subreq);
2242 TALLOC_FREE(subreq);
2244 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2248 ok = smbd_lock_socket_internal(xconn);
2250 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2251 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2255 if (!fd_is_readable(xconn->transport.sock)) {
2256 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2259 ok = smbd_unlock_socket_internal(xconn);
2261 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2262 DEBUG(1, ("%s: failed to unlock socket\n",
2267 subreq = wait_for_read_send(state, state->ev,
2268 xconn->transport.sock, false);
2269 if (tevent_req_nomem(subreq, req)) {
2272 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2276 status = receive_smb_talloc(state, xconn,
2277 xconn->transport.sock,
2284 false /* trusted_channel*/);
2286 if (tevent_req_nterror(req, status)) {
2287 tevent_req_nterror(req, status);
2288 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2289 (int)getpid(), nt_errstr(status)));
2293 ok = smbd_unlock_socket_internal(xconn);
2295 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2296 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2299 tevent_req_done(req);
2302 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2303 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2305 struct smbd_echo_read_state *state = tevent_req_data(
2306 req, struct smbd_echo_read_state);
2309 if (tevent_req_is_nterror(req, &status)) {
2312 *pbuf = talloc_move(mem_ctx, &state->buf);
2313 *pbuflen = state->buflen;
2314 *pseqnum = state->seqnum;
2315 return NT_STATUS_OK;
2318 struct smbd_echo_state {
2319 struct tevent_context *ev;
2320 struct iovec *pending;
2321 struct smbd_server_connection *sconn;
2322 struct smbXsrv_connection *xconn;
2325 struct tevent_fd *parent_fde;
2327 struct tevent_req *write_req;
2330 static void smbd_echo_writer_done(struct tevent_req *req);
2332 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2336 if (state->write_req != NULL) {
2340 num_pending = talloc_array_length(state->pending);
2341 if (num_pending == 0) {
2345 state->write_req = writev_send(state, state->ev, NULL,
2346 state->parent_pipe, false,
2347 state->pending, num_pending);
2348 if (state->write_req == NULL) {
2349 DEBUG(1, ("writev_send failed\n"));
2353 talloc_steal(state->write_req, state->pending);
2354 state->pending = NULL;
2356 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2360 static void smbd_echo_writer_done(struct tevent_req *req)
2362 struct smbd_echo_state *state = tevent_req_callback_data(
2363 req, struct smbd_echo_state);
2367 written = writev_recv(req, &err);
2369 state->write_req = NULL;
2370 if (written == -1) {
2371 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2374 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2375 smbd_echo_activate_writer(state);
2378 static bool smbd_echo_reply(struct smbd_echo_state *state,
2379 uint8_t *inbuf, size_t inbuf_len,
2382 struct smb_request req;
2383 uint16_t num_replies;
2387 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2388 DEBUG(10, ("Got netbios keepalive\n"));
2395 if (inbuf_len < smb_size) {
2396 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2399 if (!valid_smb1_header(inbuf)) {
2400 DEBUG(10, ("Got invalid SMB header\n"));
2404 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2410 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2411 smb_messages[req.cmd].name
2412 ? smb_messages[req.cmd].name : "unknown"));
2414 if (req.cmd != SMBecho) {
2421 num_replies = SVAL(req.vwv+0, 0);
2422 if (num_replies != 1) {
2423 /* Not a Windows "Hey, you're still there?" request */
2427 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2429 DEBUG(10, ("create_smb1_outbuf failed\n"));
2432 req.outbuf = (uint8_t *)outbuf;
2434 SSVAL(req.outbuf, smb_vwv0, num_replies);
2436 if (req.buflen > 0) {
2437 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2440 ok = smb1_srv_send(req.xconn,
2444 TALLOC_FREE(outbuf);
2452 static void smbd_echo_exit(struct tevent_context *ev,
2453 struct tevent_fd *fde, uint16_t flags,
2456 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2460 static void smbd_echo_got_packet(struct tevent_req *req);
2462 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2465 struct smbd_echo_state *state;
2466 struct tevent_req *read_req;
2468 state = talloc_zero(xconn, struct smbd_echo_state);
2469 if (state == NULL) {
2470 DEBUG(1, ("talloc failed\n"));
2473 state->xconn = xconn;
2474 state->parent_pipe = parent_pipe;
2475 state->ev = samba_tevent_context_init(state);
2476 if (state->ev == NULL) {
2477 DEBUG(1, ("samba_tevent_context_init failed\n"));
2481 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2482 TEVENT_FD_READ, smbd_echo_exit,
2484 if (state->parent_fde == NULL) {
2485 DEBUG(1, ("tevent_add_fd failed\n"));
2490 read_req = smbd_echo_read_send(state, state->ev, xconn);
2491 if (read_req == NULL) {
2492 DEBUG(1, ("smbd_echo_read_send failed\n"));
2496 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2499 if (tevent_loop_once(state->ev) == -1) {
2500 DEBUG(1, ("tevent_loop_once failed: %s\n",
2508 static void smbd_echo_got_packet(struct tevent_req *req)
2510 struct smbd_echo_state *state = tevent_req_callback_data(
2511 req, struct smbd_echo_state);
2515 uint32_t seqnum = 0;
2518 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2522 nt_errstr(status)));
2526 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2532 num_pending = talloc_array_length(state->pending);
2533 tmp = talloc_realloc(state, state->pending, struct iovec,
2536 DEBUG(1, ("talloc_realloc failed\n"));
2539 state->pending = tmp;
2541 if (buflen >= smb_size) {
2543 * place the seqnum in the packet so that the main process
2544 * can reply with signing
2546 SIVAL(buf, smb_ss_field, seqnum);
2547 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2550 iov = &state->pending[num_pending];
2551 iov->iov_base = talloc_move(state->pending, &buf);
2552 iov->iov_len = buflen;
2554 DEBUG(10,("echo_handler[%d]: forward to main\n",
2556 smbd_echo_activate_writer(state);
2559 req = smbd_echo_read_send(state, state->ev, state->xconn);
2561 DEBUG(1, ("smbd_echo_read_send failed\n"));
2564 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2569 * Handle SMBecho requests in a forked child process
2571 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2573 int listener_pipe[2];
2576 bool use_mutex = false;
2578 res = pipe(listener_pipe);
2580 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2584 #ifdef HAVE_ROBUST_MUTEXES
2585 use_mutex = tdb_runtime_check_for_robust_mutexes();
2588 pthread_mutexattr_t a;
2590 xconn->smb1.echo_handler.socket_mutex =
2591 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2592 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2593 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2598 res = pthread_mutexattr_init(&a);
2600 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2604 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2606 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2608 pthread_mutexattr_destroy(&a);
2611 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2613 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2615 pthread_mutexattr_destroy(&a);
2618 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2620 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2621 "%s\n", strerror(res)));
2622 pthread_mutexattr_destroy(&a);
2625 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2627 pthread_mutexattr_destroy(&a);
2629 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2637 xconn->smb1.echo_handler.socket_lock_fd =
2638 create_unlink_tmp(lp_lock_directory());
2639 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2640 DEBUG(1, ("Could not create lock fd: %s\n",
2650 close(listener_pipe[0]);
2651 set_blocking(listener_pipe[1], false);
2653 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2654 xconn->client->raw_ev_ctx,
2656 if (!NT_STATUS_IS_OK(status)) {
2657 DEBUG(1, ("reinit_after_fork failed: %s\n",
2658 nt_errstr(status)));
2661 process_set_title("smbd-echo", "echo handler");
2662 initialize_password_db(true, xconn->client->raw_ev_ctx);
2663 smbd_echo_loop(xconn, listener_pipe[1]);
2666 close(listener_pipe[1]);
2667 listener_pipe[1] = -1;
2668 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2670 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2673 * Without smb signing this is the same as the normal smbd
2674 * listener. This needs to change once signing comes in.
2676 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2677 xconn->client->raw_ev_ctx,
2679 xconn->smb1.echo_handler.trusted_fd,
2681 smbd_server_echo_handler,
2683 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2684 DEBUG(1, ("event_add_fd failed\n"));
2691 if (listener_pipe[0] != -1) {
2692 close(listener_pipe[0]);
2694 if (listener_pipe[1] != -1) {
2695 close(listener_pipe[1]);
2697 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2698 close(xconn->smb1.echo_handler.socket_lock_fd);
2700 #ifdef HAVE_ROBUST_MUTEXES
2701 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2702 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2703 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2706 smbd_echo_init(xconn);
2711 bool req_is_in_chain(const struct smb_request *req)
2713 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2715 * We're right now handling a subsequent request, so we must
2721 if (!smb1cli_is_andx_req(req->cmd)) {
2727 * Okay, an illegal request, but definitely not chained :-)
2732 return (CVAL(req->vwv+0, 0) != 0xFF);