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