s4:dsdb:tests: Also pass tests if asserted identity is present
[Samba.git] / source3 / smbd / smb1_process.c
blobc041b48d88d07cc32f1a845e156eb7a173460db1
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"
51 /* Internal message queue for deferred opens. */
52 struct pending_message_list {
53 struct pending_message_list *next, *prev;
54 struct timeval request_time; /* When was this first issued? */
55 struct smbd_server_connection *sconn;
56 struct smbXsrv_connection *xconn;
57 struct tevent_timer *te;
58 struct smb_perfcount_data pcd;
59 uint32_t seqnum;
60 bool encrypted;
61 bool processed;
62 DATA_BLOB buf;
63 struct deferred_open_record *open_rec;
66 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
68 void smbd_echo_init(struct smbXsrv_connection *xconn)
70 xconn->smb1.echo_handler.trusted_fd = -1;
71 xconn->smb1.echo_handler.socket_lock_fd = -1;
72 #ifdef HAVE_ROBUST_MUTEXES
73 xconn->smb1.echo_handler.socket_mutex = NULL;
74 #endif
77 static bool smbd_echo_active(struct smbXsrv_connection *xconn)
79 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
80 return true;
83 #ifdef HAVE_ROBUST_MUTEXES
84 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
85 return true;
87 #endif
89 return false;
92 static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
94 if (!smbd_echo_active(xconn)) {
95 return true;
98 xconn->smb1.echo_handler.ref_count++;
100 if (xconn->smb1.echo_handler.ref_count > 1) {
101 return true;
104 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
106 #ifdef HAVE_ROBUST_MUTEXES
107 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
108 int ret = EINTR;
110 while (ret == EINTR) {
111 ret = pthread_mutex_lock(
112 xconn->smb1.echo_handler.socket_mutex);
113 if (ret == 0) {
114 break;
117 if (ret != 0) {
118 DEBUG(1, ("pthread_mutex_lock failed: %s\n",
119 strerror(ret)));
120 return false;
123 #endif
125 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
126 bool ok;
128 do {
129 ok = fcntl_lock(
130 xconn->smb1.echo_handler.socket_lock_fd,
131 F_SETLKW, 0, 0, F_WRLCK);
132 } while (!ok && (errno == EINTR));
134 if (!ok) {
135 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
136 return false;
140 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
142 return true;
145 void smbd_lock_socket(struct smbXsrv_connection *xconn)
147 if (!smbd_lock_socket_internal(xconn)) {
148 exit_server_cleanly("failed to lock socket");
152 static bool smbd_unlock_socket_internal(struct smbXsrv_connection *xconn)
154 if (!smbd_echo_active(xconn)) {
155 return true;
158 xconn->smb1.echo_handler.ref_count--;
160 if (xconn->smb1.echo_handler.ref_count > 0) {
161 return true;
164 #ifdef HAVE_ROBUST_MUTEXES
165 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
166 int ret;
167 ret = pthread_mutex_unlock(
168 xconn->smb1.echo_handler.socket_mutex);
169 if (ret != 0) {
170 DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
171 strerror(ret)));
172 return false;
175 #endif
177 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
178 bool ok;
180 do {
181 ok = fcntl_lock(
182 xconn->smb1.echo_handler.socket_lock_fd,
183 F_SETLKW, 0, 0, F_UNLCK);
184 } while (!ok && (errno == EINTR));
186 if (!ok) {
187 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
188 return false;
192 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
194 return true;
197 void smbd_unlock_socket(struct smbXsrv_connection *xconn)
199 if (!smbd_unlock_socket_internal(xconn)) {
200 exit_server_cleanly("failed to unlock socket");
204 /* Accessor function for smb_read_error for smbd functions. */
206 /****************************************************************************
207 Send an smb to a fd.
208 ****************************************************************************/
210 bool smb1_srv_send(struct smbXsrv_connection *xconn, char *buffer,
211 bool do_signing, uint32_t seqnum,
212 bool do_encrypt,
213 struct smb_perfcount_data *pcd)
215 size_t len = 0;
216 ssize_t ret;
217 char *buf_out = buffer;
219 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
221 * we're not supposed to do any io
223 return true;
226 smbd_lock_socket(xconn);
228 if (do_signing) {
229 NTSTATUS status;
231 /* Sign the outgoing packet if required. */
232 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
233 if (!NT_STATUS_IS_OK(status)) {
234 DBG_ERR("Failed to calculate signing mac: %s\n",
235 nt_errstr(status));
236 return false;
240 if (do_encrypt) {
241 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &buf_out);
242 if (!NT_STATUS_IS_OK(status)) {
243 DEBUG(0, ("send_smb: SMB encryption failed "
244 "on outgoing packet! Error %s\n",
245 nt_errstr(status) ));
246 ret = -1;
247 goto out;
251 len = smb_len_large(buf_out) + 4;
253 ret = write_data(xconn->transport.sock, buf_out, len);
254 if (ret <= 0) {
255 int saved_errno = errno;
257 * Try and give an error message saying what
258 * client failed.
260 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
261 (int)getpid(), (int)len,
262 smbXsrv_connection_dbg(xconn),
263 (int)ret, strerror(saved_errno)));
264 errno = saved_errno;
266 srv_free_enc_buffer(xconn, buf_out);
267 goto out;
270 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
271 srv_free_enc_buffer(xconn, buf_out);
272 out:
273 SMB_PERFCOUNT_END(pcd);
275 smbd_unlock_socket(xconn);
276 return (ret > 0);
279 /* Socket functions for smbd packet processing. */
281 static bool valid_packet_size(size_t len)
284 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
285 * of header. Don't print the error if this fits.... JRA.
288 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
289 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
290 (unsigned long)len));
291 return false;
293 return true;
296 /****************************************************************************
297 Attempt a zerocopy writeX read. We know here that len > smb_size-4
298 ****************************************************************************/
301 * Unfortunately, earlier versions of smbclient/libsmbclient
302 * don't send this "standard" writeX header. I've fixed this
303 * for 3.2 but we'll use the old method with earlier versions.
304 * Windows and CIFSFS at least use this standard size. Not
305 * sure about MacOSX.
308 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
309 (2*14) + /* word count (including bcc) */ \
310 1 /* pad byte */)
312 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
313 const char lenbuf[4],
314 struct smbXsrv_connection *xconn,
315 int sock,
316 char **buffer,
317 unsigned int timeout,
318 size_t *p_unread,
319 size_t *len_ret)
321 /* Size of a WRITEX call (+4 byte len). */
322 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
323 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
324 ssize_t toread;
325 NTSTATUS status;
327 memcpy(writeX_header, lenbuf, 4);
329 status = read_fd_with_timeout(
330 sock, writeX_header + 4,
331 STANDARD_WRITE_AND_X_HEADER_SIZE,
332 STANDARD_WRITE_AND_X_HEADER_SIZE,
333 timeout, NULL);
335 if (!NT_STATUS_IS_OK(status)) {
336 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
337 "error = %s.\n",
338 smbXsrv_connection_dbg(xconn),
339 nt_errstr(status)));
340 return status;
344 * Ok - now try and see if this is a possible
345 * valid writeX call.
348 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
350 * If the data offset is beyond what
351 * we've read, drain the extra bytes.
353 uint16_t doff = SVAL(writeX_header,smb_vwv11);
354 ssize_t newlen;
356 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
357 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
358 if (drain_socket(sock, drain) != drain) {
359 smb_panic("receive_smb_raw_talloc_partial_read:"
360 " failed to drain pending bytes");
362 } else {
363 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
366 /* Spoof down the length and null out the bcc. */
367 set_message_bcc(writeX_header, 0);
368 newlen = smb_len(writeX_header);
370 /* Copy the header we've written. */
372 *buffer = (char *)talloc_memdup(mem_ctx,
373 writeX_header,
374 sizeof(writeX_header));
376 if (*buffer == NULL) {
377 DEBUG(0, ("Could not allocate inbuf of length %d\n",
378 (int)sizeof(writeX_header)));
379 return NT_STATUS_NO_MEMORY;
382 /* Work out the remaining bytes. */
383 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
384 *len_ret = newlen + 4;
385 return NT_STATUS_OK;
388 if (!valid_packet_size(len)) {
389 return NT_STATUS_INVALID_PARAMETER;
393 * Not a valid writeX call. Just do the standard
394 * talloc and return.
397 *buffer = talloc_array(mem_ctx, char, len+4);
399 if (*buffer == NULL) {
400 DEBUG(0, ("Could not allocate inbuf of length %d\n",
401 (int)len+4));
402 return NT_STATUS_NO_MEMORY;
405 /* Copy in what we already read. */
406 memcpy(*buffer,
407 writeX_header,
408 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
409 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
411 if(toread > 0) {
412 status = read_packet_remainder(
413 sock,
414 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
415 timeout, toread);
417 if (!NT_STATUS_IS_OK(status)) {
418 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
419 nt_errstr(status)));
420 return status;
424 *len_ret = len + 4;
425 return NT_STATUS_OK;
428 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
429 struct smbXsrv_connection *xconn,
430 int sock,
431 char **buffer, unsigned int timeout,
432 size_t *p_unread, size_t *plen)
434 char lenbuf[4];
435 size_t len;
436 int min_recv_size = lp_min_receive_file_size();
437 NTSTATUS status;
439 *p_unread = 0;
441 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
442 &len);
443 if (!NT_STATUS_IS_OK(status)) {
444 return status;
447 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
448 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
449 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
450 !smb1_srv_is_signing_active(xconn) &&
451 xconn->smb1.echo_handler.trusted_fde == NULL) {
453 return receive_smb_raw_talloc_partial_read(
454 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
455 p_unread, plen);
458 if (!valid_packet_size(len)) {
459 return NT_STATUS_INVALID_PARAMETER;
463 * The +4 here can't wrap, we've checked the length above already.
466 *buffer = talloc_array(mem_ctx, char, len+4);
468 if (*buffer == NULL) {
469 DEBUG(0, ("Could not allocate inbuf of length %d\n",
470 (int)len+4));
471 return NT_STATUS_NO_MEMORY;
474 memcpy(*buffer, lenbuf, sizeof(lenbuf));
476 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
477 if (!NT_STATUS_IS_OK(status)) {
478 return status;
481 *plen = len + 4;
482 return NT_STATUS_OK;
485 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
486 struct smbXsrv_connection *xconn,
487 int sock,
488 char **buffer, unsigned int timeout,
489 size_t *p_unread, bool *p_encrypted,
490 size_t *p_len,
491 uint32_t *seqnum,
492 bool trusted_channel)
494 size_t len = 0;
495 NTSTATUS status;
497 *p_encrypted = false;
499 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
500 p_unread, &len);
501 if (!NT_STATUS_IS_OK(status)) {
502 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
503 ("receive_smb_raw_talloc failed for client %s "
504 "read error = %s.\n",
505 smbXsrv_connection_dbg(xconn),
506 nt_errstr(status)) );
507 return status;
510 if (is_encrypted_packet((uint8_t *)*buffer)) {
511 status = srv_decrypt_buffer(xconn, *buffer);
512 if (!NT_STATUS_IS_OK(status)) {
513 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
514 "incoming packet! Error %s\n",
515 nt_errstr(status) ));
516 return status;
518 *p_encrypted = true;
521 /* Check the incoming SMB signature. */
522 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
523 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
524 "incoming packet!\n"));
525 return NT_STATUS_INVALID_NETWORK_RESPONSE;
528 *p_len = len;
529 return NT_STATUS_OK;
532 /****************************************************************************
533 Function to push a message onto the tail of a linked list of smb messages ready
534 for processing.
535 ****************************************************************************/
537 static bool push_queued_message(struct smb_request *req,
538 struct timeval request_time,
539 struct timeval end_time,
540 struct deferred_open_record *open_rec)
542 int msg_len = smb_len(req->inbuf) + 4;
543 struct pending_message_list *msg;
545 msg = talloc_zero(NULL, struct pending_message_list);
547 if(msg == NULL) {
548 DEBUG(0,("push_message: malloc fail (1)\n"));
549 return False;
551 msg->sconn = req->sconn;
552 msg->xconn = req->xconn;
554 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
555 if(msg->buf.data == NULL) {
556 DEBUG(0,("push_message: malloc fail (2)\n"));
557 TALLOC_FREE(msg);
558 return False;
561 msg->request_time = request_time;
562 msg->seqnum = req->seqnum;
563 msg->encrypted = req->encrypted;
564 msg->processed = false;
565 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
567 if (open_rec) {
568 msg->open_rec = talloc_move(msg, &open_rec);
571 #if 0
572 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
573 msg,
574 end_time,
575 smbd_deferred_open_timer,
576 msg);
577 if (!msg->te) {
578 DEBUG(0,("push_message: event_add_timed failed\n"));
579 TALLOC_FREE(msg);
580 return false;
582 #endif
584 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
586 DEBUG(10,("push_message: pushed message length %u on "
587 "deferred_open_queue\n", (unsigned int)msg_len));
589 return True;
592 /****************************************************************************
593 Function to push a deferred open smb message onto a linked list of local smb
594 messages ready for processing.
595 ****************************************************************************/
597 bool push_deferred_open_message_smb1(struct smb_request *req,
598 struct timeval timeout,
599 struct file_id id,
600 struct deferred_open_record *open_rec)
602 struct timeval_buf tvbuf;
603 struct timeval end_time;
605 if (req->unread_bytes) {
606 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
607 "unread_bytes = %u\n",
608 (unsigned int)req->unread_bytes ));
609 smb_panic("push_deferred_open_message_smb: "
610 "logic error unread_bytes != 0" );
613 end_time = timeval_sum(&req->request_time, &timeout);
615 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
616 (unsigned int) smb_len(req->inbuf)+4,
617 req->mid,
618 timeval_str_buf(&end_time, false, true, &tvbuf));
620 return push_queued_message(req, req->request_time, end_time, open_rec);
624 * Only allow 5 outstanding trans requests. We're allocating memory, so
625 * prevent a DoS.
628 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
630 int count = 0;
631 for (; list != NULL; list = list->next) {
633 if (list->mid == mid) {
634 return NT_STATUS_INVALID_PARAMETER;
637 count += 1;
639 if (count > 5) {
640 return NT_STATUS_INSUFFICIENT_RESOURCES;
643 return NT_STATUS_OK;
647 These flags determine some of the permissions required to do an operation
649 Note that I don't set NEED_WRITE on some write operations because they
650 are used by some brain-dead clients when printing, and I don't want to
651 force write permissions on print services.
653 #define AS_USER (1<<0)
654 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
655 #define TIME_INIT (1<<2)
656 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
657 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
658 #define DO_CHDIR (1<<6)
661 define a list of possible SMB messages and their corresponding
662 functions. Any message that has a NULL function is unimplemented -
663 please feel free to contribute implementations!
665 static const struct smb_message_struct {
666 const char *name;
667 void (*fn)(struct smb_request *req);
668 int flags;
669 } smb_messages[256] = {
671 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
672 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
673 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
674 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
675 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
676 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
677 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
678 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
679 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
680 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
681 /* 0x0a */ { "SMBread",reply_read,AS_USER},
682 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
683 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
684 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
685 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
686 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
687 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
688 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
689 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
690 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
691 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
692 /* 0x15 */ { NULL, NULL, 0 },
693 /* 0x16 */ { NULL, NULL, 0 },
694 /* 0x17 */ { NULL, NULL, 0 },
695 /* 0x18 */ { NULL, NULL, 0 },
696 /* 0x19 */ { NULL, NULL, 0 },
697 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
698 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
699 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
700 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
701 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
702 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
703 /* 0x20 */ { "SMBwritec", NULL,0},
704 /* 0x21 */ { NULL, NULL, 0 },
705 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
706 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
707 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
708 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
709 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
710 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
711 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
712 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
713 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
714 /* 0x2b */ { "SMBecho",reply_echo,0},
715 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
716 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
717 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
718 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
719 /* 0x30 */ { NULL, NULL, 0 },
720 /* 0x31 */ { NULL, NULL, 0 },
721 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
722 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
723 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
724 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
725 /* 0x36 */ { NULL, NULL, 0 },
726 /* 0x37 */ { NULL, NULL, 0 },
727 /* 0x38 */ { NULL, NULL, 0 },
728 /* 0x39 */ { NULL, NULL, 0 },
729 /* 0x3a */ { NULL, NULL, 0 },
730 /* 0x3b */ { NULL, NULL, 0 },
731 /* 0x3c */ { NULL, NULL, 0 },
732 /* 0x3d */ { NULL, NULL, 0 },
733 /* 0x3e */ { NULL, NULL, 0 },
734 /* 0x3f */ { NULL, NULL, 0 },
735 /* 0x40 */ { NULL, NULL, 0 },
736 /* 0x41 */ { NULL, NULL, 0 },
737 /* 0x42 */ { NULL, NULL, 0 },
738 /* 0x43 */ { NULL, NULL, 0 },
739 /* 0x44 */ { NULL, NULL, 0 },
740 /* 0x45 */ { NULL, NULL, 0 },
741 /* 0x46 */ { NULL, NULL, 0 },
742 /* 0x47 */ { NULL, NULL, 0 },
743 /* 0x48 */ { NULL, NULL, 0 },
744 /* 0x49 */ { NULL, NULL, 0 },
745 /* 0x4a */ { NULL, NULL, 0 },
746 /* 0x4b */ { NULL, NULL, 0 },
747 /* 0x4c */ { NULL, NULL, 0 },
748 /* 0x4d */ { NULL, NULL, 0 },
749 /* 0x4e */ { NULL, NULL, 0 },
750 /* 0x4f */ { NULL, NULL, 0 },
751 /* 0x50 */ { NULL, NULL, 0 },
752 /* 0x51 */ { NULL, NULL, 0 },
753 /* 0x52 */ { NULL, NULL, 0 },
754 /* 0x53 */ { NULL, NULL, 0 },
755 /* 0x54 */ { NULL, NULL, 0 },
756 /* 0x55 */ { NULL, NULL, 0 },
757 /* 0x56 */ { NULL, NULL, 0 },
758 /* 0x57 */ { NULL, NULL, 0 },
759 /* 0x58 */ { NULL, NULL, 0 },
760 /* 0x59 */ { NULL, NULL, 0 },
761 /* 0x5a */ { NULL, NULL, 0 },
762 /* 0x5b */ { NULL, NULL, 0 },
763 /* 0x5c */ { NULL, NULL, 0 },
764 /* 0x5d */ { NULL, NULL, 0 },
765 /* 0x5e */ { NULL, NULL, 0 },
766 /* 0x5f */ { NULL, NULL, 0 },
767 /* 0x60 */ { NULL, NULL, 0 },
768 /* 0x61 */ { NULL, NULL, 0 },
769 /* 0x62 */ { NULL, NULL, 0 },
770 /* 0x63 */ { NULL, NULL, 0 },
771 /* 0x64 */ { NULL, NULL, 0 },
772 /* 0x65 */ { NULL, NULL, 0 },
773 /* 0x66 */ { NULL, NULL, 0 },
774 /* 0x67 */ { NULL, NULL, 0 },
775 /* 0x68 */ { NULL, NULL, 0 },
776 /* 0x69 */ { NULL, NULL, 0 },
777 /* 0x6a */ { NULL, NULL, 0 },
778 /* 0x6b */ { NULL, NULL, 0 },
779 /* 0x6c */ { NULL, NULL, 0 },
780 /* 0x6d */ { NULL, NULL, 0 },
781 /* 0x6e */ { NULL, NULL, 0 },
782 /* 0x6f */ { NULL, NULL, 0 },
783 /* 0x70 */ { "SMBtcon",reply_tcon,0},
784 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
785 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
786 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
787 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
788 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
789 /* 0x76 */ { NULL, NULL, 0 },
790 /* 0x77 */ { NULL, NULL, 0 },
791 /* 0x78 */ { NULL, NULL, 0 },
792 /* 0x79 */ { NULL, NULL, 0 },
793 /* 0x7a */ { NULL, NULL, 0 },
794 /* 0x7b */ { NULL, NULL, 0 },
795 /* 0x7c */ { NULL, NULL, 0 },
796 /* 0x7d */ { NULL, NULL, 0 },
797 /* 0x7e */ { NULL, NULL, 0 },
798 /* 0x7f */ { NULL, NULL, 0 },
799 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
800 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
801 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
802 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
803 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
804 /* 0x85 */ { NULL, NULL, 0 },
805 /* 0x86 */ { NULL, NULL, 0 },
806 /* 0x87 */ { NULL, NULL, 0 },
807 /* 0x88 */ { NULL, NULL, 0 },
808 /* 0x89 */ { NULL, NULL, 0 },
809 /* 0x8a */ { NULL, NULL, 0 },
810 /* 0x8b */ { NULL, NULL, 0 },
811 /* 0x8c */ { NULL, NULL, 0 },
812 /* 0x8d */ { NULL, NULL, 0 },
813 /* 0x8e */ { NULL, NULL, 0 },
814 /* 0x8f */ { NULL, NULL, 0 },
815 /* 0x90 */ { NULL, NULL, 0 },
816 /* 0x91 */ { NULL, NULL, 0 },
817 /* 0x92 */ { NULL, NULL, 0 },
818 /* 0x93 */ { NULL, NULL, 0 },
819 /* 0x94 */ { NULL, NULL, 0 },
820 /* 0x95 */ { NULL, NULL, 0 },
821 /* 0x96 */ { NULL, NULL, 0 },
822 /* 0x97 */ { NULL, NULL, 0 },
823 /* 0x98 */ { NULL, NULL, 0 },
824 /* 0x99 */ { NULL, NULL, 0 },
825 /* 0x9a */ { NULL, NULL, 0 },
826 /* 0x9b */ { NULL, NULL, 0 },
827 /* 0x9c */ { NULL, NULL, 0 },
828 /* 0x9d */ { NULL, NULL, 0 },
829 /* 0x9e */ { NULL, NULL, 0 },
830 /* 0x9f */ { NULL, NULL, 0 },
831 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
832 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
833 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
834 /* 0xa3 */ { NULL, NULL, 0 },
835 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
836 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
837 /* 0xa6 */ { NULL, NULL, 0 },
838 /* 0xa7 */ { NULL, NULL, 0 },
839 /* 0xa8 */ { NULL, NULL, 0 },
840 /* 0xa9 */ { NULL, NULL, 0 },
841 /* 0xaa */ { NULL, NULL, 0 },
842 /* 0xab */ { NULL, NULL, 0 },
843 /* 0xac */ { NULL, NULL, 0 },
844 /* 0xad */ { NULL, NULL, 0 },
845 /* 0xae */ { NULL, NULL, 0 },
846 /* 0xaf */ { NULL, NULL, 0 },
847 /* 0xb0 */ { NULL, NULL, 0 },
848 /* 0xb1 */ { NULL, NULL, 0 },
849 /* 0xb2 */ { NULL, NULL, 0 },
850 /* 0xb3 */ { NULL, NULL, 0 },
851 /* 0xb4 */ { NULL, NULL, 0 },
852 /* 0xb5 */ { NULL, NULL, 0 },
853 /* 0xb6 */ { NULL, NULL, 0 },
854 /* 0xb7 */ { NULL, NULL, 0 },
855 /* 0xb8 */ { NULL, NULL, 0 },
856 /* 0xb9 */ { NULL, NULL, 0 },
857 /* 0xba */ { NULL, NULL, 0 },
858 /* 0xbb */ { NULL, NULL, 0 },
859 /* 0xbc */ { NULL, NULL, 0 },
860 /* 0xbd */ { NULL, NULL, 0 },
861 /* 0xbe */ { NULL, NULL, 0 },
862 /* 0xbf */ { NULL, NULL, 0 },
863 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
864 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
865 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
866 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
867 /* 0xc4 */ { NULL, NULL, 0 },
868 /* 0xc5 */ { NULL, NULL, 0 },
869 /* 0xc6 */ { NULL, NULL, 0 },
870 /* 0xc7 */ { NULL, NULL, 0 },
871 /* 0xc8 */ { NULL, NULL, 0 },
872 /* 0xc9 */ { NULL, NULL, 0 },
873 /* 0xca */ { NULL, NULL, 0 },
874 /* 0xcb */ { NULL, NULL, 0 },
875 /* 0xcc */ { NULL, NULL, 0 },
876 /* 0xcd */ { NULL, NULL, 0 },
877 /* 0xce */ { NULL, NULL, 0 },
878 /* 0xcf */ { NULL, NULL, 0 },
879 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
880 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
881 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
882 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
883 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
884 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
885 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
886 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
887 /* 0xd8 */ { NULL, NULL, 0 },
888 /* 0xd9 */ { NULL, NULL, 0 },
889 /* 0xda */ { NULL, NULL, 0 },
890 /* 0xdb */ { NULL, NULL, 0 },
891 /* 0xdc */ { NULL, NULL, 0 },
892 /* 0xdd */ { NULL, NULL, 0 },
893 /* 0xde */ { NULL, NULL, 0 },
894 /* 0xdf */ { NULL, NULL, 0 },
895 /* 0xe0 */ { NULL, NULL, 0 },
896 /* 0xe1 */ { NULL, NULL, 0 },
897 /* 0xe2 */ { NULL, NULL, 0 },
898 /* 0xe3 */ { NULL, NULL, 0 },
899 /* 0xe4 */ { NULL, NULL, 0 },
900 /* 0xe5 */ { NULL, NULL, 0 },
901 /* 0xe6 */ { NULL, NULL, 0 },
902 /* 0xe7 */ { NULL, NULL, 0 },
903 /* 0xe8 */ { NULL, NULL, 0 },
904 /* 0xe9 */ { NULL, NULL, 0 },
905 /* 0xea */ { NULL, NULL, 0 },
906 /* 0xeb */ { NULL, NULL, 0 },
907 /* 0xec */ { NULL, NULL, 0 },
908 /* 0xed */ { NULL, NULL, 0 },
909 /* 0xee */ { NULL, NULL, 0 },
910 /* 0xef */ { NULL, NULL, 0 },
911 /* 0xf0 */ { NULL, NULL, 0 },
912 /* 0xf1 */ { NULL, NULL, 0 },
913 /* 0xf2 */ { NULL, NULL, 0 },
914 /* 0xf3 */ { NULL, NULL, 0 },
915 /* 0xf4 */ { NULL, NULL, 0 },
916 /* 0xf5 */ { NULL, NULL, 0 },
917 /* 0xf6 */ { NULL, NULL, 0 },
918 /* 0xf7 */ { NULL, NULL, 0 },
919 /* 0xf8 */ { NULL, NULL, 0 },
920 /* 0xf9 */ { NULL, NULL, 0 },
921 /* 0xfa */ { NULL, NULL, 0 },
922 /* 0xfb */ { NULL, NULL, 0 },
923 /* 0xfc */ { NULL, NULL, 0 },
924 /* 0xfd */ { NULL, NULL, 0 },
925 /* 0xfe */ { NULL, NULL, 0 },
926 /* 0xff */ { NULL, NULL, 0 }
931 /*******************************************************************
932 Dump a packet to a file.
933 ********************************************************************/
935 static void smb_dump(const char *name, int type, const char *data)
937 size_t len;
938 int fd, i;
939 char *fname = NULL;
940 if (DEBUGLEVEL < 50) {
941 return;
944 len = smb_len_tcp(data)+4;
945 for (i=1;i<100;i++) {
946 fname = talloc_asprintf(talloc_tos(),
947 "/tmp/%s.%d.%s",
948 name,
950 type ? "req" : "resp");
951 if (fname == NULL) {
952 return;
954 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
955 if (fd != -1 || errno != EEXIST) break;
956 TALLOC_FREE(fname);
958 if (fd != -1) {
959 ssize_t ret = write(fd, data, len);
960 if (ret != len)
961 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
962 close(fd);
963 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
965 TALLOC_FREE(fname);
968 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
969 struct smb_request *req,
970 uint8_t type,
971 bool *update_session_globalp,
972 bool *update_tcon_globalp)
974 connection_struct *conn = req->conn;
975 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
976 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
977 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
978 bool update_session = false;
979 bool update_tcon = false;
981 if (req->encrypted) {
982 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
985 if (smb1_srv_is_signing_active(req->xconn)) {
986 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
987 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
989 * echo can be unsigned. Sesssion setup except final
990 * session setup response too
992 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
995 update_session |= smbXsrv_set_crypto_flag(
996 &session->global->encryption_flags, encrypt_flag);
997 update_session |= smbXsrv_set_crypto_flag(
998 &session->global->signing_flags, sign_flag);
1000 if (tcon) {
1001 update_tcon |= smbXsrv_set_crypto_flag(
1002 &tcon->global->encryption_flags, encrypt_flag);
1003 update_tcon |= smbXsrv_set_crypto_flag(
1004 &tcon->global->signing_flags, sign_flag);
1007 if (update_session) {
1008 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1011 *update_session_globalp = update_session;
1012 *update_tcon_globalp = update_tcon;
1013 return;
1016 /****************************************************************************
1017 Prepare everything for calling the actual request function, and potentially
1018 call the request function via the "new" interface.
1020 Return False if the "legacy" function needs to be called, everything is
1021 prepared.
1023 Return True if we're done.
1025 I know this API sucks, but it is the one with the least code change I could
1026 find.
1027 ****************************************************************************/
1029 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1031 const struct loadparm_substitution *lp_sub =
1032 loadparm_s3_global_substitution();
1033 int flags;
1034 uint64_t session_tag;
1035 connection_struct *conn = NULL;
1036 struct smbXsrv_connection *xconn = req->xconn;
1037 NTTIME now = timeval_to_nttime(&req->request_time);
1038 struct smbXsrv_session *session = NULL;
1039 NTSTATUS status;
1041 errno = 0;
1043 if (!xconn->smb1.negprot.done) {
1044 switch (type) {
1046 * Without a negprot the request must
1047 * either be a negprot, or one of the
1048 * evil old SMB mailslot messaging types.
1050 case SMBnegprot:
1051 case SMBsendstrt:
1052 case SMBsendend:
1053 case SMBsendtxt:
1054 break;
1055 default:
1056 exit_server_cleanly("The first request "
1057 "should be a negprot");
1061 if (smb_messages[type].fn == NULL) {
1062 DEBUG(0,("Unknown message type %d!\n",type));
1063 smb_dump("Unknown", 1, (const char *)req->inbuf);
1064 reply_unknown_new(req, type);
1065 return NULL;
1068 flags = smb_messages[type].flags;
1070 /* In share mode security we must ignore the vuid. */
1071 session_tag = req->vuid;
1072 conn = req->conn;
1074 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1075 (int)getpid(), (unsigned long)conn));
1077 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1079 /* Ensure this value is replaced in the incoming packet. */
1080 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1083 * Ensure the correct username is in current_user_info. This is a
1084 * really ugly bugfix for problems with multiple session_setup_and_X's
1085 * being done and allowing %U and %G substitutions to work correctly.
1086 * There is a reason this code is done here, don't move it unless you
1087 * know what you're doing... :-).
1088 * JRA.
1092 * lookup an existing session
1094 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1095 * here, the main check is still in change_to_user()
1097 status = smb1srv_session_lookup(xconn,
1098 session_tag,
1099 now,
1100 &session);
1101 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1102 switch (type) {
1103 case SMBsesssetupX:
1104 status = NT_STATUS_OK;
1105 break;
1106 default:
1107 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1108 (unsigned long long)session_tag,
1109 (unsigned long long)req->mid));
1110 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1111 return conn;
1115 if (session != NULL &&
1116 session->global->auth_session_info != NULL &&
1117 !(flags & AS_USER))
1120 * change_to_user() implies set_current_user_info()
1121 * and chdir_connect_service().
1123 * So we only call set_current_user_info if
1124 * we don't have AS_USER specified.
1126 set_current_user_info(
1127 session->global->auth_session_info->unix_info->sanitized_username,
1128 session->global->auth_session_info->unix_info->unix_name,
1129 session->global->auth_session_info->info->domain_name);
1132 /* Does this call need to be run as the connected user? */
1133 if (flags & AS_USER) {
1135 /* Does this call need a valid tree connection? */
1136 if (!conn) {
1138 * Amazingly, the error code depends on the command
1139 * (from Samba4).
1141 if (type == SMBntcreateX) {
1142 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1143 } else {
1144 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1146 return NULL;
1149 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1152 * change_to_user() implies set_current_user_info()
1153 * and chdir_connect_service().
1155 if (!change_to_user_and_service(conn,session_tag)) {
1156 DEBUG(0, ("Error: Could not change to user. Removing "
1157 "deferred open, mid=%llu.\n",
1158 (unsigned long long)req->mid));
1159 reply_force_doserror(req, ERRSRV, ERRbaduid);
1160 return conn;
1163 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1165 /* Does it need write permission? */
1166 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1167 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1168 return conn;
1171 /* IPC services are limited */
1172 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1173 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1174 return conn;
1176 } else if (flags & AS_GUEST) {
1178 * Does this protocol need to be run as guest? (Only archane
1179 * messenger service requests have this...)
1181 if (!change_to_guest()) {
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1183 return conn;
1185 } else {
1186 /* This call needs to be run as root */
1187 change_to_root_user();
1190 /* load service specific parameters */
1191 if (conn) {
1192 if (req->encrypted) {
1193 conn->encrypted_tid = true;
1194 /* encrypted required from now on. */
1195 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1196 } else if (ENCRYPTION_REQUIRED(conn)) {
1197 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1198 DEBUG(1,("service[%s] requires encryption"
1199 "%s ACCESS_DENIED. mid=%llu\n",
1200 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1201 smb_fn_name(type),
1202 (unsigned long long)req->mid));
1203 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1204 return conn;
1208 if (flags & DO_CHDIR) {
1209 bool ok;
1211 ok = chdir_current_service(conn);
1212 if (!ok) {
1213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1214 return conn;
1217 conn->num_smb_operations++;
1221 * Update encryption and signing state tracking flags that are
1222 * used by smbstatus to display signing and encryption status.
1224 if (session != NULL) {
1225 bool update_session_global = false;
1226 bool update_tcon_global = false;
1228 req->session = session;
1230 smb1srv_update_crypto_flags(session, req, type,
1231 &update_session_global,
1232 &update_tcon_global);
1234 if (update_session_global) {
1235 status = smbXsrv_session_update(session);
1236 if (!NT_STATUS_IS_OK(status)) {
1237 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1238 return conn;
1242 if (update_tcon_global) {
1243 status = smbXsrv_tcon_update(req->conn->tcon);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1246 return conn;
1251 smb_messages[type].fn(req);
1252 return req->conn;
1255 /****************************************************************************
1256 Construct a reply to the incoming packet.
1257 ****************************************************************************/
1259 void construct_reply(struct smbXsrv_connection *xconn,
1260 char *inbuf, int size, size_t unread_bytes,
1261 uint32_t seqnum, bool encrypted,
1262 struct smb_perfcount_data *deferred_pcd)
1264 struct smbd_server_connection *sconn = xconn->client->sconn;
1265 struct smb_request *req;
1267 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1268 smb_panic("could not allocate smb_request");
1271 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1272 encrypted, seqnum)) {
1273 exit_server_cleanly("Invalid SMB request");
1276 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1278 /* we popped this message off the queue - keep original perf data */
1279 if (deferred_pcd)
1280 req->pcd = *deferred_pcd;
1281 else {
1282 SMB_PERFCOUNT_START(&req->pcd);
1283 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1284 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1287 req->conn = switch_message(req->cmd, req);
1289 if (req->outbuf == NULL) {
1291 * Request has suspended itself, will come
1292 * back here.
1294 return;
1296 if (CVAL(req->outbuf,0) == 0) {
1297 show_msg((char *)req->outbuf);
1299 smb_request_done(req);
1302 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1303 char *inbuf, int size, uint32_t seqnum,
1304 bool encrypted,
1305 struct smb_perfcount_data *deferred_pcd)
1307 struct smb_request **reqs = NULL;
1308 struct smb_request *req;
1309 unsigned num_reqs;
1310 bool ok;
1312 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1313 seqnum, &reqs, &num_reqs);
1314 if (!ok) {
1315 char errbuf[smb_size];
1316 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1317 __LINE__, __FILE__);
1318 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted,
1319 NULL)) {
1320 exit_server_cleanly("construct_reply_chain: "
1321 "smb1_srv_send failed.");
1323 return;
1326 req = reqs[0];
1327 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1329 req->conn = switch_message(req->cmd, req);
1331 if (req->outbuf == NULL) {
1333 * Request has suspended itself, will come
1334 * back here.
1336 return;
1338 smb_request_done(req);
1342 * To be called from an async SMB handler that is potentially chained
1343 * when it is finished for shipping.
1346 void smb_request_done(struct smb_request *req)
1348 struct smb_request **reqs = NULL;
1349 struct smb_request *first_req;
1350 size_t i, num_reqs, next_index;
1351 NTSTATUS status;
1353 if (req->chain == NULL) {
1354 first_req = req;
1355 goto shipit;
1358 reqs = req->chain;
1359 num_reqs = talloc_array_length(reqs);
1361 for (i=0; i<num_reqs; i++) {
1362 if (reqs[i] == req) {
1363 break;
1366 if (i == num_reqs) {
1368 * Invalid chain, should not happen
1370 status = NT_STATUS_INTERNAL_ERROR;
1371 goto error;
1373 next_index = i+1;
1375 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1376 struct smb_request *next = reqs[next_index];
1377 struct smbXsrv_tcon *tcon;
1378 NTTIME now = timeval_to_nttime(&req->request_time);
1380 next->vuid = SVAL(req->outbuf, smb_uid);
1381 next->tid = SVAL(req->outbuf, smb_tid);
1382 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1383 now, &tcon);
1385 if (NT_STATUS_IS_OK(status)) {
1386 next->conn = tcon->compat;
1387 } else {
1388 next->conn = NULL;
1390 next->chain_fsp = req->chain_fsp;
1391 next->inbuf = req->inbuf;
1393 req = next;
1394 req->conn = switch_message(req->cmd, req);
1396 if (req->outbuf == NULL) {
1398 * Request has suspended itself, will come
1399 * back here.
1401 return;
1403 next_index += 1;
1406 first_req = reqs[0];
1408 for (i=1; i<next_index; i++) {
1409 bool ok;
1411 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1412 if (!ok) {
1413 status = NT_STATUS_INTERNAL_ERROR;
1414 goto error;
1418 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1419 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1422 * This scary statement intends to set the
1423 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1424 * to the value last_req->outbuf carries
1426 SSVAL(first_req->outbuf, smb_flg2,
1427 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1428 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1431 * Transfer the error codes from the subrequest to the main one
1433 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1434 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1436 _smb_setlen_large(
1437 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1439 shipit:
1440 if (!smb1_srv_send(first_req->xconn,
1441 (char *)first_req->outbuf,
1442 true, first_req->seqnum+1,
1443 IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
1444 &first_req->pcd)) {
1445 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1446 "failed.");
1448 TALLOC_FREE(req); /* non-chained case */
1449 TALLOC_FREE(reqs); /* chained case */
1450 return;
1452 error:
1454 char errbuf[smb_size];
1455 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1456 if (!smb1_srv_send(req->xconn, errbuf, true,
1457 req->seqnum+1, req->encrypted,
1458 NULL)) {
1459 exit_server_cleanly("construct_reply_chain: "
1460 "smb1_srv_send failed.");
1463 TALLOC_FREE(req); /* non-chained case */
1464 TALLOC_FREE(reqs); /* chained case */
1467 /****************************************************************************
1468 Process an smb from the client
1469 ****************************************************************************/
1471 void process_smb1(struct smbXsrv_connection *xconn,
1472 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1473 uint32_t seqnum, bool encrypted,
1474 struct smb_perfcount_data *deferred_pcd)
1476 struct smbd_server_connection *sconn = xconn->client->sconn;
1478 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1479 * so subtract 4 from it. */
1480 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1481 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1482 smb_len(inbuf)));
1484 /* special magic for immediate exit */
1485 if ((nread == 9) &&
1486 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1487 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1488 uint8_t exitcode = CVAL(inbuf, 8);
1489 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1490 (int)exitcode);
1491 exit(exitcode);
1494 exit_server_cleanly("Non-SMB packet");
1497 show_msg((char *)inbuf);
1499 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1500 construct_reply_chain(xconn, (char *)inbuf, nread,
1501 seqnum, encrypted, deferred_pcd);
1502 } else {
1503 construct_reply(xconn, (char *)inbuf, nread, unread_bytes,
1504 seqnum, encrypted, deferred_pcd);
1507 sconn->trans_num++;
1510 /****************************************************************************
1511 Return a string containing the function name of a SMB command.
1512 ****************************************************************************/
1514 const char *smb_fn_name(int type)
1516 const char *unknown_name = "SMBunknown";
1518 if (smb_messages[type].name == NULL)
1519 return(unknown_name);
1521 return(smb_messages[type].name);
1524 /****************************************************************************
1525 Helper functions for contruct_reply.
1526 ****************************************************************************/
1528 void add_to_common_flags2(uint32_t v)
1530 common_flags2 |= v;
1533 void remove_from_common_flags2(uint32_t v)
1535 common_flags2 &= ~v;
1539 * @brief Find the smb_cmd offset of the last command pushed
1540 * @param[in] buf The buffer we're building up
1541 * @retval Where can we put our next andx cmd?
1543 * While chaining requests, the "next" request we're looking at needs to put
1544 * its SMB_Command before the data the previous request already built up added
1545 * to the chain. Find the offset to the place where we have to put our cmd.
1548 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1550 uint8_t cmd;
1551 size_t ofs;
1553 cmd = CVAL(buf, smb_com);
1555 if (!smb1cli_is_andx_req(cmd)) {
1556 return false;
1559 ofs = smb_vwv0;
1561 while (CVAL(buf, ofs) != 0xff) {
1563 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1564 return false;
1568 * ofs is from start of smb header, so add the 4 length
1569 * bytes. The next cmd is right after the wct field.
1571 ofs = SVAL(buf, ofs+2) + 4 + 1;
1573 if (ofs+4 >= talloc_get_size(buf)) {
1574 return false;
1578 *pofs = ofs;
1579 return true;
1583 * @brief Do the smb chaining at a buffer level
1584 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1585 * @param[in] andx_buf Buffer to be appended
1588 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1590 uint8_t smb_command = CVAL(andx_buf, smb_com);
1591 uint8_t wct = CVAL(andx_buf, smb_wct);
1592 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1593 uint32_t num_bytes = smb_buflen(andx_buf);
1594 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1596 uint8_t *outbuf;
1597 size_t old_size, new_size;
1598 size_t ofs;
1599 size_t chain_padding = 0;
1600 size_t andx_cmd_ofs;
1603 old_size = talloc_get_size(*poutbuf);
1605 if ((old_size % 4) != 0) {
1607 * Align the wct field of subsequent requests to a 4-byte
1608 * boundary
1610 chain_padding = 4 - (old_size % 4);
1614 * After the old request comes the new wct field (1 byte), the vwv's
1615 * and the num_bytes field.
1618 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1619 new_size += num_bytes;
1621 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1622 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1623 (unsigned)new_size));
1624 return false;
1627 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1628 if (outbuf == NULL) {
1629 DEBUG(0, ("talloc failed\n"));
1630 return false;
1632 *poutbuf = outbuf;
1634 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1635 DEBUG(1, ("invalid command chain\n"));
1636 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1637 return false;
1640 if (chain_padding != 0) {
1641 memset(outbuf + old_size, 0, chain_padding);
1642 old_size += chain_padding;
1645 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1646 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1648 ofs = old_size;
1651 * Push the chained request:
1653 * wct field
1656 SCVAL(outbuf, ofs, wct);
1657 ofs += 1;
1660 * vwv array
1663 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1666 * HACK ALERT
1668 * Read&X has an offset into its data buffer at
1669 * vwv[6]. reply_read_andx has no idea anymore that it's
1670 * running from within a chain, so we have to fix up the
1671 * offset here.
1673 * Although it looks disgusting at this place, I want to keep
1674 * it here. The alternative would be to push knowledge about
1675 * the andx chain down into read&x again.
1678 if (smb_command == SMBreadX) {
1679 uint8_t *bytes_addr;
1681 if (wct < 7) {
1683 * Invalid read&x response
1685 return false;
1688 bytes_addr = outbuf + ofs /* vwv start */
1689 + sizeof(uint16_t) * wct /* vwv array */
1690 + sizeof(uint16_t) /* bcc */
1691 + 1; /* padding byte */
1693 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1694 bytes_addr - outbuf - 4);
1697 ofs += sizeof(uint16_t) * wct;
1700 * bcc (byte count)
1703 SSVAL(outbuf, ofs, num_bytes);
1704 ofs += sizeof(uint16_t);
1707 * The bytes field
1710 memcpy(outbuf + ofs, bytes, num_bytes);
1712 return true;
1715 bool smb1_is_chain(const uint8_t *buf)
1717 uint8_t cmd, wct, andx_cmd;
1719 cmd = CVAL(buf, smb_com);
1720 if (!smb1cli_is_andx_req(cmd)) {
1721 return false;
1723 wct = CVAL(buf, smb_wct);
1724 if (wct < 2) {
1725 return false;
1727 andx_cmd = CVAL(buf, smb_vwv);
1728 return (andx_cmd != 0xFF);
1731 bool smb1_walk_chain(const uint8_t *buf,
1732 bool (*fn)(uint8_t cmd,
1733 uint8_t wct, const uint16_t *vwv,
1734 uint16_t num_bytes, const uint8_t *bytes,
1735 void *private_data),
1736 void *private_data)
1738 size_t smblen = smb_len(buf);
1739 const char *smb_buf = smb_base(buf);
1740 uint8_t cmd, chain_cmd;
1741 uint8_t wct;
1742 const uint16_t *vwv;
1743 uint16_t num_bytes;
1744 const uint8_t *bytes;
1746 cmd = CVAL(buf, smb_com);
1747 wct = CVAL(buf, smb_wct);
1748 vwv = (const uint16_t *)(buf + smb_vwv);
1749 num_bytes = smb_buflen(buf);
1750 bytes = (const uint8_t *)smb_buf_const(buf);
1752 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1753 return false;
1756 if (!smb1cli_is_andx_req(cmd)) {
1757 return true;
1759 if (wct < 2) {
1760 return false;
1763 chain_cmd = CVAL(vwv, 0);
1765 while (chain_cmd != 0xff) {
1766 uint32_t chain_offset; /* uint32_t to avoid overflow */
1767 size_t length_needed;
1768 ptrdiff_t vwv_offset;
1770 chain_offset = SVAL(vwv+1, 0);
1773 * Check if the client tries to fool us. The chain
1774 * offset needs to point beyond the current request in
1775 * the chain, it needs to strictly grow. Otherwise we
1776 * might be tricked into an endless loop always
1777 * processing the same request over and over again. We
1778 * used to assume that vwv and the byte buffer array
1779 * in a chain are always attached, but OS/2 the
1780 * Write&X/Read&X chain puts the Read&X vwv array
1781 * right behind the Write&X vwv chain. The Write&X bcc
1782 * array is put behind the Read&X vwv array. So now we
1783 * check whether the chain offset points strictly
1784 * behind the previous vwv array. req->buf points
1785 * right after the vwv array of the previous
1786 * request. See
1787 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1788 * more information.
1791 vwv_offset = ((const char *)vwv - smb_buf);
1792 if (chain_offset <= vwv_offset) {
1793 return false;
1797 * Next check: Make sure the chain offset does not
1798 * point beyond the overall smb request length.
1801 length_needed = chain_offset+1; /* wct */
1802 if (length_needed > smblen) {
1803 return false;
1807 * Now comes the pointer magic. Goal here is to set up
1808 * vwv and buf correctly again. The chain offset (the
1809 * former vwv[1]) points at the new wct field.
1812 wct = CVAL(smb_buf, chain_offset);
1814 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1815 return false;
1819 * Next consistency check: Make the new vwv array fits
1820 * in the overall smb request.
1823 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1824 if (length_needed > smblen) {
1825 return false;
1827 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1830 * Now grab the new byte buffer....
1833 num_bytes = SVAL(vwv+wct, 0);
1836 * .. and check that it fits.
1839 length_needed += num_bytes;
1840 if (length_needed > smblen) {
1841 return false;
1843 bytes = (const uint8_t *)(vwv+wct+1);
1845 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1846 return false;
1849 if (!smb1cli_is_andx_req(chain_cmd)) {
1850 return true;
1852 chain_cmd = CVAL(vwv, 0);
1854 return true;
1857 static bool smb1_chain_length_cb(uint8_t cmd,
1858 uint8_t wct, const uint16_t *vwv,
1859 uint16_t num_bytes, const uint8_t *bytes,
1860 void *private_data)
1862 unsigned *count = (unsigned *)private_data;
1863 *count += 1;
1864 return true;
1867 unsigned smb1_chain_length(const uint8_t *buf)
1869 unsigned count = 0;
1871 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1872 return 0;
1874 return count;
1877 struct smb1_parse_chain_state {
1878 TALLOC_CTX *mem_ctx;
1879 const uint8_t *buf;
1880 struct smbd_server_connection *sconn;
1881 struct smbXsrv_connection *xconn;
1882 bool encrypted;
1883 uint32_t seqnum;
1885 struct smb_request **reqs;
1886 unsigned num_reqs;
1889 static bool smb1_parse_chain_cb(uint8_t cmd,
1890 uint8_t wct, const uint16_t *vwv,
1891 uint16_t num_bytes, const uint8_t *bytes,
1892 void *private_data)
1894 struct smb1_parse_chain_state *state =
1895 (struct smb1_parse_chain_state *)private_data;
1896 struct smb_request **reqs;
1897 struct smb_request *req;
1898 bool ok;
1900 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1901 struct smb_request *, state->num_reqs+1);
1902 if (reqs == NULL) {
1903 return false;
1905 state->reqs = reqs;
1907 req = talloc(reqs, struct smb_request);
1908 if (req == NULL) {
1909 return false;
1912 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1913 state->encrypted, state->seqnum);
1914 if (!ok) {
1915 return false;
1917 req->cmd = cmd;
1918 req->wct = wct;
1919 req->vwv = vwv;
1920 req->buflen = num_bytes;
1921 req->buf = bytes;
1923 reqs[state->num_reqs] = req;
1924 state->num_reqs += 1;
1925 return true;
1928 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1929 struct smbXsrv_connection *xconn,
1930 bool encrypted, uint32_t seqnum,
1931 struct smb_request ***reqs, unsigned *num_reqs)
1933 struct smbd_server_connection *sconn = NULL;
1934 struct smb1_parse_chain_state state;
1935 unsigned i;
1937 if (xconn != NULL) {
1938 sconn = xconn->client->sconn;
1941 state.mem_ctx = mem_ctx;
1942 state.buf = buf;
1943 state.sconn = sconn;
1944 state.xconn = xconn;
1945 state.encrypted = encrypted;
1946 state.seqnum = seqnum;
1947 state.reqs = NULL;
1948 state.num_reqs = 0;
1950 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1951 TALLOC_FREE(state.reqs);
1952 return false;
1954 for (i=0; i<state.num_reqs; i++) {
1955 state.reqs[i]->chain = state.reqs;
1957 *reqs = state.reqs;
1958 *num_reqs = state.num_reqs;
1959 return true;
1962 static bool fd_is_readable(int fd)
1964 int ret, revents;
1966 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
1968 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
1972 static void smbd_server_connection_write_handler(
1973 struct smbXsrv_connection *xconn)
1975 /* TODO: make write nonblocking */
1978 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
1979 int fd)
1981 uint8_t *inbuf = NULL;
1982 size_t inbuf_len = 0;
1983 size_t unread_bytes = 0;
1984 bool encrypted = false;
1985 TALLOC_CTX *mem_ctx = talloc_tos();
1986 NTSTATUS status;
1987 uint32_t seqnum;
1989 bool async_echo = lp_async_smb_echo_handler();
1990 bool from_client = false;
1992 if (async_echo) {
1993 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
1995 * This is the super-ugly hack to prefer the packets
1996 * forwarded by the echo handler over the ones by the
1997 * client directly
1999 fd = xconn->smb1.echo_handler.trusted_fd;
2003 from_client = (xconn->transport.sock == fd);
2005 if (async_echo && from_client) {
2006 smbd_lock_socket(xconn);
2008 if (!fd_is_readable(fd)) {
2009 DEBUG(10,("the echo listener was faster\n"));
2010 smbd_unlock_socket(xconn);
2011 return;
2015 /* TODO: make this completely nonblocking */
2016 status = receive_smb_talloc(mem_ctx, xconn, fd,
2017 (char **)(void *)&inbuf,
2018 0, /* timeout */
2019 &unread_bytes,
2020 &encrypted,
2021 &inbuf_len, &seqnum,
2022 !from_client /* trusted channel */);
2024 if (async_echo && from_client) {
2025 smbd_unlock_socket(xconn);
2028 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2029 goto process;
2031 if (NT_STATUS_IS_ERR(status)) {
2032 exit_server_cleanly("failed to receive smb request");
2034 if (!NT_STATUS_IS_OK(status)) {
2035 return;
2038 process:
2039 process_smb(xconn, inbuf, inbuf_len, unread_bytes,
2040 seqnum, encrypted, NULL);
2043 static void smbd_server_echo_handler(struct tevent_context *ev,
2044 struct tevent_fd *fde,
2045 uint16_t flags,
2046 void *private_data)
2048 struct smbXsrv_connection *xconn =
2049 talloc_get_type_abort(private_data,
2050 struct smbXsrv_connection);
2052 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2054 * we're not supposed to do any io
2056 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2057 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2058 return;
2061 if (flags & TEVENT_FD_WRITE) {
2062 smbd_server_connection_write_handler(xconn);
2063 return;
2065 if (flags & TEVENT_FD_READ) {
2066 smbd_smb1_server_connection_read_handler(
2067 xconn, xconn->smb1.echo_handler.trusted_fd);
2068 return;
2073 * Send keepalive packets to our client
2075 bool keepalive_fn(const struct timeval *now, void *private_data)
2077 struct smbd_server_connection *sconn = talloc_get_type_abort(
2078 private_data, struct smbd_server_connection);
2079 struct smbXsrv_connection *xconn = NULL;
2080 bool ret;
2082 if (sconn->using_smb2) {
2083 /* Don't do keepalives on an SMB2 connection. */
2084 return false;
2088 * With SMB1 we only have 1 connection
2090 xconn = sconn->client->connections;
2091 smbd_lock_socket(xconn);
2092 ret = send_keepalive(xconn->transport.sock);
2093 smbd_unlock_socket(xconn);
2095 if (!ret) {
2096 int saved_errno = errno;
2098 * Try and give an error message saying what
2099 * client failed.
2101 DEBUG(0, ("send_keepalive failed for client %s. "
2102 "Error %s - exiting\n",
2103 smbXsrv_connection_dbg(xconn),
2104 strerror(saved_errno)));
2105 errno = saved_errno;
2106 return False;
2108 return True;
2112 * Read an smb packet in the echo handler child, giving the parent
2113 * smbd one second to react once the socket becomes readable.
2116 struct smbd_echo_read_state {
2117 struct tevent_context *ev;
2118 struct smbXsrv_connection *xconn;
2120 char *buf;
2121 size_t buflen;
2122 uint32_t seqnum;
2125 static void smbd_echo_read_readable(struct tevent_req *subreq);
2126 static void smbd_echo_read_waited(struct tevent_req *subreq);
2128 static struct tevent_req *smbd_echo_read_send(
2129 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2130 struct smbXsrv_connection *xconn)
2132 struct tevent_req *req, *subreq;
2133 struct smbd_echo_read_state *state;
2135 req = tevent_req_create(mem_ctx, &state,
2136 struct smbd_echo_read_state);
2137 if (req == NULL) {
2138 return NULL;
2140 state->ev = ev;
2141 state->xconn = xconn;
2143 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2144 if (tevent_req_nomem(subreq, req)) {
2145 return tevent_req_post(req, ev);
2147 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2148 return req;
2151 static void smbd_echo_read_readable(struct tevent_req *subreq)
2153 struct tevent_req *req = tevent_req_callback_data(
2154 subreq, struct tevent_req);
2155 struct smbd_echo_read_state *state = tevent_req_data(
2156 req, struct smbd_echo_read_state);
2157 bool ok;
2158 int err;
2160 ok = wait_for_read_recv(subreq, &err);
2161 TALLOC_FREE(subreq);
2162 if (!ok) {
2163 tevent_req_nterror(req, map_nt_error_from_unix(err));
2164 return;
2168 * Give the parent smbd one second to step in
2171 subreq = tevent_wakeup_send(
2172 state, state->ev, timeval_current_ofs(1, 0));
2173 if (tevent_req_nomem(subreq, req)) {
2174 return;
2176 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2179 static void smbd_echo_read_waited(struct tevent_req *subreq)
2181 struct tevent_req *req = tevent_req_callback_data(
2182 subreq, struct tevent_req);
2183 struct smbd_echo_read_state *state = tevent_req_data(
2184 req, struct smbd_echo_read_state);
2185 struct smbXsrv_connection *xconn = state->xconn;
2186 bool ok;
2187 NTSTATUS status;
2188 size_t unread = 0;
2189 bool encrypted;
2191 ok = tevent_wakeup_recv(subreq);
2192 TALLOC_FREE(subreq);
2193 if (!ok) {
2194 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2195 return;
2198 ok = smbd_lock_socket_internal(xconn);
2199 if (!ok) {
2200 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2201 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2202 return;
2205 if (!fd_is_readable(xconn->transport.sock)) {
2206 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2207 (int)getpid()));
2209 ok = smbd_unlock_socket_internal(xconn);
2210 if (!ok) {
2211 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2212 DEBUG(1, ("%s: failed to unlock socket\n",
2213 __location__));
2214 return;
2217 subreq = wait_for_read_send(state, state->ev,
2218 xconn->transport.sock, false);
2219 if (tevent_req_nomem(subreq, req)) {
2220 return;
2222 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2223 return;
2226 status = receive_smb_talloc(state, xconn,
2227 xconn->transport.sock,
2228 &state->buf,
2229 0 /* timeout */,
2230 &unread,
2231 &encrypted,
2232 &state->buflen,
2233 &state->seqnum,
2234 false /* trusted_channel*/);
2236 if (tevent_req_nterror(req, status)) {
2237 tevent_req_nterror(req, status);
2238 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2239 (int)getpid(), nt_errstr(status)));
2240 return;
2243 ok = smbd_unlock_socket_internal(xconn);
2244 if (!ok) {
2245 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2246 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2247 return;
2249 tevent_req_done(req);
2252 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2253 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2255 struct smbd_echo_read_state *state = tevent_req_data(
2256 req, struct smbd_echo_read_state);
2257 NTSTATUS status;
2259 if (tevent_req_is_nterror(req, &status)) {
2260 return status;
2262 *pbuf = talloc_move(mem_ctx, &state->buf);
2263 *pbuflen = state->buflen;
2264 *pseqnum = state->seqnum;
2265 return NT_STATUS_OK;
2268 struct smbd_echo_state {
2269 struct tevent_context *ev;
2270 struct iovec *pending;
2271 struct smbd_server_connection *sconn;
2272 struct smbXsrv_connection *xconn;
2273 int parent_pipe;
2275 struct tevent_fd *parent_fde;
2277 struct tevent_req *write_req;
2280 static void smbd_echo_writer_done(struct tevent_req *req);
2282 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2284 int num_pending;
2286 if (state->write_req != NULL) {
2287 return;
2290 num_pending = talloc_array_length(state->pending);
2291 if (num_pending == 0) {
2292 return;
2295 state->write_req = writev_send(state, state->ev, NULL,
2296 state->parent_pipe, false,
2297 state->pending, num_pending);
2298 if (state->write_req == NULL) {
2299 DEBUG(1, ("writev_send failed\n"));
2300 exit(1);
2303 talloc_steal(state->write_req, state->pending);
2304 state->pending = NULL;
2306 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2307 state);
2310 static void smbd_echo_writer_done(struct tevent_req *req)
2312 struct smbd_echo_state *state = tevent_req_callback_data(
2313 req, struct smbd_echo_state);
2314 ssize_t written;
2315 int err;
2317 written = writev_recv(req, &err);
2318 TALLOC_FREE(req);
2319 state->write_req = NULL;
2320 if (written == -1) {
2321 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2322 exit(1);
2324 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2325 smbd_echo_activate_writer(state);
2328 static bool smbd_echo_reply(struct smbd_echo_state *state,
2329 uint8_t *inbuf, size_t inbuf_len,
2330 uint32_t seqnum)
2332 struct smb_request req;
2333 uint16_t num_replies;
2334 char *outbuf;
2335 bool ok;
2337 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2338 DEBUG(10, ("Got netbios keepalive\n"));
2340 * Just swallow it
2342 return true;
2345 if (inbuf_len < smb_size) {
2346 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2347 return false;
2349 if (!valid_smb1_header(inbuf)) {
2350 DEBUG(10, ("Got invalid SMB header\n"));
2351 return false;
2354 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2355 seqnum)) {
2356 return false;
2358 req.inbuf = inbuf;
2360 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2361 smb_messages[req.cmd].name
2362 ? smb_messages[req.cmd].name : "unknown"));
2364 if (req.cmd != SMBecho) {
2365 return false;
2367 if (req.wct < 1) {
2368 return false;
2371 num_replies = SVAL(req.vwv+0, 0);
2372 if (num_replies != 1) {
2373 /* Not a Windows "Hey, you're still there?" request */
2374 return false;
2377 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2378 1, req.buflen)) {
2379 DEBUG(10, ("create_smb1_outbuf failed\n"));
2380 return false;
2382 req.outbuf = (uint8_t *)outbuf;
2384 SSVAL(req.outbuf, smb_vwv0, num_replies);
2386 if (req.buflen > 0) {
2387 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2390 ok = smb1_srv_send(req.xconn,
2391 (char *)outbuf,
2392 true, seqnum+1,
2393 false, &req.pcd);
2394 TALLOC_FREE(outbuf);
2395 if (!ok) {
2396 exit(1);
2399 return true;
2402 static void smbd_echo_exit(struct tevent_context *ev,
2403 struct tevent_fd *fde, uint16_t flags,
2404 void *private_data)
2406 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2407 exit(0);
2410 static void smbd_echo_got_packet(struct tevent_req *req);
2412 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2413 int parent_pipe)
2415 struct smbd_echo_state *state;
2416 struct tevent_req *read_req;
2418 state = talloc_zero(xconn, struct smbd_echo_state);
2419 if (state == NULL) {
2420 DEBUG(1, ("talloc failed\n"));
2421 return;
2423 state->xconn = xconn;
2424 state->parent_pipe = parent_pipe;
2425 state->ev = samba_tevent_context_init(state);
2426 if (state->ev == NULL) {
2427 DEBUG(1, ("samba_tevent_context_init failed\n"));
2428 TALLOC_FREE(state);
2429 return;
2431 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2432 TEVENT_FD_READ, smbd_echo_exit,
2433 state);
2434 if (state->parent_fde == NULL) {
2435 DEBUG(1, ("tevent_add_fd failed\n"));
2436 TALLOC_FREE(state);
2437 return;
2440 read_req = smbd_echo_read_send(state, state->ev, xconn);
2441 if (read_req == NULL) {
2442 DEBUG(1, ("smbd_echo_read_send failed\n"));
2443 TALLOC_FREE(state);
2444 return;
2446 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2448 while (true) {
2449 if (tevent_loop_once(state->ev) == -1) {
2450 DEBUG(1, ("tevent_loop_once failed: %s\n",
2451 strerror(errno)));
2452 break;
2455 TALLOC_FREE(state);
2458 static void smbd_echo_got_packet(struct tevent_req *req)
2460 struct smbd_echo_state *state = tevent_req_callback_data(
2461 req, struct smbd_echo_state);
2462 NTSTATUS status;
2463 char *buf = NULL;
2464 size_t buflen = 0;
2465 uint32_t seqnum = 0;
2466 bool reply;
2468 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2469 TALLOC_FREE(req);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2472 nt_errstr(status)));
2473 exit(1);
2476 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2477 if (!reply) {
2478 size_t num_pending;
2479 struct iovec *tmp;
2480 struct iovec *iov;
2482 num_pending = talloc_array_length(state->pending);
2483 tmp = talloc_realloc(state, state->pending, struct iovec,
2484 num_pending+1);
2485 if (tmp == NULL) {
2486 DEBUG(1, ("talloc_realloc failed\n"));
2487 exit(1);
2489 state->pending = tmp;
2491 if (buflen >= smb_size) {
2493 * place the seqnum in the packet so that the main process
2494 * can reply with signing
2496 SIVAL(buf, smb_ss_field, seqnum);
2497 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2500 iov = &state->pending[num_pending];
2501 iov->iov_base = talloc_move(state->pending, &buf);
2502 iov->iov_len = buflen;
2504 DEBUG(10,("echo_handler[%d]: forward to main\n",
2505 (int)getpid()));
2506 smbd_echo_activate_writer(state);
2509 req = smbd_echo_read_send(state, state->ev, state->xconn);
2510 if (req == NULL) {
2511 DEBUG(1, ("smbd_echo_read_send failed\n"));
2512 exit(1);
2514 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2519 * Handle SMBecho requests in a forked child process
2521 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2523 int listener_pipe[2];
2524 int res;
2525 pid_t child;
2526 bool use_mutex = false;
2528 res = pipe(listener_pipe);
2529 if (res == -1) {
2530 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2531 return false;
2534 #ifdef HAVE_ROBUST_MUTEXES
2535 use_mutex = tdb_runtime_check_for_robust_mutexes();
2537 if (use_mutex) {
2538 pthread_mutexattr_t a;
2540 xconn->smb1.echo_handler.socket_mutex =
2541 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2542 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2543 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2544 strerror(errno)));
2545 goto fail;
2548 res = pthread_mutexattr_init(&a);
2549 if (res != 0) {
2550 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2551 strerror(res)));
2552 goto fail;
2554 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2555 if (res != 0) {
2556 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2557 strerror(res)));
2558 pthread_mutexattr_destroy(&a);
2559 goto fail;
2561 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2562 if (res != 0) {
2563 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2564 strerror(res)));
2565 pthread_mutexattr_destroy(&a);
2566 goto fail;
2568 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2569 if (res != 0) {
2570 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2571 "%s\n", strerror(res)));
2572 pthread_mutexattr_destroy(&a);
2573 goto fail;
2575 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2576 &a);
2577 pthread_mutexattr_destroy(&a);
2578 if (res != 0) {
2579 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2580 strerror(res)));
2581 goto fail;
2584 #endif
2586 if (!use_mutex) {
2587 xconn->smb1.echo_handler.socket_lock_fd =
2588 create_unlink_tmp(lp_lock_directory());
2589 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2590 DEBUG(1, ("Could not create lock fd: %s\n",
2591 strerror(errno)));
2592 goto fail;
2596 child = fork();
2597 if (child == 0) {
2598 NTSTATUS status;
2600 close(listener_pipe[0]);
2601 set_blocking(listener_pipe[1], false);
2603 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2604 xconn->client->raw_ev_ctx,
2605 true,
2606 "smbd-echo");
2607 if (!NT_STATUS_IS_OK(status)) {
2608 DEBUG(1, ("reinit_after_fork failed: %s\n",
2609 nt_errstr(status)));
2610 exit(1);
2612 initialize_password_db(true, xconn->client->raw_ev_ctx);
2613 smbd_echo_loop(xconn, listener_pipe[1]);
2614 exit(0);
2616 close(listener_pipe[1]);
2617 listener_pipe[1] = -1;
2618 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2620 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2623 * Without smb signing this is the same as the normal smbd
2624 * listener. This needs to change once signing comes in.
2626 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2627 xconn->client->raw_ev_ctx,
2628 xconn,
2629 xconn->smb1.echo_handler.trusted_fd,
2630 TEVENT_FD_READ,
2631 smbd_server_echo_handler,
2632 xconn);
2633 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2634 DEBUG(1, ("event_add_fd failed\n"));
2635 goto fail;
2638 return true;
2640 fail:
2641 if (listener_pipe[0] != -1) {
2642 close(listener_pipe[0]);
2644 if (listener_pipe[1] != -1) {
2645 close(listener_pipe[1]);
2647 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2648 close(xconn->smb1.echo_handler.socket_lock_fd);
2650 #ifdef HAVE_ROBUST_MUTEXES
2651 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2652 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2653 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2655 #endif
2656 smbd_echo_init(xconn);
2658 return false;
2661 bool req_is_in_chain(const struct smb_request *req)
2663 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2665 * We're right now handling a subsequent request, so we must
2666 * be in a chain
2668 return true;
2671 if (!smb1cli_is_andx_req(req->cmd)) {
2672 return false;
2675 if (req->wct < 2) {
2677 * Okay, an illegal request, but definitely not chained :-)
2679 return false;
2682 return (CVAL(req->vwv+0, 0) != 0xFF);