smbd: Remove unused "pcd" arg from smb1_srv_send()
[Samba.git] / source3 / smbd / smb1_process.c
blob0d2724fcff05f0abca99f0251b05300c6f59c79d
1 /*
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/>.
21 #include "includes.h"
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"
33 #include "passdb.h"
34 #include "auth.h"
35 #include "messages.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;
60 uint32_t seqnum;
61 bool encrypted;
62 bool processed;
63 DATA_BLOB buf;
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;
75 #endif
78 static bool smbd_echo_active(struct smbXsrv_connection *xconn)
80 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
81 return true;
84 #ifdef HAVE_ROBUST_MUTEXES
85 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
86 return true;
88 #endif
90 return false;
93 static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
95 if (!smbd_echo_active(xconn)) {
96 return true;
99 xconn->smb1.echo_handler.ref_count++;
101 if (xconn->smb1.echo_handler.ref_count > 1) {
102 return true;
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) {
109 int ret = EINTR;
111 while (ret == EINTR) {
112 ret = pthread_mutex_lock(
113 xconn->smb1.echo_handler.socket_mutex);
114 if (ret == 0) {
115 break;
118 if (ret != 0) {
119 DEBUG(1, ("pthread_mutex_lock failed: %s\n",
120 strerror(ret)));
121 return false;
124 #endif
126 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
127 bool ok;
129 do {
130 ok = fcntl_lock(
131 xconn->smb1.echo_handler.socket_lock_fd,
132 F_SETLKW, 0, 0, F_WRLCK);
133 } while (!ok && (errno == EINTR));
135 if (!ok) {
136 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
137 return false;
141 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
143 return true;
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)) {
156 return true;
159 xconn->smb1.echo_handler.ref_count--;
161 if (xconn->smb1.echo_handler.ref_count > 0) {
162 return true;
165 #ifdef HAVE_ROBUST_MUTEXES
166 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
167 int ret;
168 ret = pthread_mutex_unlock(
169 xconn->smb1.echo_handler.socket_mutex);
170 if (ret != 0) {
171 DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
172 strerror(ret)));
173 return false;
176 #endif
178 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
179 bool ok;
181 do {
182 ok = fcntl_lock(
183 xconn->smb1.echo_handler.socket_lock_fd,
184 F_SETLKW, 0, 0, F_UNLCK);
185 } while (!ok && (errno == EINTR));
187 if (!ok) {
188 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
189 return false;
193 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
195 return true;
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 /****************************************************************************
208 Send an smb to a fd.
209 ****************************************************************************/
211 bool smb1_srv_send(struct smbXsrv_connection *xconn,
212 char *buffer,
213 bool do_signing,
214 uint32_t seqnum,
215 bool do_encrypt)
217 size_t len = 0;
218 ssize_t ret;
219 char *buf_out = buffer;
221 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
223 * we're not supposed to do any io
225 return true;
228 smbd_lock_socket(xconn);
230 if (do_signing) {
231 NTSTATUS status;
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",
237 nt_errstr(status));
238 return false;
242 if (do_encrypt) {
243 char *enc = NULL;
244 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &enc);
245 if (!NT_STATUS_IS_OK(status)) {
246 DEBUG(0, ("send_smb: SMB encryption failed "
247 "on outgoing packet! Error %s\n",
248 nt_errstr(status) ));
249 SAFE_FREE(enc);
250 ret = -1;
251 goto out;
253 buf_out = enc;
256 len = smb_len_large(buf_out) + 4;
258 ret = write_data(xconn->transport.sock, buf_out, len);
259 if (ret <= 0) {
260 int saved_errno = errno;
262 * Try and give an error message saying what
263 * client failed.
265 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
266 (int)getpid(), (int)len,
267 smbXsrv_connection_dbg(xconn),
268 (int)ret, strerror(saved_errno)));
269 errno = saved_errno;
271 srv_free_enc_buffer(xconn, buf_out);
272 goto out;
275 srv_free_enc_buffer(xconn, buf_out);
276 out:
277 smbd_unlock_socket(xconn);
278 return (ret > 0);
281 /* Socket functions for smbd packet processing. */
283 static bool valid_packet_size(size_t len)
286 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
287 * of header. Don't print the error if this fits.... JRA.
290 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
291 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
292 (unsigned long)len));
293 return false;
295 return true;
298 /****************************************************************************
299 Attempt a zerocopy writeX read. We know here that len > smb_size-4
300 ****************************************************************************/
303 * Unfortunately, earlier versions of smbclient/libsmbclient
304 * don't send this "standard" writeX header. I've fixed this
305 * for 3.2 but we'll use the old method with earlier versions.
306 * Windows and CIFSFS at least use this standard size. Not
307 * sure about MacOSX.
310 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
311 (2*14) + /* word count (including bcc) */ \
312 1 /* pad byte */)
314 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
315 const char lenbuf[4],
316 struct smbXsrv_connection *xconn,
317 int sock,
318 char **buffer,
319 unsigned int timeout,
320 size_t *p_unread,
321 size_t *len_ret)
323 /* Size of a WRITEX call (+4 byte len). */
324 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
325 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
326 ssize_t toread;
327 NTSTATUS status;
329 memcpy(writeX_header, lenbuf, 4);
331 status = read_fd_with_timeout(
332 sock, writeX_header + 4,
333 STANDARD_WRITE_AND_X_HEADER_SIZE,
334 STANDARD_WRITE_AND_X_HEADER_SIZE,
335 timeout, NULL);
337 if (!NT_STATUS_IS_OK(status)) {
338 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
339 "error = %s.\n",
340 smbXsrv_connection_dbg(xconn),
341 nt_errstr(status)));
342 return status;
346 * Ok - now try and see if this is a possible
347 * valid writeX call.
350 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
352 * If the data offset is beyond what
353 * we've read, drain the extra bytes.
355 uint16_t doff = SVAL(writeX_header,smb_vwv11);
356 ssize_t newlen;
358 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
359 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
360 if (drain_socket(sock, drain) != drain) {
361 smb_panic("receive_smb_raw_talloc_partial_read:"
362 " failed to drain pending bytes");
364 } else {
365 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
368 /* Spoof down the length and null out the bcc. */
369 set_message_bcc(writeX_header, 0);
370 newlen = smb_len(writeX_header);
372 /* Copy the header we've written. */
374 *buffer = (char *)talloc_memdup(mem_ctx,
375 writeX_header,
376 sizeof(writeX_header));
378 if (*buffer == NULL) {
379 DEBUG(0, ("Could not allocate inbuf of length %d\n",
380 (int)sizeof(writeX_header)));
381 return NT_STATUS_NO_MEMORY;
384 /* Work out the remaining bytes. */
385 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
386 *len_ret = newlen + 4;
387 return NT_STATUS_OK;
390 if (!valid_packet_size(len)) {
391 return NT_STATUS_INVALID_PARAMETER;
395 * Not a valid writeX call. Just do the standard
396 * talloc and return.
399 *buffer = talloc_array(mem_ctx, char, len+4);
401 if (*buffer == NULL) {
402 DEBUG(0, ("Could not allocate inbuf of length %d\n",
403 (int)len+4));
404 return NT_STATUS_NO_MEMORY;
407 /* Copy in what we already read. */
408 memcpy(*buffer,
409 writeX_header,
410 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
411 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
413 if(toread > 0) {
414 status = read_packet_remainder(
415 sock,
416 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
417 timeout, toread);
419 if (!NT_STATUS_IS_OK(status)) {
420 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
421 nt_errstr(status)));
422 return status;
426 *len_ret = len + 4;
427 return NT_STATUS_OK;
430 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
431 struct smbXsrv_connection *xconn,
432 int sock,
433 char **buffer, unsigned int timeout,
434 size_t *p_unread, size_t *plen)
436 char lenbuf[4];
437 size_t len;
438 int min_recv_size = lp_min_receive_file_size();
439 NTSTATUS status;
441 *p_unread = 0;
443 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
444 &len);
445 if (!NT_STATUS_IS_OK(status)) {
446 return status;
449 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
450 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
451 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
452 !smb1_srv_is_signing_active(xconn) &&
453 xconn->smb1.echo_handler.trusted_fde == NULL) {
455 return receive_smb_raw_talloc_partial_read(
456 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
457 p_unread, plen);
460 if (!valid_packet_size(len)) {
461 return NT_STATUS_INVALID_PARAMETER;
465 * The +4 here can't wrap, we've checked the length above already.
468 *buffer = talloc_array(mem_ctx, char, len+4);
470 if (*buffer == NULL) {
471 DEBUG(0, ("Could not allocate inbuf of length %d\n",
472 (int)len+4));
473 return NT_STATUS_NO_MEMORY;
476 memcpy(*buffer, lenbuf, sizeof(lenbuf));
478 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
479 if (!NT_STATUS_IS_OK(status)) {
480 return status;
483 *plen = len + 4;
484 return NT_STATUS_OK;
487 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
488 struct smbXsrv_connection *xconn,
489 int sock,
490 char **buffer, unsigned int timeout,
491 size_t *p_unread, bool *p_encrypted,
492 size_t *p_len,
493 uint32_t *seqnum,
494 bool trusted_channel)
496 size_t len = 0;
497 NTSTATUS status;
499 *p_encrypted = false;
501 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
502 p_unread, &len);
503 if (!NT_STATUS_IS_OK(status)) {
504 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
505 ("receive_smb_raw_talloc failed for client %s "
506 "read error = %s.\n",
507 smbXsrv_connection_dbg(xconn),
508 nt_errstr(status)) );
509 return status;
512 if (is_encrypted_packet((uint8_t *)*buffer)) {
513 status = srv_decrypt_buffer(xconn, *buffer);
514 if (!NT_STATUS_IS_OK(status)) {
515 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
516 "incoming packet! Error %s\n",
517 nt_errstr(status) ));
518 return status;
520 *p_encrypted = true;
523 /* Check the incoming SMB signature. */
524 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
525 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
526 "incoming packet!\n"));
527 return NT_STATUS_INVALID_NETWORK_RESPONSE;
530 *p_len = len;
531 return NT_STATUS_OK;
534 /****************************************************************************
535 Function to push a message onto the tail of a linked list of smb messages ready
536 for processing.
537 ****************************************************************************/
539 static bool push_queued_message(struct smb_request *req,
540 struct timeval request_time,
541 struct timeval end_time,
542 struct deferred_open_record *open_rec)
544 int msg_len = smb_len(req->inbuf) + 4;
545 struct pending_message_list *msg;
547 msg = talloc_zero(NULL, struct pending_message_list);
549 if(msg == NULL) {
550 DEBUG(0,("push_message: malloc fail (1)\n"));
551 return False;
553 msg->sconn = req->sconn;
554 msg->xconn = req->xconn;
556 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
557 if(msg->buf.data == NULL) {
558 DEBUG(0,("push_message: malloc fail (2)\n"));
559 TALLOC_FREE(msg);
560 return False;
563 msg->request_time = request_time;
564 msg->seqnum = req->seqnum;
565 msg->encrypted = req->encrypted;
566 msg->processed = false;
568 if (open_rec) {
569 msg->open_rec = talloc_move(msg, &open_rec);
572 #if 0
573 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
574 msg,
575 end_time,
576 smbd_deferred_open_timer,
577 msg);
578 if (!msg->te) {
579 DEBUG(0,("push_message: event_add_timed failed\n"));
580 TALLOC_FREE(msg);
581 return false;
583 #endif
585 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
587 DEBUG(10,("push_message: pushed message length %u on "
588 "deferred_open_queue\n", (unsigned int)msg_len));
590 return True;
593 /****************************************************************************
594 Function to push a deferred open smb message onto a linked list of local smb
595 messages ready for processing.
596 ****************************************************************************/
598 bool push_deferred_open_message_smb1(struct smb_request *req,
599 struct timeval timeout,
600 struct file_id id,
601 struct deferred_open_record *open_rec)
603 struct timeval_buf tvbuf;
604 struct timeval end_time;
606 if (req->unread_bytes) {
607 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
608 "unread_bytes = %u\n",
609 (unsigned int)req->unread_bytes ));
610 smb_panic("push_deferred_open_message_smb: "
611 "logic error unread_bytes != 0" );
614 end_time = timeval_sum(&req->request_time, &timeout);
616 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
617 (unsigned int) smb_len(req->inbuf)+4,
618 req->mid,
619 timeval_str_buf(&end_time, false, true, &tvbuf));
621 return push_queued_message(req, req->request_time, end_time, open_rec);
625 * Only allow 5 outstanding trans requests. We're allocating memory, so
626 * prevent a DoS.
629 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
631 int count = 0;
632 for (; list != NULL; list = list->next) {
634 if (list->mid == mid) {
635 return NT_STATUS_INVALID_PARAMETER;
638 count += 1;
640 if (count > 5) {
641 return NT_STATUS_INSUFFICIENT_RESOURCES;
644 return NT_STATUS_OK;
648 These flags determine some of the permissions required to do an operation
650 Note that I don't set NEED_WRITE on some write operations because they
651 are used by some brain-dead clients when printing, and I don't want to
652 force write permissions on print services.
654 #define AS_USER (1<<0)
655 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
656 #define TIME_INIT (1<<2)
657 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
658 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
659 #define DO_CHDIR (1<<6)
662 define a list of possible SMB messages and their corresponding
663 functions. Any message that has a NULL function is unimplemented -
664 please feel free to contribute implementations!
666 static const struct smb_message_struct {
667 const char *name;
668 void (*fn)(struct smb_request *req);
669 int flags;
670 } smb_messages[256] = {
672 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
673 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
674 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
675 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
676 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
677 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
678 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
679 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
680 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
681 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
682 /* 0x0a */ { "SMBread",reply_read,AS_USER},
683 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
684 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
685 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
686 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
687 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
688 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
689 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
690 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
691 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
692 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
693 /* 0x15 */ { NULL, NULL, 0 },
694 /* 0x16 */ { NULL, NULL, 0 },
695 /* 0x17 */ { NULL, NULL, 0 },
696 /* 0x18 */ { NULL, NULL, 0 },
697 /* 0x19 */ { NULL, NULL, 0 },
698 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
699 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
700 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
701 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
702 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
703 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
704 /* 0x20 */ { "SMBwritec", NULL,0},
705 /* 0x21 */ { NULL, NULL, 0 },
706 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
707 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
708 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
709 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
710 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
711 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
712 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
713 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
714 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
715 /* 0x2b */ { "SMBecho",reply_echo,0},
716 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
717 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
718 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
719 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
720 /* 0x30 */ { NULL, NULL, 0 },
721 /* 0x31 */ { NULL, NULL, 0 },
722 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
723 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
724 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
725 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
726 /* 0x36 */ { NULL, NULL, 0 },
727 /* 0x37 */ { NULL, NULL, 0 },
728 /* 0x38 */ { NULL, NULL, 0 },
729 /* 0x39 */ { NULL, NULL, 0 },
730 /* 0x3a */ { NULL, NULL, 0 },
731 /* 0x3b */ { NULL, NULL, 0 },
732 /* 0x3c */ { NULL, NULL, 0 },
733 /* 0x3d */ { NULL, NULL, 0 },
734 /* 0x3e */ { NULL, NULL, 0 },
735 /* 0x3f */ { NULL, NULL, 0 },
736 /* 0x40 */ { NULL, NULL, 0 },
737 /* 0x41 */ { NULL, NULL, 0 },
738 /* 0x42 */ { NULL, NULL, 0 },
739 /* 0x43 */ { NULL, NULL, 0 },
740 /* 0x44 */ { NULL, NULL, 0 },
741 /* 0x45 */ { NULL, NULL, 0 },
742 /* 0x46 */ { NULL, NULL, 0 },
743 /* 0x47 */ { NULL, NULL, 0 },
744 /* 0x48 */ { NULL, NULL, 0 },
745 /* 0x49 */ { NULL, NULL, 0 },
746 /* 0x4a */ { NULL, NULL, 0 },
747 /* 0x4b */ { NULL, NULL, 0 },
748 /* 0x4c */ { NULL, NULL, 0 },
749 /* 0x4d */ { NULL, NULL, 0 },
750 /* 0x4e */ { NULL, NULL, 0 },
751 /* 0x4f */ { NULL, NULL, 0 },
752 /* 0x50 */ { NULL, NULL, 0 },
753 /* 0x51 */ { NULL, NULL, 0 },
754 /* 0x52 */ { NULL, NULL, 0 },
755 /* 0x53 */ { NULL, NULL, 0 },
756 /* 0x54 */ { NULL, NULL, 0 },
757 /* 0x55 */ { NULL, NULL, 0 },
758 /* 0x56 */ { NULL, NULL, 0 },
759 /* 0x57 */ { NULL, NULL, 0 },
760 /* 0x58 */ { NULL, NULL, 0 },
761 /* 0x59 */ { NULL, NULL, 0 },
762 /* 0x5a */ { NULL, NULL, 0 },
763 /* 0x5b */ { NULL, NULL, 0 },
764 /* 0x5c */ { NULL, NULL, 0 },
765 /* 0x5d */ { NULL, NULL, 0 },
766 /* 0x5e */ { NULL, NULL, 0 },
767 /* 0x5f */ { NULL, NULL, 0 },
768 /* 0x60 */ { NULL, NULL, 0 },
769 /* 0x61 */ { NULL, NULL, 0 },
770 /* 0x62 */ { NULL, NULL, 0 },
771 /* 0x63 */ { NULL, NULL, 0 },
772 /* 0x64 */ { NULL, NULL, 0 },
773 /* 0x65 */ { NULL, NULL, 0 },
774 /* 0x66 */ { NULL, NULL, 0 },
775 /* 0x67 */ { NULL, NULL, 0 },
776 /* 0x68 */ { NULL, NULL, 0 },
777 /* 0x69 */ { NULL, NULL, 0 },
778 /* 0x6a */ { NULL, NULL, 0 },
779 /* 0x6b */ { NULL, NULL, 0 },
780 /* 0x6c */ { NULL, NULL, 0 },
781 /* 0x6d */ { NULL, NULL, 0 },
782 /* 0x6e */ { NULL, NULL, 0 },
783 /* 0x6f */ { NULL, NULL, 0 },
784 /* 0x70 */ { "SMBtcon",reply_tcon,0},
785 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
786 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
787 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
788 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
789 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
790 /* 0x76 */ { NULL, NULL, 0 },
791 /* 0x77 */ { NULL, NULL, 0 },
792 /* 0x78 */ { NULL, NULL, 0 },
793 /* 0x79 */ { NULL, NULL, 0 },
794 /* 0x7a */ { NULL, NULL, 0 },
795 /* 0x7b */ { NULL, NULL, 0 },
796 /* 0x7c */ { NULL, NULL, 0 },
797 /* 0x7d */ { NULL, NULL, 0 },
798 /* 0x7e */ { NULL, NULL, 0 },
799 /* 0x7f */ { NULL, NULL, 0 },
800 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
801 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
802 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
803 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
804 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
805 /* 0x85 */ { NULL, NULL, 0 },
806 /* 0x86 */ { NULL, NULL, 0 },
807 /* 0x87 */ { NULL, NULL, 0 },
808 /* 0x88 */ { NULL, NULL, 0 },
809 /* 0x89 */ { NULL, NULL, 0 },
810 /* 0x8a */ { NULL, NULL, 0 },
811 /* 0x8b */ { NULL, NULL, 0 },
812 /* 0x8c */ { NULL, NULL, 0 },
813 /* 0x8d */ { NULL, NULL, 0 },
814 /* 0x8e */ { NULL, NULL, 0 },
815 /* 0x8f */ { NULL, NULL, 0 },
816 /* 0x90 */ { NULL, NULL, 0 },
817 /* 0x91 */ { NULL, NULL, 0 },
818 /* 0x92 */ { NULL, NULL, 0 },
819 /* 0x93 */ { NULL, NULL, 0 },
820 /* 0x94 */ { NULL, NULL, 0 },
821 /* 0x95 */ { NULL, NULL, 0 },
822 /* 0x96 */ { NULL, NULL, 0 },
823 /* 0x97 */ { NULL, NULL, 0 },
824 /* 0x98 */ { NULL, NULL, 0 },
825 /* 0x99 */ { NULL, NULL, 0 },
826 /* 0x9a */ { NULL, NULL, 0 },
827 /* 0x9b */ { NULL, NULL, 0 },
828 /* 0x9c */ { NULL, NULL, 0 },
829 /* 0x9d */ { NULL, NULL, 0 },
830 /* 0x9e */ { NULL, NULL, 0 },
831 /* 0x9f */ { NULL, NULL, 0 },
832 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
833 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
834 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
835 /* 0xa3 */ { NULL, NULL, 0 },
836 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
837 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
838 /* 0xa6 */ { NULL, NULL, 0 },
839 /* 0xa7 */ { NULL, NULL, 0 },
840 /* 0xa8 */ { NULL, NULL, 0 },
841 /* 0xa9 */ { NULL, NULL, 0 },
842 /* 0xaa */ { NULL, NULL, 0 },
843 /* 0xab */ { NULL, NULL, 0 },
844 /* 0xac */ { NULL, NULL, 0 },
845 /* 0xad */ { NULL, NULL, 0 },
846 /* 0xae */ { NULL, NULL, 0 },
847 /* 0xaf */ { NULL, NULL, 0 },
848 /* 0xb0 */ { NULL, NULL, 0 },
849 /* 0xb1 */ { NULL, NULL, 0 },
850 /* 0xb2 */ { NULL, NULL, 0 },
851 /* 0xb3 */ { NULL, NULL, 0 },
852 /* 0xb4 */ { NULL, NULL, 0 },
853 /* 0xb5 */ { NULL, NULL, 0 },
854 /* 0xb6 */ { NULL, NULL, 0 },
855 /* 0xb7 */ { NULL, NULL, 0 },
856 /* 0xb8 */ { NULL, NULL, 0 },
857 /* 0xb9 */ { NULL, NULL, 0 },
858 /* 0xba */ { NULL, NULL, 0 },
859 /* 0xbb */ { NULL, NULL, 0 },
860 /* 0xbc */ { NULL, NULL, 0 },
861 /* 0xbd */ { NULL, NULL, 0 },
862 /* 0xbe */ { NULL, NULL, 0 },
863 /* 0xbf */ { NULL, NULL, 0 },
864 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
865 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
866 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
867 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
868 /* 0xc4 */ { NULL, NULL, 0 },
869 /* 0xc5 */ { NULL, NULL, 0 },
870 /* 0xc6 */ { NULL, NULL, 0 },
871 /* 0xc7 */ { NULL, NULL, 0 },
872 /* 0xc8 */ { NULL, NULL, 0 },
873 /* 0xc9 */ { NULL, NULL, 0 },
874 /* 0xca */ { NULL, NULL, 0 },
875 /* 0xcb */ { NULL, NULL, 0 },
876 /* 0xcc */ { NULL, NULL, 0 },
877 /* 0xcd */ { NULL, NULL, 0 },
878 /* 0xce */ { NULL, NULL, 0 },
879 /* 0xcf */ { NULL, NULL, 0 },
880 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
881 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
882 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
883 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
884 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
885 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
886 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
887 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
888 /* 0xd8 */ { NULL, NULL, 0 },
889 /* 0xd9 */ { NULL, NULL, 0 },
890 /* 0xda */ { NULL, NULL, 0 },
891 /* 0xdb */ { NULL, NULL, 0 },
892 /* 0xdc */ { NULL, NULL, 0 },
893 /* 0xdd */ { NULL, NULL, 0 },
894 /* 0xde */ { NULL, NULL, 0 },
895 /* 0xdf */ { NULL, NULL, 0 },
896 /* 0xe0 */ { NULL, NULL, 0 },
897 /* 0xe1 */ { NULL, NULL, 0 },
898 /* 0xe2 */ { NULL, NULL, 0 },
899 /* 0xe3 */ { NULL, NULL, 0 },
900 /* 0xe4 */ { NULL, NULL, 0 },
901 /* 0xe5 */ { NULL, NULL, 0 },
902 /* 0xe6 */ { NULL, NULL, 0 },
903 /* 0xe7 */ { NULL, NULL, 0 },
904 /* 0xe8 */ { NULL, NULL, 0 },
905 /* 0xe9 */ { NULL, NULL, 0 },
906 /* 0xea */ { NULL, NULL, 0 },
907 /* 0xeb */ { NULL, NULL, 0 },
908 /* 0xec */ { NULL, NULL, 0 },
909 /* 0xed */ { NULL, NULL, 0 },
910 /* 0xee */ { NULL, NULL, 0 },
911 /* 0xef */ { NULL, NULL, 0 },
912 /* 0xf0 */ { NULL, NULL, 0 },
913 /* 0xf1 */ { NULL, NULL, 0 },
914 /* 0xf2 */ { NULL, NULL, 0 },
915 /* 0xf3 */ { NULL, NULL, 0 },
916 /* 0xf4 */ { NULL, NULL, 0 },
917 /* 0xf5 */ { NULL, NULL, 0 },
918 /* 0xf6 */ { NULL, NULL, 0 },
919 /* 0xf7 */ { NULL, NULL, 0 },
920 /* 0xf8 */ { NULL, NULL, 0 },
921 /* 0xf9 */ { NULL, NULL, 0 },
922 /* 0xfa */ { NULL, NULL, 0 },
923 /* 0xfb */ { NULL, NULL, 0 },
924 /* 0xfc */ { NULL, NULL, 0 },
925 /* 0xfd */ { NULL, NULL, 0 },
926 /* 0xfe */ { NULL, NULL, 0 },
927 /* 0xff */ { NULL, NULL, 0 }
932 /*******************************************************************
933 Dump a packet to a file.
934 ********************************************************************/
936 static void smb_dump(const char *name, int type, const char *data)
938 size_t len;
939 int fd, i;
940 char *fname = NULL;
941 if (DEBUGLEVEL < 50) {
942 return;
945 len = smb_len_tcp(data)+4;
946 for (i=1;i<100;i++) {
947 fname = talloc_asprintf(talloc_tos(),
948 "/tmp/%s.%d.%s",
949 name,
951 type ? "req" : "resp");
952 if (fname == NULL) {
953 return;
955 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
956 if (fd != -1 || errno != EEXIST) break;
957 TALLOC_FREE(fname);
959 if (fd != -1) {
960 ssize_t ret = write(fd, data, len);
961 if (ret != len)
962 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
963 close(fd);
964 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
966 TALLOC_FREE(fname);
969 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
970 struct smb_request *req,
971 uint8_t type,
972 bool *update_session_globalp,
973 bool *update_tcon_globalp)
975 connection_struct *conn = req->conn;
976 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
977 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
978 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
979 bool update_session = false;
980 bool update_tcon = false;
982 if (req->encrypted) {
983 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
986 if (smb1_srv_is_signing_active(req->xconn)) {
987 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
988 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
990 * echo can be unsigned. Sesssion setup except final
991 * session setup response too
993 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
996 update_session |= smbXsrv_set_crypto_flag(
997 &session->global->encryption_flags, encrypt_flag);
998 update_session |= smbXsrv_set_crypto_flag(
999 &session->global->signing_flags, sign_flag);
1001 if (tcon) {
1002 update_tcon |= smbXsrv_set_crypto_flag(
1003 &tcon->global->encryption_flags, encrypt_flag);
1004 update_tcon |= smbXsrv_set_crypto_flag(
1005 &tcon->global->signing_flags, sign_flag);
1008 if (update_session) {
1009 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1012 *update_session_globalp = update_session;
1013 *update_tcon_globalp = update_tcon;
1014 return;
1017 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1019 int snum;
1020 enum remote_arch_types ra_type;
1022 SMB_ASSERT(conn != NULL);
1023 SMB_ASSERT(!conn->sconn->using_smb2);
1025 snum = SNUM(conn);
1028 * Obey the client case sensitivity requests - only for clients that
1029 * support it. */
1030 switch (lp_case_sensitive(snum)) {
1031 case Auto:
1033 * We need this uglyness due to DOS/Win9x clients that lie
1034 * about case insensitivity. */
1035 ra_type = get_remote_arch();
1036 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1038 * Client can't support per-packet case sensitive
1039 * pathnames. */
1040 conn->case_sensitive = false;
1041 } else {
1042 conn->case_sensitive =
1043 !(flags & FLAG_CASELESS_PATHNAMES);
1045 break;
1046 case True:
1047 conn->case_sensitive = true;
1048 break;
1049 default:
1050 conn->case_sensitive = false;
1051 break;
1055 /****************************************************************************
1056 Prepare everything for calling the actual request function, and potentially
1057 call the request function via the "new" interface.
1059 Return False if the "legacy" function needs to be called, everything is
1060 prepared.
1062 Return True if we're done.
1064 I know this API sucks, but it is the one with the least code change I could
1065 find.
1066 ****************************************************************************/
1068 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1070 const struct loadparm_substitution *lp_sub =
1071 loadparm_s3_global_substitution();
1072 int flags;
1073 uint64_t session_tag;
1074 connection_struct *conn = NULL;
1075 struct smbXsrv_connection *xconn = req->xconn;
1076 NTTIME now = timeval_to_nttime(&req->request_time);
1077 struct smbXsrv_session *session = NULL;
1078 NTSTATUS status;
1080 errno = 0;
1082 if (!xconn->smb1.negprot.done) {
1083 switch (type) {
1085 * Without a negprot the request must
1086 * either be a negprot, or one of the
1087 * evil old SMB mailslot messaging types.
1089 case SMBnegprot:
1090 case SMBsendstrt:
1091 case SMBsendend:
1092 case SMBsendtxt:
1093 break;
1094 default:
1095 exit_server_cleanly("The first request "
1096 "should be a negprot");
1100 if (smb_messages[type].fn == NULL) {
1101 DEBUG(0,("Unknown message type %d!\n",type));
1102 smb_dump("Unknown", 1, (const char *)req->inbuf);
1103 reply_unknown_new(req, type);
1104 return NULL;
1107 flags = smb_messages[type].flags;
1109 /* In share mode security we must ignore the vuid. */
1110 session_tag = req->vuid;
1111 conn = req->conn;
1113 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1114 (int)getpid(), (unsigned long)conn));
1116 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1118 /* Ensure this value is replaced in the incoming packet. */
1119 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1122 * Ensure the correct username is in current_user_info. This is a
1123 * really ugly bugfix for problems with multiple session_setup_and_X's
1124 * being done and allowing %U and %G substitutions to work correctly.
1125 * There is a reason this code is done here, don't move it unless you
1126 * know what you're doing... :-).
1127 * JRA.
1131 * lookup an existing session
1133 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1134 * here, the main check is still in change_to_user()
1136 status = smb1srv_session_lookup(xconn,
1137 session_tag,
1138 now,
1139 &session);
1140 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1141 switch (type) {
1142 case SMBsesssetupX:
1143 status = NT_STATUS_OK;
1144 break;
1145 default:
1146 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1147 (unsigned long long)session_tag,
1148 (unsigned long long)req->mid));
1149 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1150 return conn;
1154 if (session != NULL &&
1155 session->global->auth_session_info != NULL &&
1156 !(flags & AS_USER))
1159 * change_to_user() implies set_current_user_info()
1160 * and chdir_connect_service().
1162 * So we only call set_current_user_info if
1163 * we don't have AS_USER specified.
1165 set_current_user_info(
1166 session->global->auth_session_info->unix_info->sanitized_username,
1167 session->global->auth_session_info->unix_info->unix_name,
1168 session->global->auth_session_info->info->domain_name);
1171 /* Does this call need to be run as the connected user? */
1172 if (flags & AS_USER) {
1174 /* Does this call need a valid tree connection? */
1175 if (!conn) {
1177 * Amazingly, the error code depends on the command
1178 * (from Samba4).
1180 if (type == SMBntcreateX) {
1181 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1182 } else {
1183 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1185 return NULL;
1188 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1191 * change_to_user() implies set_current_user_info()
1192 * and chdir_connect_service().
1194 if (!change_to_user_and_service(conn,session_tag)) {
1195 DEBUG(0, ("Error: Could not change to user. Removing "
1196 "deferred open, mid=%llu.\n",
1197 (unsigned long long)req->mid));
1198 reply_force_doserror(req, ERRSRV, ERRbaduid);
1199 return conn;
1202 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1204 /* Does it need write permission? */
1205 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1206 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1207 return conn;
1210 /* IPC services are limited */
1211 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1213 return conn;
1215 } else if (flags & AS_GUEST) {
1217 * Does this protocol need to be run as guest? (Only archane
1218 * messenger service requests have this...)
1220 if (!change_to_guest()) {
1221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1222 return conn;
1224 } else {
1225 /* This call needs to be run as root */
1226 change_to_root_user();
1229 /* load service specific parameters */
1230 if (conn) {
1231 if (req->encrypted) {
1232 conn->encrypted_tid = true;
1233 /* encrypted required from now on. */
1234 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1235 } else if (ENCRYPTION_REQUIRED(conn)) {
1236 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1237 DEBUG(1,("service[%s] requires encryption"
1238 "%s ACCESS_DENIED. mid=%llu\n",
1239 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1240 smb_fn_name(type),
1241 (unsigned long long)req->mid));
1242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1243 return conn;
1247 if (flags & DO_CHDIR) {
1248 bool ok;
1250 ok = chdir_current_service(conn);
1251 if (!ok) {
1252 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1253 return conn;
1256 conn->num_smb_operations++;
1260 * Update encryption and signing state tracking flags that are
1261 * used by smbstatus to display signing and encryption status.
1263 if (session != NULL) {
1264 bool update_session_global = false;
1265 bool update_tcon_global = false;
1267 req->session = session;
1269 smb1srv_update_crypto_flags(session, req, type,
1270 &update_session_global,
1271 &update_tcon_global);
1273 if (update_session_global) {
1274 status = smbXsrv_session_update(session);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1277 return conn;
1281 if (update_tcon_global) {
1282 status = smbXsrv_tcon_update(req->conn->tcon);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1285 return conn;
1290 smb_messages[type].fn(req);
1291 return req->conn;
1294 /****************************************************************************
1295 Construct a reply to the incoming packet.
1296 ****************************************************************************/
1298 void construct_reply(struct smbXsrv_connection *xconn,
1299 char *inbuf, int size, size_t unread_bytes,
1300 uint32_t seqnum, bool encrypted,
1301 struct smb_perfcount_data *deferred_pcd)
1303 struct smbd_server_connection *sconn = xconn->client->sconn;
1304 struct smb_request *req;
1306 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1307 smb_panic("could not allocate smb_request");
1310 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1311 encrypted, seqnum)) {
1312 exit_server_cleanly("Invalid SMB request");
1315 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1317 /* we popped this message off the queue - keep original perf data */
1318 if (deferred_pcd) {
1319 req->pcd = *deferred_pcd;
1322 req->conn = switch_message(req->cmd, req);
1324 if (req->outbuf == NULL) {
1326 * Request has suspended itself, will come
1327 * back here.
1329 return;
1331 if (CVAL(req->outbuf,0) == 0) {
1332 show_msg((char *)req->outbuf);
1334 smb_request_done(req);
1337 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1338 char *inbuf, int size, uint32_t seqnum,
1339 bool encrypted,
1340 struct smb_perfcount_data *deferred_pcd)
1342 struct smb_request **reqs = NULL;
1343 struct smb_request *req;
1344 unsigned num_reqs;
1345 bool ok;
1347 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1348 seqnum, &reqs, &num_reqs);
1349 if (!ok) {
1350 char errbuf[smb_size];
1351 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1352 __LINE__, __FILE__);
1353 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
1354 exit_server_cleanly("construct_reply_chain: "
1355 "smb1_srv_send failed.");
1357 return;
1360 req = reqs[0];
1361 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1363 req->conn = switch_message(req->cmd, req);
1365 if (req->outbuf == NULL) {
1367 * Request has suspended itself, will come
1368 * back here.
1370 return;
1372 smb_request_done(req);
1376 * To be called from an async SMB handler that is potentially chained
1377 * when it is finished for shipping.
1380 void smb_request_done(struct smb_request *req)
1382 struct smb_request **reqs = NULL;
1383 struct smb_request *first_req;
1384 size_t i, num_reqs, next_index;
1385 NTSTATUS status;
1387 if (req->chain == NULL) {
1388 first_req = req;
1389 goto shipit;
1392 reqs = req->chain;
1393 num_reqs = talloc_array_length(reqs);
1395 for (i=0; i<num_reqs; i++) {
1396 if (reqs[i] == req) {
1397 break;
1400 if (i == num_reqs) {
1402 * Invalid chain, should not happen
1404 status = NT_STATUS_INTERNAL_ERROR;
1405 goto error;
1407 next_index = i+1;
1409 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1410 struct smb_request *next = reqs[next_index];
1411 struct smbXsrv_tcon *tcon;
1412 NTTIME now = timeval_to_nttime(&req->request_time);
1414 next->vuid = SVAL(req->outbuf, smb_uid);
1415 next->tid = SVAL(req->outbuf, smb_tid);
1416 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1417 now, &tcon);
1419 if (NT_STATUS_IS_OK(status)) {
1420 next->conn = tcon->compat;
1421 } else {
1422 next->conn = NULL;
1424 next->chain_fsp = req->chain_fsp;
1425 next->inbuf = req->inbuf;
1427 req = next;
1428 req->conn = switch_message(req->cmd, req);
1430 if (req->outbuf == NULL) {
1432 * Request has suspended itself, will come
1433 * back here.
1435 return;
1437 next_index += 1;
1440 first_req = reqs[0];
1442 for (i=1; i<next_index; i++) {
1443 bool ok;
1445 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1446 if (!ok) {
1447 status = NT_STATUS_INTERNAL_ERROR;
1448 goto error;
1452 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1453 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1456 * This scary statement intends to set the
1457 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1458 * to the value last_req->outbuf carries
1460 SSVAL(first_req->outbuf, smb_flg2,
1461 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1462 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1465 * Transfer the error codes from the subrequest to the main one
1467 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1468 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1470 _smb_setlen_large(
1471 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1473 shipit:
1474 if (!smb1_srv_send(first_req->xconn,
1475 (char *)first_req->outbuf,
1476 true,
1477 first_req->seqnum + 1,
1478 IS_CONN_ENCRYPTED(req->conn) ||
1479 first_req->encrypted)) {
1480 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1481 "failed.");
1483 TALLOC_FREE(req); /* non-chained case */
1484 TALLOC_FREE(reqs); /* chained case */
1485 return;
1487 error:
1489 char errbuf[smb_size];
1490 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1491 if (!smb1_srv_send(req->xconn,
1492 errbuf,
1493 true,
1494 req->seqnum + 1,
1495 req->encrypted)) {
1496 exit_server_cleanly("construct_reply_chain: "
1497 "smb1_srv_send failed.");
1500 TALLOC_FREE(req); /* non-chained case */
1501 TALLOC_FREE(reqs); /* chained case */
1504 /****************************************************************************
1505 Process an smb from the client
1506 ****************************************************************************/
1508 void process_smb1(struct smbXsrv_connection *xconn,
1509 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1510 uint32_t seqnum, bool encrypted,
1511 struct smb_perfcount_data *deferred_pcd)
1513 struct smbd_server_connection *sconn = xconn->client->sconn;
1515 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1516 * so subtract 4 from it. */
1517 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1518 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1519 smb_len(inbuf)));
1521 /* special magic for immediate exit */
1522 if ((nread == 9) &&
1523 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1524 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1525 uint8_t exitcode = CVAL(inbuf, 8);
1526 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1527 (int)exitcode);
1528 exit(exitcode);
1531 exit_server_cleanly("Non-SMB packet");
1534 show_msg((char *)inbuf);
1536 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1537 construct_reply_chain(xconn, (char *)inbuf, nread,
1538 seqnum, encrypted, deferred_pcd);
1539 } else {
1540 construct_reply(xconn, (char *)inbuf, nread, unread_bytes,
1541 seqnum, encrypted, deferred_pcd);
1544 sconn->trans_num++;
1547 /****************************************************************************
1548 Return a string containing the function name of a SMB command.
1549 ****************************************************************************/
1551 const char *smb_fn_name(int type)
1553 const char *unknown_name = "SMBunknown";
1555 if (smb_messages[type].name == NULL)
1556 return(unknown_name);
1558 return(smb_messages[type].name);
1561 /****************************************************************************
1562 Helper functions for contruct_reply.
1563 ****************************************************************************/
1565 void add_to_common_flags2(uint32_t v)
1567 common_flags2 |= v;
1570 void remove_from_common_flags2(uint32_t v)
1572 common_flags2 &= ~v;
1576 * @brief Find the smb_cmd offset of the last command pushed
1577 * @param[in] buf The buffer we're building up
1578 * @retval Where can we put our next andx cmd?
1580 * While chaining requests, the "next" request we're looking at needs to put
1581 * its SMB_Command before the data the previous request already built up added
1582 * to the chain. Find the offset to the place where we have to put our cmd.
1585 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1587 uint8_t cmd;
1588 size_t ofs;
1590 cmd = CVAL(buf, smb_com);
1592 if (!smb1cli_is_andx_req(cmd)) {
1593 return false;
1596 ofs = smb_vwv0;
1598 while (CVAL(buf, ofs) != 0xff) {
1600 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1601 return false;
1605 * ofs is from start of smb header, so add the 4 length
1606 * bytes. The next cmd is right after the wct field.
1608 ofs = SVAL(buf, ofs+2) + 4 + 1;
1610 if (ofs+4 >= talloc_get_size(buf)) {
1611 return false;
1615 *pofs = ofs;
1616 return true;
1620 * @brief Do the smb chaining at a buffer level
1621 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1622 * @param[in] andx_buf Buffer to be appended
1625 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1627 uint8_t smb_command = CVAL(andx_buf, smb_com);
1628 uint8_t wct = CVAL(andx_buf, smb_wct);
1629 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1630 uint32_t num_bytes = smb_buflen(andx_buf);
1631 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1633 uint8_t *outbuf;
1634 size_t old_size, new_size;
1635 size_t ofs;
1636 size_t chain_padding = 0;
1637 size_t andx_cmd_ofs;
1640 old_size = talloc_get_size(*poutbuf);
1642 if ((old_size % 4) != 0) {
1644 * Align the wct field of subsequent requests to a 4-byte
1645 * boundary
1647 chain_padding = 4 - (old_size % 4);
1651 * After the old request comes the new wct field (1 byte), the vwv's
1652 * and the num_bytes field.
1655 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1656 new_size += num_bytes;
1658 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1659 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1660 (unsigned)new_size));
1661 return false;
1664 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1665 if (outbuf == NULL) {
1666 DEBUG(0, ("talloc failed\n"));
1667 return false;
1669 *poutbuf = outbuf;
1671 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1672 DEBUG(1, ("invalid command chain\n"));
1673 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1674 return false;
1677 if (chain_padding != 0) {
1678 memset(outbuf + old_size, 0, chain_padding);
1679 old_size += chain_padding;
1682 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1683 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1685 ofs = old_size;
1688 * Push the chained request:
1690 * wct field
1693 SCVAL(outbuf, ofs, wct);
1694 ofs += 1;
1697 * vwv array
1700 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1703 * HACK ALERT
1705 * Read&X has an offset into its data buffer at
1706 * vwv[6]. reply_read_andx has no idea anymore that it's
1707 * running from within a chain, so we have to fix up the
1708 * offset here.
1710 * Although it looks disgusting at this place, I want to keep
1711 * it here. The alternative would be to push knowledge about
1712 * the andx chain down into read&x again.
1715 if (smb_command == SMBreadX) {
1716 uint8_t *bytes_addr;
1718 if (wct < 7) {
1720 * Invalid read&x response
1722 return false;
1725 bytes_addr = outbuf + ofs /* vwv start */
1726 + sizeof(uint16_t) * wct /* vwv array */
1727 + sizeof(uint16_t) /* bcc */
1728 + 1; /* padding byte */
1730 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1731 bytes_addr - outbuf - 4);
1734 ofs += sizeof(uint16_t) * wct;
1737 * bcc (byte count)
1740 SSVAL(outbuf, ofs, num_bytes);
1741 ofs += sizeof(uint16_t);
1744 * The bytes field
1747 memcpy(outbuf + ofs, bytes, num_bytes);
1749 return true;
1752 bool smb1_is_chain(const uint8_t *buf)
1754 uint8_t cmd, wct, andx_cmd;
1756 cmd = CVAL(buf, smb_com);
1757 if (!smb1cli_is_andx_req(cmd)) {
1758 return false;
1760 wct = CVAL(buf, smb_wct);
1761 if (wct < 2) {
1762 return false;
1764 andx_cmd = CVAL(buf, smb_vwv);
1765 return (andx_cmd != 0xFF);
1768 bool smb1_walk_chain(const uint8_t *buf,
1769 bool (*fn)(uint8_t cmd,
1770 uint8_t wct, const uint16_t *vwv,
1771 uint16_t num_bytes, const uint8_t *bytes,
1772 void *private_data),
1773 void *private_data)
1775 size_t smblen = smb_len(buf);
1776 const char *smb_buf = smb_base(buf);
1777 uint8_t cmd, chain_cmd;
1778 uint8_t wct;
1779 const uint16_t *vwv;
1780 uint16_t num_bytes;
1781 const uint8_t *bytes;
1783 cmd = CVAL(buf, smb_com);
1784 wct = CVAL(buf, smb_wct);
1785 vwv = (const uint16_t *)(buf + smb_vwv);
1786 num_bytes = smb_buflen(buf);
1787 bytes = (const uint8_t *)smb_buf_const(buf);
1789 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1790 return false;
1793 if (!smb1cli_is_andx_req(cmd)) {
1794 return true;
1796 if (wct < 2) {
1797 return false;
1800 chain_cmd = CVAL(vwv, 0);
1802 while (chain_cmd != 0xff) {
1803 uint32_t chain_offset; /* uint32_t to avoid overflow */
1804 size_t length_needed;
1805 ptrdiff_t vwv_offset;
1807 chain_offset = SVAL(vwv+1, 0);
1810 * Check if the client tries to fool us. The chain
1811 * offset needs to point beyond the current request in
1812 * the chain, it needs to strictly grow. Otherwise we
1813 * might be tricked into an endless loop always
1814 * processing the same request over and over again. We
1815 * used to assume that vwv and the byte buffer array
1816 * in a chain are always attached, but OS/2 the
1817 * Write&X/Read&X chain puts the Read&X vwv array
1818 * right behind the Write&X vwv chain. The Write&X bcc
1819 * array is put behind the Read&X vwv array. So now we
1820 * check whether the chain offset points strictly
1821 * behind the previous vwv array. req->buf points
1822 * right after the vwv array of the previous
1823 * request. See
1824 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1825 * more information.
1828 vwv_offset = ((const char *)vwv - smb_buf);
1829 if (chain_offset <= vwv_offset) {
1830 return false;
1834 * Next check: Make sure the chain offset does not
1835 * point beyond the overall smb request length.
1838 length_needed = chain_offset+1; /* wct */
1839 if (length_needed > smblen) {
1840 return false;
1844 * Now comes the pointer magic. Goal here is to set up
1845 * vwv and buf correctly again. The chain offset (the
1846 * former vwv[1]) points at the new wct field.
1849 wct = CVAL(smb_buf, chain_offset);
1851 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1852 return false;
1856 * Next consistency check: Make the new vwv array fits
1857 * in the overall smb request.
1860 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1861 if (length_needed > smblen) {
1862 return false;
1864 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1867 * Now grab the new byte buffer....
1870 num_bytes = SVAL(vwv+wct, 0);
1873 * .. and check that it fits.
1876 length_needed += num_bytes;
1877 if (length_needed > smblen) {
1878 return false;
1880 bytes = (const uint8_t *)(vwv+wct+1);
1882 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1883 return false;
1886 if (!smb1cli_is_andx_req(chain_cmd)) {
1887 return true;
1889 chain_cmd = CVAL(vwv, 0);
1891 return true;
1894 static bool smb1_chain_length_cb(uint8_t cmd,
1895 uint8_t wct, const uint16_t *vwv,
1896 uint16_t num_bytes, const uint8_t *bytes,
1897 void *private_data)
1899 unsigned *count = (unsigned *)private_data;
1900 *count += 1;
1901 return true;
1904 unsigned smb1_chain_length(const uint8_t *buf)
1906 unsigned count = 0;
1908 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1909 return 0;
1911 return count;
1914 struct smb1_parse_chain_state {
1915 TALLOC_CTX *mem_ctx;
1916 const uint8_t *buf;
1917 struct smbd_server_connection *sconn;
1918 struct smbXsrv_connection *xconn;
1919 bool encrypted;
1920 uint32_t seqnum;
1922 struct smb_request **reqs;
1923 unsigned num_reqs;
1926 static bool smb1_parse_chain_cb(uint8_t cmd,
1927 uint8_t wct, const uint16_t *vwv,
1928 uint16_t num_bytes, const uint8_t *bytes,
1929 void *private_data)
1931 struct smb1_parse_chain_state *state =
1932 (struct smb1_parse_chain_state *)private_data;
1933 struct smb_request **reqs;
1934 struct smb_request *req;
1935 bool ok;
1937 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1938 struct smb_request *, state->num_reqs+1);
1939 if (reqs == NULL) {
1940 return false;
1942 state->reqs = reqs;
1944 req = talloc(reqs, struct smb_request);
1945 if (req == NULL) {
1946 return false;
1949 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1950 state->encrypted, state->seqnum);
1951 if (!ok) {
1952 return false;
1954 req->cmd = cmd;
1955 req->wct = wct;
1956 req->vwv = vwv;
1957 req->buflen = num_bytes;
1958 req->buf = bytes;
1960 reqs[state->num_reqs] = req;
1961 state->num_reqs += 1;
1962 return true;
1965 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1966 struct smbXsrv_connection *xconn,
1967 bool encrypted, uint32_t seqnum,
1968 struct smb_request ***reqs, unsigned *num_reqs)
1970 struct smbd_server_connection *sconn = NULL;
1971 struct smb1_parse_chain_state state;
1972 unsigned i;
1974 if (xconn != NULL) {
1975 sconn = xconn->client->sconn;
1978 state.mem_ctx = mem_ctx;
1979 state.buf = buf;
1980 state.sconn = sconn;
1981 state.xconn = xconn;
1982 state.encrypted = encrypted;
1983 state.seqnum = seqnum;
1984 state.reqs = NULL;
1985 state.num_reqs = 0;
1987 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1988 TALLOC_FREE(state.reqs);
1989 return false;
1991 for (i=0; i<state.num_reqs; i++) {
1992 state.reqs[i]->chain = state.reqs;
1994 *reqs = state.reqs;
1995 *num_reqs = state.num_reqs;
1996 return true;
1999 static bool fd_is_readable(int fd)
2001 int ret, revents;
2003 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2005 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2009 static void smbd_server_connection_write_handler(
2010 struct smbXsrv_connection *xconn)
2012 /* TODO: make write nonblocking */
2015 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2016 int fd)
2018 uint8_t *inbuf = NULL;
2019 size_t inbuf_len = 0;
2020 size_t unread_bytes = 0;
2021 bool encrypted = false;
2022 TALLOC_CTX *mem_ctx = talloc_tos();
2023 NTSTATUS status;
2024 uint32_t seqnum;
2026 bool async_echo = lp_async_smb_echo_handler();
2027 bool from_client = false;
2029 if (async_echo) {
2030 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
2032 * This is the super-ugly hack to prefer the packets
2033 * forwarded by the echo handler over the ones by the
2034 * client directly
2036 fd = xconn->smb1.echo_handler.trusted_fd;
2040 from_client = (xconn->transport.sock == fd);
2042 if (async_echo && from_client) {
2043 smbd_lock_socket(xconn);
2045 if (!fd_is_readable(fd)) {
2046 DEBUG(10,("the echo listener was faster\n"));
2047 smbd_unlock_socket(xconn);
2048 return;
2052 /* TODO: make this completely nonblocking */
2053 status = receive_smb_talloc(mem_ctx, xconn, fd,
2054 (char **)(void *)&inbuf,
2055 0, /* timeout */
2056 &unread_bytes,
2057 &encrypted,
2058 &inbuf_len, &seqnum,
2059 !from_client /* trusted channel */);
2061 if (async_echo && from_client) {
2062 smbd_unlock_socket(xconn);
2065 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2066 goto process;
2068 if (NT_STATUS_IS_ERR(status)) {
2069 exit_server_cleanly("failed to receive smb request");
2071 if (!NT_STATUS_IS_OK(status)) {
2072 return;
2075 process:
2076 process_smb(xconn, inbuf, inbuf_len, unread_bytes,
2077 seqnum, encrypted, NULL);
2080 static void smbd_server_echo_handler(struct tevent_context *ev,
2081 struct tevent_fd *fde,
2082 uint16_t flags,
2083 void *private_data)
2085 struct smbXsrv_connection *xconn =
2086 talloc_get_type_abort(private_data,
2087 struct smbXsrv_connection);
2089 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2091 * we're not supposed to do any io
2093 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2094 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2095 return;
2098 if (flags & TEVENT_FD_WRITE) {
2099 smbd_server_connection_write_handler(xconn);
2100 return;
2102 if (flags & TEVENT_FD_READ) {
2103 smbd_smb1_server_connection_read_handler(
2104 xconn, xconn->smb1.echo_handler.trusted_fd);
2105 return;
2110 * Send keepalive packets to our client
2112 bool keepalive_fn(const struct timeval *now, void *private_data)
2114 struct smbd_server_connection *sconn = talloc_get_type_abort(
2115 private_data, struct smbd_server_connection);
2116 struct smbXsrv_connection *xconn = NULL;
2117 bool ret;
2119 if (sconn->using_smb2) {
2120 /* Don't do keepalives on an SMB2 connection. */
2121 return false;
2125 * With SMB1 we only have 1 connection
2127 xconn = sconn->client->connections;
2128 smbd_lock_socket(xconn);
2129 ret = send_keepalive(xconn->transport.sock);
2130 smbd_unlock_socket(xconn);
2132 if (!ret) {
2133 int saved_errno = errno;
2135 * Try and give an error message saying what
2136 * client failed.
2138 DEBUG(0, ("send_keepalive failed for client %s. "
2139 "Error %s - exiting\n",
2140 smbXsrv_connection_dbg(xconn),
2141 strerror(saved_errno)));
2142 errno = saved_errno;
2143 return False;
2145 return True;
2149 * Read an smb packet in the echo handler child, giving the parent
2150 * smbd one second to react once the socket becomes readable.
2153 struct smbd_echo_read_state {
2154 struct tevent_context *ev;
2155 struct smbXsrv_connection *xconn;
2157 char *buf;
2158 size_t buflen;
2159 uint32_t seqnum;
2162 static void smbd_echo_read_readable(struct tevent_req *subreq);
2163 static void smbd_echo_read_waited(struct tevent_req *subreq);
2165 static struct tevent_req *smbd_echo_read_send(
2166 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2167 struct smbXsrv_connection *xconn)
2169 struct tevent_req *req, *subreq;
2170 struct smbd_echo_read_state *state;
2172 req = tevent_req_create(mem_ctx, &state,
2173 struct smbd_echo_read_state);
2174 if (req == NULL) {
2175 return NULL;
2177 state->ev = ev;
2178 state->xconn = xconn;
2180 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2181 if (tevent_req_nomem(subreq, req)) {
2182 return tevent_req_post(req, ev);
2184 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2185 return req;
2188 static void smbd_echo_read_readable(struct tevent_req *subreq)
2190 struct tevent_req *req = tevent_req_callback_data(
2191 subreq, struct tevent_req);
2192 struct smbd_echo_read_state *state = tevent_req_data(
2193 req, struct smbd_echo_read_state);
2194 bool ok;
2195 int err;
2197 ok = wait_for_read_recv(subreq, &err);
2198 TALLOC_FREE(subreq);
2199 if (!ok) {
2200 tevent_req_nterror(req, map_nt_error_from_unix(err));
2201 return;
2205 * Give the parent smbd one second to step in
2208 subreq = tevent_wakeup_send(
2209 state, state->ev, timeval_current_ofs(1, 0));
2210 if (tevent_req_nomem(subreq, req)) {
2211 return;
2213 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2216 static void smbd_echo_read_waited(struct tevent_req *subreq)
2218 struct tevent_req *req = tevent_req_callback_data(
2219 subreq, struct tevent_req);
2220 struct smbd_echo_read_state *state = tevent_req_data(
2221 req, struct smbd_echo_read_state);
2222 struct smbXsrv_connection *xconn = state->xconn;
2223 bool ok;
2224 NTSTATUS status;
2225 size_t unread = 0;
2226 bool encrypted;
2228 ok = tevent_wakeup_recv(subreq);
2229 TALLOC_FREE(subreq);
2230 if (!ok) {
2231 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2232 return;
2235 ok = smbd_lock_socket_internal(xconn);
2236 if (!ok) {
2237 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2238 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2239 return;
2242 if (!fd_is_readable(xconn->transport.sock)) {
2243 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2244 (int)getpid()));
2246 ok = smbd_unlock_socket_internal(xconn);
2247 if (!ok) {
2248 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2249 DEBUG(1, ("%s: failed to unlock socket\n",
2250 __location__));
2251 return;
2254 subreq = wait_for_read_send(state, state->ev,
2255 xconn->transport.sock, false);
2256 if (tevent_req_nomem(subreq, req)) {
2257 return;
2259 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2260 return;
2263 status = receive_smb_talloc(state, xconn,
2264 xconn->transport.sock,
2265 &state->buf,
2266 0 /* timeout */,
2267 &unread,
2268 &encrypted,
2269 &state->buflen,
2270 &state->seqnum,
2271 false /* trusted_channel*/);
2273 if (tevent_req_nterror(req, status)) {
2274 tevent_req_nterror(req, status);
2275 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2276 (int)getpid(), nt_errstr(status)));
2277 return;
2280 ok = smbd_unlock_socket_internal(xconn);
2281 if (!ok) {
2282 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2283 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2284 return;
2286 tevent_req_done(req);
2289 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2290 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2292 struct smbd_echo_read_state *state = tevent_req_data(
2293 req, struct smbd_echo_read_state);
2294 NTSTATUS status;
2296 if (tevent_req_is_nterror(req, &status)) {
2297 return status;
2299 *pbuf = talloc_move(mem_ctx, &state->buf);
2300 *pbuflen = state->buflen;
2301 *pseqnum = state->seqnum;
2302 return NT_STATUS_OK;
2305 struct smbd_echo_state {
2306 struct tevent_context *ev;
2307 struct iovec *pending;
2308 struct smbd_server_connection *sconn;
2309 struct smbXsrv_connection *xconn;
2310 int parent_pipe;
2312 struct tevent_fd *parent_fde;
2314 struct tevent_req *write_req;
2317 static void smbd_echo_writer_done(struct tevent_req *req);
2319 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2321 int num_pending;
2323 if (state->write_req != NULL) {
2324 return;
2327 num_pending = talloc_array_length(state->pending);
2328 if (num_pending == 0) {
2329 return;
2332 state->write_req = writev_send(state, state->ev, NULL,
2333 state->parent_pipe, false,
2334 state->pending, num_pending);
2335 if (state->write_req == NULL) {
2336 DEBUG(1, ("writev_send failed\n"));
2337 exit(1);
2340 talloc_steal(state->write_req, state->pending);
2341 state->pending = NULL;
2343 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2344 state);
2347 static void smbd_echo_writer_done(struct tevent_req *req)
2349 struct smbd_echo_state *state = tevent_req_callback_data(
2350 req, struct smbd_echo_state);
2351 ssize_t written;
2352 int err;
2354 written = writev_recv(req, &err);
2355 TALLOC_FREE(req);
2356 state->write_req = NULL;
2357 if (written == -1) {
2358 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2359 exit(1);
2361 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2362 smbd_echo_activate_writer(state);
2365 static bool smbd_echo_reply(struct smbd_echo_state *state,
2366 uint8_t *inbuf, size_t inbuf_len,
2367 uint32_t seqnum)
2369 struct smb_request req;
2370 uint16_t num_replies;
2371 char *outbuf;
2372 bool ok;
2374 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2375 DEBUG(10, ("Got netbios keepalive\n"));
2377 * Just swallow it
2379 return true;
2382 if (inbuf_len < smb_size) {
2383 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2384 return false;
2386 if (!valid_smb1_header(inbuf)) {
2387 DEBUG(10, ("Got invalid SMB header\n"));
2388 return false;
2391 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2392 seqnum)) {
2393 return false;
2395 req.inbuf = inbuf;
2397 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2398 smb_messages[req.cmd].name
2399 ? smb_messages[req.cmd].name : "unknown"));
2401 if (req.cmd != SMBecho) {
2402 return false;
2404 if (req.wct < 1) {
2405 return false;
2408 num_replies = SVAL(req.vwv+0, 0);
2409 if (num_replies != 1) {
2410 /* Not a Windows "Hey, you're still there?" request */
2411 return false;
2414 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2415 1, req.buflen)) {
2416 DEBUG(10, ("create_smb1_outbuf failed\n"));
2417 return false;
2419 req.outbuf = (uint8_t *)outbuf;
2421 SSVAL(req.outbuf, smb_vwv0, num_replies);
2423 if (req.buflen > 0) {
2424 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2427 ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
2428 TALLOC_FREE(outbuf);
2429 if (!ok) {
2430 exit(1);
2433 return true;
2436 static void smbd_echo_exit(struct tevent_context *ev,
2437 struct tevent_fd *fde, uint16_t flags,
2438 void *private_data)
2440 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2441 exit(0);
2444 static void smbd_echo_got_packet(struct tevent_req *req);
2446 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2447 int parent_pipe)
2449 struct smbd_echo_state *state;
2450 struct tevent_req *read_req;
2452 state = talloc_zero(xconn, struct smbd_echo_state);
2453 if (state == NULL) {
2454 DEBUG(1, ("talloc failed\n"));
2455 return;
2457 state->xconn = xconn;
2458 state->parent_pipe = parent_pipe;
2459 state->ev = samba_tevent_context_init(state);
2460 if (state->ev == NULL) {
2461 DEBUG(1, ("samba_tevent_context_init failed\n"));
2462 TALLOC_FREE(state);
2463 return;
2465 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2466 TEVENT_FD_READ, smbd_echo_exit,
2467 state);
2468 if (state->parent_fde == NULL) {
2469 DEBUG(1, ("tevent_add_fd failed\n"));
2470 TALLOC_FREE(state);
2471 return;
2474 read_req = smbd_echo_read_send(state, state->ev, xconn);
2475 if (read_req == NULL) {
2476 DEBUG(1, ("smbd_echo_read_send failed\n"));
2477 TALLOC_FREE(state);
2478 return;
2480 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2482 while (true) {
2483 if (tevent_loop_once(state->ev) == -1) {
2484 DEBUG(1, ("tevent_loop_once failed: %s\n",
2485 strerror(errno)));
2486 break;
2489 TALLOC_FREE(state);
2492 static void smbd_echo_got_packet(struct tevent_req *req)
2494 struct smbd_echo_state *state = tevent_req_callback_data(
2495 req, struct smbd_echo_state);
2496 NTSTATUS status;
2497 char *buf = NULL;
2498 size_t buflen = 0;
2499 uint32_t seqnum = 0;
2500 bool reply;
2502 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2503 TALLOC_FREE(req);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2506 nt_errstr(status)));
2507 exit(1);
2510 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2511 if (!reply) {
2512 size_t num_pending;
2513 struct iovec *tmp;
2514 struct iovec *iov;
2516 num_pending = talloc_array_length(state->pending);
2517 tmp = talloc_realloc(state, state->pending, struct iovec,
2518 num_pending+1);
2519 if (tmp == NULL) {
2520 DEBUG(1, ("talloc_realloc failed\n"));
2521 exit(1);
2523 state->pending = tmp;
2525 if (buflen >= smb_size) {
2527 * place the seqnum in the packet so that the main process
2528 * can reply with signing
2530 SIVAL(buf, smb_ss_field, seqnum);
2531 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2534 iov = &state->pending[num_pending];
2535 iov->iov_base = talloc_move(state->pending, &buf);
2536 iov->iov_len = buflen;
2538 DEBUG(10,("echo_handler[%d]: forward to main\n",
2539 (int)getpid()));
2540 smbd_echo_activate_writer(state);
2543 req = smbd_echo_read_send(state, state->ev, state->xconn);
2544 if (req == NULL) {
2545 DEBUG(1, ("smbd_echo_read_send failed\n"));
2546 exit(1);
2548 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2553 * Handle SMBecho requests in a forked child process
2555 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2557 int listener_pipe[2];
2558 int res;
2559 pid_t child;
2560 bool use_mutex = false;
2562 res = pipe(listener_pipe);
2563 if (res == -1) {
2564 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2565 return false;
2568 #ifdef HAVE_ROBUST_MUTEXES
2569 use_mutex = tdb_runtime_check_for_robust_mutexes();
2571 if (use_mutex) {
2572 pthread_mutexattr_t a;
2574 xconn->smb1.echo_handler.socket_mutex =
2575 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2576 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2577 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2578 strerror(errno)));
2579 goto fail;
2582 res = pthread_mutexattr_init(&a);
2583 if (res != 0) {
2584 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2585 strerror(res)));
2586 goto fail;
2588 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2589 if (res != 0) {
2590 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2591 strerror(res)));
2592 pthread_mutexattr_destroy(&a);
2593 goto fail;
2595 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2596 if (res != 0) {
2597 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2598 strerror(res)));
2599 pthread_mutexattr_destroy(&a);
2600 goto fail;
2602 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2603 if (res != 0) {
2604 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2605 "%s\n", strerror(res)));
2606 pthread_mutexattr_destroy(&a);
2607 goto fail;
2609 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2610 &a);
2611 pthread_mutexattr_destroy(&a);
2612 if (res != 0) {
2613 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2614 strerror(res)));
2615 goto fail;
2618 #endif
2620 if (!use_mutex) {
2621 xconn->smb1.echo_handler.socket_lock_fd =
2622 create_unlink_tmp(lp_lock_directory());
2623 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2624 DEBUG(1, ("Could not create lock fd: %s\n",
2625 strerror(errno)));
2626 goto fail;
2630 child = fork();
2631 if (child == 0) {
2632 NTSTATUS status;
2634 close(listener_pipe[0]);
2635 set_blocking(listener_pipe[1], false);
2637 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2638 xconn->client->raw_ev_ctx,
2639 true);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 DEBUG(1, ("reinit_after_fork failed: %s\n",
2642 nt_errstr(status)));
2643 exit(1);
2645 process_set_title("smbd-echo", "echo handler");
2646 initialize_password_db(true, xconn->client->raw_ev_ctx);
2647 smbd_echo_loop(xconn, listener_pipe[1]);
2648 exit(0);
2650 close(listener_pipe[1]);
2651 listener_pipe[1] = -1;
2652 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2654 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2657 * Without smb signing this is the same as the normal smbd
2658 * listener. This needs to change once signing comes in.
2660 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2661 xconn->client->raw_ev_ctx,
2662 xconn,
2663 xconn->smb1.echo_handler.trusted_fd,
2664 TEVENT_FD_READ,
2665 smbd_server_echo_handler,
2666 xconn);
2667 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2668 DEBUG(1, ("event_add_fd failed\n"));
2669 goto fail;
2672 return true;
2674 fail:
2675 if (listener_pipe[0] != -1) {
2676 close(listener_pipe[0]);
2678 if (listener_pipe[1] != -1) {
2679 close(listener_pipe[1]);
2681 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2682 close(xconn->smb1.echo_handler.socket_lock_fd);
2684 #ifdef HAVE_ROBUST_MUTEXES
2685 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2686 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2687 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2689 #endif
2690 smbd_echo_init(xconn);
2692 return false;
2695 bool req_is_in_chain(const struct smb_request *req)
2697 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2699 * We're right now handling a subsequent request, so we must
2700 * be in a chain
2702 return true;
2705 if (!smb1cli_is_andx_req(req->cmd)) {
2706 return false;
2709 if (req->wct < 2) {
2711 * Okay, an illegal request, but definitely not chained :-)
2713 return false;
2716 return (CVAL(req->vwv+0, 0) != 0xFF);