s4:auth: Set ‘authoritative’ even if there is an error
[Samba.git] / source3 / smbd / smb1_process.c
bloba25ae9d2767cadd747482e61a933ea3776e8cb39
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "../lib/tsocket/tsocket.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "smbd/smbXsrv_open.h"
27 #include "librpc/gen_ndr/netlogon.h"
28 #include "../lib/async_req/async_sock.h"
29 #include "ctdbd_conn.h"
30 #include "../lib/util/select.h"
31 #include "printing/queue_process.h"
32 #include "system/select.h"
33 #include "passdb.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "lib/messages_ctdb.h"
37 #include "smbprofile.h"
38 #include "rpc_server/spoolss/srv_spoolss_nt.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "../libcli/security/dom_sid.h"
41 #include "../libcli/security/security_token.h"
42 #include "lib/id_cache.h"
43 #include "lib/util/sys_rw_data.h"
44 #include "system/threads.h"
45 #include "lib/pthreadpool/pthreadpool_tevent.h"
46 #include "util_event.h"
47 #include "libcli/smb/smbXcli_base.h"
48 #include "lib/util/time_basic.h"
49 #include "source3/lib/substitute.h"
50 #include "lib/util/util_process.h"
52 /* Internal message queue for deferred opens. */
53 struct pending_message_list {
54 struct pending_message_list *next, *prev;
55 struct timeval request_time; /* When was this first issued? */
56 struct smbd_server_connection *sconn;
57 struct smbXsrv_connection *xconn;
58 struct tevent_timer *te;
59 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,
211 char *buffer,
212 bool do_signing,
213 uint32_t seqnum,
214 bool do_encrypt)
216 size_t len = 0;
217 ssize_t ret;
218 char *buf_out = buffer;
220 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
222 * we're not supposed to do any io
224 return true;
227 smbd_lock_socket(xconn);
229 if (do_signing) {
230 NTSTATUS status;
232 /* Sign the outgoing packet if required. */
233 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
234 if (!NT_STATUS_IS_OK(status)) {
235 DBG_ERR("Failed to calculate signing mac: %s\n",
236 nt_errstr(status));
237 return false;
241 if (do_encrypt) {
242 char *enc = NULL;
243 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &enc);
244 if (!NT_STATUS_IS_OK(status)) {
245 DEBUG(0, ("send_smb: SMB encryption failed "
246 "on outgoing packet! Error %s\n",
247 nt_errstr(status) ));
248 SAFE_FREE(enc);
249 ret = -1;
250 goto out;
252 buf_out = enc;
255 len = smb_len_large(buf_out) + 4;
257 ret = write_data(xconn->transport.sock, buf_out, len);
258 if (ret <= 0) {
259 int saved_errno = errno;
261 * Try and give an error message saying what
262 * client failed.
264 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
265 (int)getpid(), (int)len,
266 smbXsrv_connection_dbg(xconn),
267 (int)ret, strerror(saved_errno)));
268 errno = saved_errno;
270 srv_free_enc_buffer(xconn, buf_out);
271 goto out;
274 srv_free_enc_buffer(xconn, buf_out);
275 out:
276 smbd_unlock_socket(xconn);
277 return (ret > 0);
280 /* Socket functions for smbd packet processing. */
282 static bool valid_packet_size(size_t len)
285 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
286 * of header. Don't print the error if this fits.... JRA.
289 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
290 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
291 (unsigned long)len));
292 return false;
294 return true;
297 /****************************************************************************
298 Attempt a zerocopy writeX read. We know here that len > smb_size-4
299 ****************************************************************************/
302 * Unfortunately, earlier versions of smbclient/libsmbclient
303 * don't send this "standard" writeX header. I've fixed this
304 * for 3.2 but we'll use the old method with earlier versions.
305 * Windows and CIFSFS at least use this standard size. Not
306 * sure about MacOSX.
309 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
310 (2*14) + /* word count (including bcc) */ \
311 1 /* pad byte */)
313 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
314 const char lenbuf[4],
315 struct smbXsrv_connection *xconn,
316 int sock,
317 char **buffer,
318 unsigned int timeout,
319 size_t *p_unread,
320 size_t *len_ret)
322 /* Size of a WRITEX call (+4 byte len). */
323 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
324 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
325 ssize_t toread;
326 NTSTATUS status;
328 memcpy(writeX_header, lenbuf, 4);
330 status = read_fd_with_timeout(
331 sock, writeX_header + 4,
332 STANDARD_WRITE_AND_X_HEADER_SIZE,
333 STANDARD_WRITE_AND_X_HEADER_SIZE,
334 timeout, NULL);
336 if (!NT_STATUS_IS_OK(status)) {
337 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
338 "error = %s.\n",
339 smbXsrv_connection_dbg(xconn),
340 nt_errstr(status)));
341 return status;
345 * Ok - now try and see if this is a possible
346 * valid writeX call.
349 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
351 * If the data offset is beyond what
352 * we've read, drain the extra bytes.
354 uint16_t doff = SVAL(writeX_header,smb_vwv11);
355 ssize_t newlen;
357 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
358 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
359 if (drain_socket(sock, drain) != drain) {
360 smb_panic("receive_smb_raw_talloc_partial_read:"
361 " failed to drain pending bytes");
363 } else {
364 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
367 /* Spoof down the length and null out the bcc. */
368 set_message_bcc(writeX_header, 0);
369 newlen = smb_len(writeX_header);
371 /* Copy the header we've written. */
373 *buffer = (char *)talloc_memdup(mem_ctx,
374 writeX_header,
375 sizeof(writeX_header));
377 if (*buffer == NULL) {
378 DEBUG(0, ("Could not allocate inbuf of length %d\n",
379 (int)sizeof(writeX_header)));
380 return NT_STATUS_NO_MEMORY;
383 /* Work out the remaining bytes. */
384 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
385 *len_ret = newlen + 4;
386 return NT_STATUS_OK;
389 if (!valid_packet_size(len)) {
390 return NT_STATUS_INVALID_PARAMETER;
394 * Not a valid writeX call. Just do the standard
395 * talloc and return.
398 *buffer = talloc_array(mem_ctx, char, len+4);
400 if (*buffer == NULL) {
401 DEBUG(0, ("Could not allocate inbuf of length %d\n",
402 (int)len+4));
403 return NT_STATUS_NO_MEMORY;
406 /* Copy in what we already read. */
407 memcpy(*buffer,
408 writeX_header,
409 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
410 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
412 if(toread > 0) {
413 status = read_packet_remainder(
414 sock,
415 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
416 timeout, toread);
418 if (!NT_STATUS_IS_OK(status)) {
419 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
420 nt_errstr(status)));
421 return status;
425 *len_ret = len + 4;
426 return NT_STATUS_OK;
429 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
430 struct smbXsrv_connection *xconn,
431 int sock,
432 char **buffer, unsigned int timeout,
433 size_t *p_unread, size_t *plen)
435 char lenbuf[4];
436 size_t len;
437 int min_recv_size = lp_min_receive_file_size();
438 NTSTATUS status;
440 *p_unread = 0;
442 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
443 &len);
444 if (!NT_STATUS_IS_OK(status)) {
445 return status;
448 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
449 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
450 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
451 !smb1_srv_is_signing_active(xconn) &&
452 xconn->smb1.echo_handler.trusted_fde == NULL) {
454 return receive_smb_raw_talloc_partial_read(
455 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
456 p_unread, plen);
459 if (!valid_packet_size(len)) {
460 return NT_STATUS_INVALID_PARAMETER;
464 * The +4 here can't wrap, we've checked the length above already.
467 *buffer = talloc_array(mem_ctx, char, len+4);
469 if (*buffer == NULL) {
470 DEBUG(0, ("Could not allocate inbuf of length %d\n",
471 (int)len+4));
472 return NT_STATUS_NO_MEMORY;
475 memcpy(*buffer, lenbuf, sizeof(lenbuf));
477 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
478 if (!NT_STATUS_IS_OK(status)) {
479 return status;
482 *plen = len + 4;
483 return NT_STATUS_OK;
486 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
487 struct smbXsrv_connection *xconn,
488 int sock,
489 char **buffer, unsigned int timeout,
490 size_t *p_unread, bool *p_encrypted,
491 size_t *p_len,
492 uint32_t *seqnum,
493 bool trusted_channel)
495 size_t len = 0;
496 NTSTATUS status;
498 *p_encrypted = false;
500 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
501 p_unread, &len);
502 if (!NT_STATUS_IS_OK(status)) {
503 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
504 ("receive_smb_raw_talloc failed for client %s "
505 "read error = %s.\n",
506 smbXsrv_connection_dbg(xconn),
507 nt_errstr(status)) );
508 return status;
511 if (is_encrypted_packet((uint8_t *)*buffer)) {
512 status = srv_decrypt_buffer(xconn, *buffer);
513 if (!NT_STATUS_IS_OK(status)) {
514 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
515 "incoming packet! Error %s\n",
516 nt_errstr(status) ));
517 return status;
519 *p_encrypted = true;
522 /* Check the incoming SMB signature. */
523 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
524 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
525 "incoming packet!\n"));
526 return NT_STATUS_INVALID_NETWORK_RESPONSE;
529 *p_len = len;
530 return NT_STATUS_OK;
533 /****************************************************************************
534 Function to push a message onto the tail of a linked list of smb messages ready
535 for processing.
536 ****************************************************************************/
538 static bool push_queued_message(struct smb_request *req,
539 struct timeval request_time,
540 struct timeval end_time,
541 struct deferred_open_record *open_rec)
543 int msg_len = smb_len(req->inbuf) + 4;
544 struct pending_message_list *msg;
546 msg = talloc_zero(NULL, struct pending_message_list);
548 if(msg == NULL) {
549 DEBUG(0,("push_message: malloc fail (1)\n"));
550 return False;
552 msg->sconn = req->sconn;
553 msg->xconn = req->xconn;
555 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
556 if(msg->buf.data == NULL) {
557 DEBUG(0,("push_message: malloc fail (2)\n"));
558 TALLOC_FREE(msg);
559 return False;
562 msg->request_time = request_time;
563 msg->seqnum = req->seqnum;
564 msg->encrypted = req->encrypted;
565 msg->processed = false;
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 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1018 int snum;
1019 enum remote_arch_types ra_type;
1021 SMB_ASSERT(conn != NULL);
1022 SMB_ASSERT(!conn->sconn->using_smb2);
1024 snum = SNUM(conn);
1027 * Obey the client case sensitivity requests - only for clients that
1028 * support it. */
1029 switch (lp_case_sensitive(snum)) {
1030 case Auto:
1032 * We need this uglyness due to DOS/Win9x clients that lie
1033 * about case insensitivity. */
1034 ra_type = get_remote_arch();
1035 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1037 * Client can't support per-packet case sensitive
1038 * pathnames. */
1039 conn->case_sensitive = false;
1040 } else {
1041 conn->case_sensitive =
1042 !(flags & FLAG_CASELESS_PATHNAMES);
1044 break;
1045 case True:
1046 conn->case_sensitive = true;
1047 break;
1048 default:
1049 conn->case_sensitive = false;
1050 break;
1054 /****************************************************************************
1055 Prepare everything for calling the actual request function, and potentially
1056 call the request function via the "new" interface.
1058 Return False if the "legacy" function needs to be called, everything is
1059 prepared.
1061 Return True if we're done.
1063 I know this API sucks, but it is the one with the least code change I could
1064 find.
1065 ****************************************************************************/
1067 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1069 const struct loadparm_substitution *lp_sub =
1070 loadparm_s3_global_substitution();
1071 int flags;
1072 uint64_t session_tag;
1073 connection_struct *conn = NULL;
1074 struct smbXsrv_connection *xconn = req->xconn;
1075 NTTIME now = timeval_to_nttime(&req->request_time);
1076 struct smbXsrv_session *session = NULL;
1077 NTSTATUS status;
1079 errno = 0;
1081 if (!xconn->smb1.negprot.done) {
1082 switch (type) {
1084 * Without a negprot the request must
1085 * either be a negprot, or one of the
1086 * evil old SMB mailslot messaging types.
1088 case SMBnegprot:
1089 case SMBsendstrt:
1090 case SMBsendend:
1091 case SMBsendtxt:
1092 break;
1093 default:
1094 exit_server_cleanly("The first request "
1095 "should be a negprot");
1099 if (smb_messages[type].fn == NULL) {
1100 DEBUG(0,("Unknown message type %d!\n",type));
1101 smb_dump("Unknown", 1, (const char *)req->inbuf);
1102 reply_unknown_new(req, type);
1103 return NULL;
1106 flags = smb_messages[type].flags;
1108 /* In share mode security we must ignore the vuid. */
1109 session_tag = req->vuid;
1110 conn = req->conn;
1112 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1113 (int)getpid(), (unsigned long)conn));
1115 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1117 /* Ensure this value is replaced in the incoming packet. */
1118 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1121 * Ensure the correct username is in current_user_info. This is a
1122 * really ugly bugfix for problems with multiple session_setup_and_X's
1123 * being done and allowing %U and %G substitutions to work correctly.
1124 * There is a reason this code is done here, don't move it unless you
1125 * know what you're doing... :-).
1126 * JRA.
1130 * lookup an existing session
1132 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1133 * here, the main check is still in change_to_user()
1135 status = smb1srv_session_lookup(xconn,
1136 session_tag,
1137 now,
1138 &session);
1139 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1140 switch (type) {
1141 case SMBsesssetupX:
1142 status = NT_STATUS_OK;
1143 break;
1144 default:
1145 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1146 (unsigned long long)session_tag,
1147 (unsigned long long)req->mid));
1148 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1149 return conn;
1153 if (session != NULL &&
1154 session->global->auth_session_info != NULL &&
1155 !(flags & AS_USER))
1158 * change_to_user() implies set_current_user_info()
1159 * and chdir_connect_service().
1161 * So we only call set_current_user_info if
1162 * we don't have AS_USER specified.
1164 set_current_user_info(
1165 session->global->auth_session_info->unix_info->sanitized_username,
1166 session->global->auth_session_info->unix_info->unix_name,
1167 session->global->auth_session_info->info->domain_name);
1170 /* Does this call need to be run as the connected user? */
1171 if (flags & AS_USER) {
1173 /* Does this call need a valid tree connection? */
1174 if (!conn) {
1176 * Amazingly, the error code depends on the command
1177 * (from Samba4).
1179 if (type == SMBntcreateX) {
1180 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1181 } else {
1182 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1184 return NULL;
1187 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1190 * change_to_user() implies set_current_user_info()
1191 * and chdir_connect_service().
1193 if (!change_to_user_and_service(conn,session_tag)) {
1194 DEBUG(0, ("Error: Could not change to user. Removing "
1195 "deferred open, mid=%llu.\n",
1196 (unsigned long long)req->mid));
1197 reply_force_doserror(req, ERRSRV, ERRbaduid);
1198 return conn;
1201 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1203 /* Does it need write permission? */
1204 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1205 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1206 return conn;
1209 /* IPC services are limited */
1210 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1211 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1212 return conn;
1214 } else if (flags & AS_GUEST) {
1216 * Does this protocol need to be run as guest? (Only archane
1217 * messenger service requests have this...)
1219 if (!change_to_guest()) {
1220 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1221 return conn;
1223 } else {
1224 /* This call needs to be run as root */
1225 change_to_root_user();
1228 /* load service specific parameters */
1229 if (conn) {
1230 if (req->encrypted) {
1231 conn->encrypted_tid = true;
1232 /* encrypted required from now on. */
1233 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1234 } else if (ENCRYPTION_REQUIRED(conn)) {
1235 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1236 DEBUG(1,("service[%s] requires encryption"
1237 "%s ACCESS_DENIED. mid=%llu\n",
1238 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1239 smb_fn_name(type),
1240 (unsigned long long)req->mid));
1241 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1242 return conn;
1246 if (flags & DO_CHDIR) {
1247 bool ok;
1249 ok = chdir_current_service(conn);
1250 if (!ok) {
1251 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1252 return conn;
1255 conn->num_smb_operations++;
1259 * Update encryption and signing state tracking flags that are
1260 * used by smbstatus to display signing and encryption status.
1262 if (session != NULL) {
1263 bool update_session_global = false;
1264 bool update_tcon_global = false;
1266 req->session = session;
1268 smb1srv_update_crypto_flags(session, req, type,
1269 &update_session_global,
1270 &update_tcon_global);
1272 if (update_session_global) {
1273 status = smbXsrv_session_update(session);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1276 return conn;
1280 if (update_tcon_global) {
1281 status = smbXsrv_tcon_update(req->conn->tcon);
1282 if (!NT_STATUS_IS_OK(status)) {
1283 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1284 return conn;
1289 smb_messages[type].fn(req);
1290 return req->conn;
1293 /****************************************************************************
1294 Construct a reply to the incoming packet.
1295 ****************************************************************************/
1297 void construct_reply(struct smbXsrv_connection *xconn,
1298 char *inbuf,
1299 int size,
1300 size_t unread_bytes,
1301 uint32_t seqnum,
1302 bool encrypted)
1304 struct smbd_server_connection *sconn = xconn->client->sconn;
1305 struct smb_request *req;
1307 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1308 smb_panic("could not allocate smb_request");
1311 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1312 encrypted, seqnum)) {
1313 exit_server_cleanly("Invalid SMB request");
1316 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1318 req->conn = switch_message(req->cmd, req);
1320 if (req->outbuf == NULL) {
1322 * Request has suspended itself, will come
1323 * back here.
1325 return;
1327 if (CVAL(req->outbuf,0) == 0) {
1328 show_msg((char *)req->outbuf);
1330 smb_request_done(req);
1333 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1334 char *inbuf,
1335 int size,
1336 uint32_t seqnum,
1337 bool encrypted)
1339 struct smb_request **reqs = NULL;
1340 struct smb_request *req;
1341 unsigned num_reqs;
1342 bool ok;
1344 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1345 seqnum, &reqs, &num_reqs);
1346 if (!ok) {
1347 char errbuf[smb_size];
1348 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1349 __LINE__, __FILE__);
1350 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
1351 exit_server_cleanly("construct_reply_chain: "
1352 "smb1_srv_send failed.");
1354 return;
1357 req = reqs[0];
1358 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1360 req->conn = switch_message(req->cmd, req);
1362 if (req->outbuf == NULL) {
1364 * Request has suspended itself, will come
1365 * back here.
1367 return;
1369 smb_request_done(req);
1373 * To be called from an async SMB handler that is potentially chained
1374 * when it is finished for shipping.
1377 void smb_request_done(struct smb_request *req)
1379 struct smb_request **reqs = NULL;
1380 struct smb_request *first_req;
1381 size_t i, num_reqs, next_index;
1382 NTSTATUS status;
1384 if (req->chain == NULL) {
1385 first_req = req;
1386 goto shipit;
1389 reqs = req->chain;
1390 num_reqs = talloc_array_length(reqs);
1392 for (i=0; i<num_reqs; i++) {
1393 if (reqs[i] == req) {
1394 break;
1397 if (i == num_reqs) {
1399 * Invalid chain, should not happen
1401 status = NT_STATUS_INTERNAL_ERROR;
1402 goto error;
1404 next_index = i+1;
1406 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1407 struct smb_request *next = reqs[next_index];
1408 struct smbXsrv_tcon *tcon;
1409 NTTIME now = timeval_to_nttime(&req->request_time);
1411 next->vuid = SVAL(req->outbuf, smb_uid);
1412 next->tid = SVAL(req->outbuf, smb_tid);
1413 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1414 now, &tcon);
1416 if (NT_STATUS_IS_OK(status)) {
1417 next->conn = tcon->compat;
1418 } else {
1419 next->conn = NULL;
1421 next->chain_fsp = req->chain_fsp;
1422 next->inbuf = req->inbuf;
1424 req = next;
1425 req->conn = switch_message(req->cmd, req);
1427 if (req->outbuf == NULL) {
1429 * Request has suspended itself, will come
1430 * back here.
1432 return;
1434 next_index += 1;
1437 first_req = reqs[0];
1439 for (i=1; i<next_index; i++) {
1440 bool ok;
1442 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1443 if (!ok) {
1444 status = NT_STATUS_INTERNAL_ERROR;
1445 goto error;
1449 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1450 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1453 * This scary statement intends to set the
1454 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1455 * to the value last_req->outbuf carries
1457 SSVAL(first_req->outbuf, smb_flg2,
1458 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1459 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1462 * Transfer the error codes from the subrequest to the main one
1464 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1465 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1467 _smb_setlen_large(
1468 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1470 shipit:
1471 if (!smb1_srv_send(first_req->xconn,
1472 (char *)first_req->outbuf,
1473 true,
1474 first_req->seqnum + 1,
1475 IS_CONN_ENCRYPTED(req->conn) ||
1476 first_req->encrypted)) {
1477 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1478 "failed.");
1480 TALLOC_FREE(req); /* non-chained case */
1481 TALLOC_FREE(reqs); /* chained case */
1482 return;
1484 error:
1486 char errbuf[smb_size];
1487 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1488 if (!smb1_srv_send(req->xconn,
1489 errbuf,
1490 true,
1491 req->seqnum + 1,
1492 req->encrypted)) {
1493 exit_server_cleanly("construct_reply_chain: "
1494 "smb1_srv_send failed.");
1497 TALLOC_FREE(req); /* non-chained case */
1498 TALLOC_FREE(reqs); /* chained case */
1501 /****************************************************************************
1502 Process an smb from the client
1503 ****************************************************************************/
1505 void process_smb1(struct smbXsrv_connection *xconn,
1506 uint8_t *inbuf,
1507 size_t nread,
1508 size_t unread_bytes,
1509 uint32_t seqnum,
1510 bool encrypted)
1512 struct smbd_server_connection *sconn = xconn->client->sconn;
1514 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1515 * so subtract 4 from it. */
1516 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1517 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1518 smb_len(inbuf)));
1520 /* special magic for immediate exit */
1521 if ((nread == 9) &&
1522 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1523 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1524 uint8_t exitcode = CVAL(inbuf, 8);
1525 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1526 (int)exitcode);
1527 exit(exitcode);
1530 exit_server_cleanly("Non-SMB packet");
1533 show_msg((char *)inbuf);
1535 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1536 construct_reply_chain(xconn,
1537 (char *)inbuf,
1538 nread,
1539 seqnum,
1540 encrypted);
1541 } else {
1542 construct_reply(xconn,
1543 (char *)inbuf,
1544 nread,
1545 unread_bytes,
1546 seqnum,
1547 encrypted);
1550 sconn->trans_num++;
1553 /****************************************************************************
1554 Return a string containing the function name of a SMB command.
1555 ****************************************************************************/
1557 const char *smb_fn_name(int type)
1559 const char *unknown_name = "SMBunknown";
1561 if (smb_messages[type].name == NULL)
1562 return(unknown_name);
1564 return(smb_messages[type].name);
1567 /****************************************************************************
1568 Helper functions for contruct_reply.
1569 ****************************************************************************/
1571 void add_to_common_flags2(uint32_t v)
1573 common_flags2 |= v;
1576 void remove_from_common_flags2(uint32_t v)
1578 common_flags2 &= ~v;
1582 * @brief Find the smb_cmd offset of the last command pushed
1583 * @param[in] buf The buffer we're building up
1584 * @retval Where can we put our next andx cmd?
1586 * While chaining requests, the "next" request we're looking at needs to put
1587 * its SMB_Command before the data the previous request already built up added
1588 * to the chain. Find the offset to the place where we have to put our cmd.
1591 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1593 uint8_t cmd;
1594 size_t ofs;
1596 cmd = CVAL(buf, smb_com);
1598 if (!smb1cli_is_andx_req(cmd)) {
1599 return false;
1602 ofs = smb_vwv0;
1604 while (CVAL(buf, ofs) != 0xff) {
1606 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1607 return false;
1611 * ofs is from start of smb header, so add the 4 length
1612 * bytes. The next cmd is right after the wct field.
1614 ofs = SVAL(buf, ofs+2) + 4 + 1;
1616 if (ofs+4 >= talloc_get_size(buf)) {
1617 return false;
1621 *pofs = ofs;
1622 return true;
1626 * @brief Do the smb chaining at a buffer level
1627 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1628 * @param[in] andx_buf Buffer to be appended
1631 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1633 uint8_t smb_command = CVAL(andx_buf, smb_com);
1634 uint8_t wct = CVAL(andx_buf, smb_wct);
1635 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1636 uint32_t num_bytes = smb_buflen(andx_buf);
1637 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1639 uint8_t *outbuf;
1640 size_t old_size, new_size;
1641 size_t ofs;
1642 size_t chain_padding = 0;
1643 size_t andx_cmd_ofs;
1646 old_size = talloc_get_size(*poutbuf);
1648 if ((old_size % 4) != 0) {
1650 * Align the wct field of subsequent requests to a 4-byte
1651 * boundary
1653 chain_padding = 4 - (old_size % 4);
1657 * After the old request comes the new wct field (1 byte), the vwv's
1658 * and the num_bytes field.
1661 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1662 new_size += num_bytes;
1664 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1665 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1666 (unsigned)new_size));
1667 return false;
1670 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1671 if (outbuf == NULL) {
1672 DEBUG(0, ("talloc failed\n"));
1673 return false;
1675 *poutbuf = outbuf;
1677 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1678 DEBUG(1, ("invalid command chain\n"));
1679 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1680 return false;
1683 if (chain_padding != 0) {
1684 memset(outbuf + old_size, 0, chain_padding);
1685 old_size += chain_padding;
1688 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1689 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1691 ofs = old_size;
1694 * Push the chained request:
1696 * wct field
1699 SCVAL(outbuf, ofs, wct);
1700 ofs += 1;
1703 * vwv array
1706 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1709 * HACK ALERT
1711 * Read&X has an offset into its data buffer at
1712 * vwv[6]. reply_read_andx has no idea anymore that it's
1713 * running from within a chain, so we have to fix up the
1714 * offset here.
1716 * Although it looks disgusting at this place, I want to keep
1717 * it here. The alternative would be to push knowledge about
1718 * the andx chain down into read&x again.
1721 if (smb_command == SMBreadX) {
1722 uint8_t *bytes_addr;
1724 if (wct < 7) {
1726 * Invalid read&x response
1728 return false;
1731 bytes_addr = outbuf + ofs /* vwv start */
1732 + sizeof(uint16_t) * wct /* vwv array */
1733 + sizeof(uint16_t) /* bcc */
1734 + 1; /* padding byte */
1736 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1737 bytes_addr - outbuf - 4);
1740 ofs += sizeof(uint16_t) * wct;
1743 * bcc (byte count)
1746 SSVAL(outbuf, ofs, num_bytes);
1747 ofs += sizeof(uint16_t);
1750 * The bytes field
1753 memcpy(outbuf + ofs, bytes, num_bytes);
1755 return true;
1758 bool smb1_is_chain(const uint8_t *buf)
1760 uint8_t cmd, wct, andx_cmd;
1762 cmd = CVAL(buf, smb_com);
1763 if (!smb1cli_is_andx_req(cmd)) {
1764 return false;
1766 wct = CVAL(buf, smb_wct);
1767 if (wct < 2) {
1768 return false;
1770 andx_cmd = CVAL(buf, smb_vwv);
1771 return (andx_cmd != 0xFF);
1774 bool smb1_walk_chain(const uint8_t *buf,
1775 bool (*fn)(uint8_t cmd,
1776 uint8_t wct, const uint16_t *vwv,
1777 uint16_t num_bytes, const uint8_t *bytes,
1778 void *private_data),
1779 void *private_data)
1781 size_t smblen = smb_len(buf);
1782 const char *smb_buf = smb_base(buf);
1783 uint8_t cmd, chain_cmd;
1784 uint8_t wct;
1785 const uint16_t *vwv;
1786 uint16_t num_bytes;
1787 const uint8_t *bytes;
1789 cmd = CVAL(buf, smb_com);
1790 wct = CVAL(buf, smb_wct);
1791 vwv = (const uint16_t *)(buf + smb_vwv);
1792 num_bytes = smb_buflen(buf);
1793 bytes = (const uint8_t *)smb_buf_const(buf);
1795 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1796 return false;
1799 if (!smb1cli_is_andx_req(cmd)) {
1800 return true;
1802 if (wct < 2) {
1803 return false;
1806 chain_cmd = CVAL(vwv, 0);
1808 while (chain_cmd != 0xff) {
1809 uint32_t chain_offset; /* uint32_t to avoid overflow */
1810 size_t length_needed;
1811 ptrdiff_t vwv_offset;
1813 chain_offset = SVAL(vwv+1, 0);
1816 * Check if the client tries to fool us. The chain
1817 * offset needs to point beyond the current request in
1818 * the chain, it needs to strictly grow. Otherwise we
1819 * might be tricked into an endless loop always
1820 * processing the same request over and over again. We
1821 * used to assume that vwv and the byte buffer array
1822 * in a chain are always attached, but OS/2 the
1823 * Write&X/Read&X chain puts the Read&X vwv array
1824 * right behind the Write&X vwv chain. The Write&X bcc
1825 * array is put behind the Read&X vwv array. So now we
1826 * check whether the chain offset points strictly
1827 * behind the previous vwv array. req->buf points
1828 * right after the vwv array of the previous
1829 * request. See
1830 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1831 * more information.
1834 vwv_offset = ((const char *)vwv - smb_buf);
1835 if (chain_offset <= vwv_offset) {
1836 return false;
1840 * Next check: Make sure the chain offset does not
1841 * point beyond the overall smb request length.
1844 length_needed = chain_offset+1; /* wct */
1845 if (length_needed > smblen) {
1846 return false;
1850 * Now comes the pointer magic. Goal here is to set up
1851 * vwv and buf correctly again. The chain offset (the
1852 * former vwv[1]) points at the new wct field.
1855 wct = CVAL(smb_buf, chain_offset);
1857 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1858 return false;
1862 * Next consistency check: Make the new vwv array fits
1863 * in the overall smb request.
1866 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1867 if (length_needed > smblen) {
1868 return false;
1870 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1873 * Now grab the new byte buffer....
1876 num_bytes = SVAL(vwv+wct, 0);
1879 * .. and check that it fits.
1882 length_needed += num_bytes;
1883 if (length_needed > smblen) {
1884 return false;
1886 bytes = (const uint8_t *)(vwv+wct+1);
1888 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1889 return false;
1892 if (!smb1cli_is_andx_req(chain_cmd)) {
1893 return true;
1895 chain_cmd = CVAL(vwv, 0);
1897 return true;
1900 static bool smb1_chain_length_cb(uint8_t cmd,
1901 uint8_t wct, const uint16_t *vwv,
1902 uint16_t num_bytes, const uint8_t *bytes,
1903 void *private_data)
1905 unsigned *count = (unsigned *)private_data;
1906 *count += 1;
1907 return true;
1910 unsigned smb1_chain_length(const uint8_t *buf)
1912 unsigned count = 0;
1914 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1915 return 0;
1917 return count;
1920 struct smb1_parse_chain_state {
1921 TALLOC_CTX *mem_ctx;
1922 const uint8_t *buf;
1923 struct smbd_server_connection *sconn;
1924 struct smbXsrv_connection *xconn;
1925 bool encrypted;
1926 uint32_t seqnum;
1928 struct smb_request **reqs;
1929 unsigned num_reqs;
1932 static bool smb1_parse_chain_cb(uint8_t cmd,
1933 uint8_t wct, const uint16_t *vwv,
1934 uint16_t num_bytes, const uint8_t *bytes,
1935 void *private_data)
1937 struct smb1_parse_chain_state *state =
1938 (struct smb1_parse_chain_state *)private_data;
1939 struct smb_request **reqs;
1940 struct smb_request *req;
1941 bool ok;
1943 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1944 struct smb_request *, state->num_reqs+1);
1945 if (reqs == NULL) {
1946 return false;
1948 state->reqs = reqs;
1950 req = talloc(reqs, struct smb_request);
1951 if (req == NULL) {
1952 return false;
1955 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1956 state->encrypted, state->seqnum);
1957 if (!ok) {
1958 return false;
1960 req->cmd = cmd;
1961 req->wct = wct;
1962 req->vwv = vwv;
1963 req->buflen = num_bytes;
1964 req->buf = bytes;
1966 reqs[state->num_reqs] = req;
1967 state->num_reqs += 1;
1968 return true;
1971 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1972 struct smbXsrv_connection *xconn,
1973 bool encrypted, uint32_t seqnum,
1974 struct smb_request ***reqs, unsigned *num_reqs)
1976 struct smbd_server_connection *sconn = NULL;
1977 struct smb1_parse_chain_state state;
1978 unsigned i;
1980 if (xconn != NULL) {
1981 sconn = xconn->client->sconn;
1984 state.mem_ctx = mem_ctx;
1985 state.buf = buf;
1986 state.sconn = sconn;
1987 state.xconn = xconn;
1988 state.encrypted = encrypted;
1989 state.seqnum = seqnum;
1990 state.reqs = NULL;
1991 state.num_reqs = 0;
1993 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1994 TALLOC_FREE(state.reqs);
1995 return false;
1997 for (i=0; i<state.num_reqs; i++) {
1998 state.reqs[i]->chain = state.reqs;
2000 *reqs = state.reqs;
2001 *num_reqs = state.num_reqs;
2002 return true;
2005 static bool fd_is_readable(int fd)
2007 int ret, revents;
2009 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2011 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2015 static void smbd_server_connection_write_handler(
2016 struct smbXsrv_connection *xconn)
2018 /* TODO: make write nonblocking */
2021 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2022 int fd)
2024 uint8_t *inbuf = NULL;
2025 size_t inbuf_len = 0;
2026 size_t unread_bytes = 0;
2027 bool encrypted = false;
2028 TALLOC_CTX *mem_ctx = talloc_tos();
2029 NTSTATUS status;
2030 uint32_t seqnum;
2032 bool async_echo = lp_async_smb_echo_handler();
2033 bool from_client = false;
2035 if (async_echo) {
2036 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
2038 * This is the super-ugly hack to prefer the packets
2039 * forwarded by the echo handler over the ones by the
2040 * client directly
2042 fd = xconn->smb1.echo_handler.trusted_fd;
2046 from_client = (xconn->transport.sock == fd);
2048 if (async_echo && from_client) {
2049 smbd_lock_socket(xconn);
2051 if (!fd_is_readable(fd)) {
2052 DEBUG(10,("the echo listener was faster\n"));
2053 smbd_unlock_socket(xconn);
2054 return;
2058 /* TODO: make this completely nonblocking */
2059 status = receive_smb_talloc(mem_ctx, xconn, fd,
2060 (char **)(void *)&inbuf,
2061 0, /* timeout */
2062 &unread_bytes,
2063 &encrypted,
2064 &inbuf_len, &seqnum,
2065 !from_client /* trusted channel */);
2067 if (async_echo && from_client) {
2068 smbd_unlock_socket(xconn);
2071 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2072 goto process;
2074 if (NT_STATUS_IS_ERR(status)) {
2075 exit_server_cleanly("failed to receive smb request");
2077 if (!NT_STATUS_IS_OK(status)) {
2078 return;
2081 process:
2082 process_smb(xconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted);
2085 static void smbd_server_echo_handler(struct tevent_context *ev,
2086 struct tevent_fd *fde,
2087 uint16_t flags,
2088 void *private_data)
2090 struct smbXsrv_connection *xconn =
2091 talloc_get_type_abort(private_data,
2092 struct smbXsrv_connection);
2094 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2096 * we're not supposed to do any io
2098 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2099 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2100 return;
2103 if (flags & TEVENT_FD_WRITE) {
2104 smbd_server_connection_write_handler(xconn);
2105 return;
2107 if (flags & TEVENT_FD_READ) {
2108 smbd_smb1_server_connection_read_handler(
2109 xconn, xconn->smb1.echo_handler.trusted_fd);
2110 return;
2115 * Send keepalive packets to our client
2117 bool keepalive_fn(const struct timeval *now, void *private_data)
2119 struct smbd_server_connection *sconn = talloc_get_type_abort(
2120 private_data, struct smbd_server_connection);
2121 struct smbXsrv_connection *xconn = NULL;
2122 bool ret;
2124 if (sconn->using_smb2) {
2125 /* Don't do keepalives on an SMB2 connection. */
2126 return false;
2130 * With SMB1 we only have 1 connection
2132 xconn = sconn->client->connections;
2133 smbd_lock_socket(xconn);
2134 ret = send_keepalive(xconn->transport.sock);
2135 smbd_unlock_socket(xconn);
2137 if (!ret) {
2138 int saved_errno = errno;
2140 * Try and give an error message saying what
2141 * client failed.
2143 DEBUG(0, ("send_keepalive failed for client %s. "
2144 "Error %s - exiting\n",
2145 smbXsrv_connection_dbg(xconn),
2146 strerror(saved_errno)));
2147 errno = saved_errno;
2148 return False;
2150 return True;
2154 * Read an smb packet in the echo handler child, giving the parent
2155 * smbd one second to react once the socket becomes readable.
2158 struct smbd_echo_read_state {
2159 struct tevent_context *ev;
2160 struct smbXsrv_connection *xconn;
2162 char *buf;
2163 size_t buflen;
2164 uint32_t seqnum;
2167 static void smbd_echo_read_readable(struct tevent_req *subreq);
2168 static void smbd_echo_read_waited(struct tevent_req *subreq);
2170 static struct tevent_req *smbd_echo_read_send(
2171 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2172 struct smbXsrv_connection *xconn)
2174 struct tevent_req *req, *subreq;
2175 struct smbd_echo_read_state *state;
2177 req = tevent_req_create(mem_ctx, &state,
2178 struct smbd_echo_read_state);
2179 if (req == NULL) {
2180 return NULL;
2182 state->ev = ev;
2183 state->xconn = xconn;
2185 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2186 if (tevent_req_nomem(subreq, req)) {
2187 return tevent_req_post(req, ev);
2189 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2190 return req;
2193 static void smbd_echo_read_readable(struct tevent_req *subreq)
2195 struct tevent_req *req = tevent_req_callback_data(
2196 subreq, struct tevent_req);
2197 struct smbd_echo_read_state *state = tevent_req_data(
2198 req, struct smbd_echo_read_state);
2199 bool ok;
2200 int err;
2202 ok = wait_for_read_recv(subreq, &err);
2203 TALLOC_FREE(subreq);
2204 if (!ok) {
2205 tevent_req_nterror(req, map_nt_error_from_unix(err));
2206 return;
2210 * Give the parent smbd one second to step in
2213 subreq = tevent_wakeup_send(
2214 state, state->ev, timeval_current_ofs(1, 0));
2215 if (tevent_req_nomem(subreq, req)) {
2216 return;
2218 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2221 static void smbd_echo_read_waited(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2225 struct smbd_echo_read_state *state = tevent_req_data(
2226 req, struct smbd_echo_read_state);
2227 struct smbXsrv_connection *xconn = state->xconn;
2228 bool ok;
2229 NTSTATUS status;
2230 size_t unread = 0;
2231 bool encrypted;
2233 ok = tevent_wakeup_recv(subreq);
2234 TALLOC_FREE(subreq);
2235 if (!ok) {
2236 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2237 return;
2240 ok = smbd_lock_socket_internal(xconn);
2241 if (!ok) {
2242 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2243 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2244 return;
2247 if (!fd_is_readable(xconn->transport.sock)) {
2248 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2249 (int)getpid()));
2251 ok = smbd_unlock_socket_internal(xconn);
2252 if (!ok) {
2253 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2254 DEBUG(1, ("%s: failed to unlock socket\n",
2255 __location__));
2256 return;
2259 subreq = wait_for_read_send(state, state->ev,
2260 xconn->transport.sock, false);
2261 if (tevent_req_nomem(subreq, req)) {
2262 return;
2264 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2265 return;
2268 status = receive_smb_talloc(state, xconn,
2269 xconn->transport.sock,
2270 &state->buf,
2271 0 /* timeout */,
2272 &unread,
2273 &encrypted,
2274 &state->buflen,
2275 &state->seqnum,
2276 false /* trusted_channel*/);
2278 if (tevent_req_nterror(req, status)) {
2279 tevent_req_nterror(req, status);
2280 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2281 (int)getpid(), nt_errstr(status)));
2282 return;
2285 ok = smbd_unlock_socket_internal(xconn);
2286 if (!ok) {
2287 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2288 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2289 return;
2291 tevent_req_done(req);
2294 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2295 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2297 struct smbd_echo_read_state *state = tevent_req_data(
2298 req, struct smbd_echo_read_state);
2299 NTSTATUS status;
2301 if (tevent_req_is_nterror(req, &status)) {
2302 return status;
2304 *pbuf = talloc_move(mem_ctx, &state->buf);
2305 *pbuflen = state->buflen;
2306 *pseqnum = state->seqnum;
2307 return NT_STATUS_OK;
2310 struct smbd_echo_state {
2311 struct tevent_context *ev;
2312 struct iovec *pending;
2313 struct smbd_server_connection *sconn;
2314 struct smbXsrv_connection *xconn;
2315 int parent_pipe;
2317 struct tevent_fd *parent_fde;
2319 struct tevent_req *write_req;
2322 static void smbd_echo_writer_done(struct tevent_req *req);
2324 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2326 int num_pending;
2328 if (state->write_req != NULL) {
2329 return;
2332 num_pending = talloc_array_length(state->pending);
2333 if (num_pending == 0) {
2334 return;
2337 state->write_req = writev_send(state, state->ev, NULL,
2338 state->parent_pipe, false,
2339 state->pending, num_pending);
2340 if (state->write_req == NULL) {
2341 DEBUG(1, ("writev_send failed\n"));
2342 exit(1);
2345 talloc_steal(state->write_req, state->pending);
2346 state->pending = NULL;
2348 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2349 state);
2352 static void smbd_echo_writer_done(struct tevent_req *req)
2354 struct smbd_echo_state *state = tevent_req_callback_data(
2355 req, struct smbd_echo_state);
2356 ssize_t written;
2357 int err;
2359 written = writev_recv(req, &err);
2360 TALLOC_FREE(req);
2361 state->write_req = NULL;
2362 if (written == -1) {
2363 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2364 exit(1);
2366 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2367 smbd_echo_activate_writer(state);
2370 static bool smbd_echo_reply(struct smbd_echo_state *state,
2371 uint8_t *inbuf, size_t inbuf_len,
2372 uint32_t seqnum)
2374 struct smb_request req;
2375 uint16_t num_replies;
2376 char *outbuf;
2377 bool ok;
2379 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2380 DEBUG(10, ("Got netbios keepalive\n"));
2382 * Just swallow it
2384 return true;
2387 if (inbuf_len < smb_size) {
2388 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2389 return false;
2391 if (!valid_smb1_header(inbuf)) {
2392 DEBUG(10, ("Got invalid SMB header\n"));
2393 return false;
2396 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2397 seqnum)) {
2398 return false;
2400 req.inbuf = inbuf;
2402 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2403 smb_messages[req.cmd].name
2404 ? smb_messages[req.cmd].name : "unknown"));
2406 if (req.cmd != SMBecho) {
2407 return false;
2409 if (req.wct < 1) {
2410 return false;
2413 num_replies = SVAL(req.vwv+0, 0);
2414 if (num_replies != 1) {
2415 /* Not a Windows "Hey, you're still there?" request */
2416 return false;
2419 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2420 1, req.buflen)) {
2421 DEBUG(10, ("create_smb1_outbuf failed\n"));
2422 return false;
2424 req.outbuf = (uint8_t *)outbuf;
2426 SSVAL(req.outbuf, smb_vwv0, num_replies);
2428 if (req.buflen > 0) {
2429 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2432 ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
2433 TALLOC_FREE(outbuf);
2434 if (!ok) {
2435 exit(1);
2438 return true;
2441 static void smbd_echo_exit(struct tevent_context *ev,
2442 struct tevent_fd *fde, uint16_t flags,
2443 void *private_data)
2445 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2446 exit(0);
2449 static void smbd_echo_got_packet(struct tevent_req *req);
2451 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2452 int parent_pipe)
2454 struct smbd_echo_state *state;
2455 struct tevent_req *read_req;
2457 state = talloc_zero(xconn, struct smbd_echo_state);
2458 if (state == NULL) {
2459 DEBUG(1, ("talloc failed\n"));
2460 return;
2462 state->xconn = xconn;
2463 state->parent_pipe = parent_pipe;
2464 state->ev = samba_tevent_context_init(state);
2465 if (state->ev == NULL) {
2466 DEBUG(1, ("samba_tevent_context_init failed\n"));
2467 TALLOC_FREE(state);
2468 return;
2470 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2471 TEVENT_FD_READ, smbd_echo_exit,
2472 state);
2473 if (state->parent_fde == NULL) {
2474 DEBUG(1, ("tevent_add_fd failed\n"));
2475 TALLOC_FREE(state);
2476 return;
2479 read_req = smbd_echo_read_send(state, state->ev, xconn);
2480 if (read_req == NULL) {
2481 DEBUG(1, ("smbd_echo_read_send failed\n"));
2482 TALLOC_FREE(state);
2483 return;
2485 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2487 while (true) {
2488 if (tevent_loop_once(state->ev) == -1) {
2489 DEBUG(1, ("tevent_loop_once failed: %s\n",
2490 strerror(errno)));
2491 break;
2494 TALLOC_FREE(state);
2497 static void smbd_echo_got_packet(struct tevent_req *req)
2499 struct smbd_echo_state *state = tevent_req_callback_data(
2500 req, struct smbd_echo_state);
2501 NTSTATUS status;
2502 char *buf = NULL;
2503 size_t buflen = 0;
2504 uint32_t seqnum = 0;
2505 bool reply;
2507 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2508 TALLOC_FREE(req);
2509 if (!NT_STATUS_IS_OK(status)) {
2510 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2511 nt_errstr(status)));
2512 exit(1);
2515 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2516 if (!reply) {
2517 size_t num_pending;
2518 struct iovec *tmp;
2519 struct iovec *iov;
2521 num_pending = talloc_array_length(state->pending);
2522 tmp = talloc_realloc(state, state->pending, struct iovec,
2523 num_pending+1);
2524 if (tmp == NULL) {
2525 DEBUG(1, ("talloc_realloc failed\n"));
2526 exit(1);
2528 state->pending = tmp;
2530 if (buflen >= smb_size) {
2532 * place the seqnum in the packet so that the main process
2533 * can reply with signing
2535 SIVAL(buf, smb_ss_field, seqnum);
2536 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2539 iov = &state->pending[num_pending];
2540 iov->iov_base = talloc_move(state->pending, &buf);
2541 iov->iov_len = buflen;
2543 DEBUG(10,("echo_handler[%d]: forward to main\n",
2544 (int)getpid()));
2545 smbd_echo_activate_writer(state);
2548 req = smbd_echo_read_send(state, state->ev, state->xconn);
2549 if (req == NULL) {
2550 DEBUG(1, ("smbd_echo_read_send failed\n"));
2551 exit(1);
2553 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2558 * Handle SMBecho requests in a forked child process
2560 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2562 int listener_pipe[2];
2563 int res;
2564 pid_t child;
2565 bool use_mutex = false;
2567 res = pipe(listener_pipe);
2568 if (res == -1) {
2569 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2570 return false;
2573 #ifdef HAVE_ROBUST_MUTEXES
2574 use_mutex = tdb_runtime_check_for_robust_mutexes();
2576 if (use_mutex) {
2577 pthread_mutexattr_t a;
2579 xconn->smb1.echo_handler.socket_mutex =
2580 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2581 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2582 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2583 strerror(errno)));
2584 goto fail;
2587 res = pthread_mutexattr_init(&a);
2588 if (res != 0) {
2589 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2590 strerror(res)));
2591 goto fail;
2593 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2594 if (res != 0) {
2595 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2596 strerror(res)));
2597 pthread_mutexattr_destroy(&a);
2598 goto fail;
2600 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2601 if (res != 0) {
2602 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2603 strerror(res)));
2604 pthread_mutexattr_destroy(&a);
2605 goto fail;
2607 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2608 if (res != 0) {
2609 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2610 "%s\n", strerror(res)));
2611 pthread_mutexattr_destroy(&a);
2612 goto fail;
2614 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2615 &a);
2616 pthread_mutexattr_destroy(&a);
2617 if (res != 0) {
2618 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2619 strerror(res)));
2620 goto fail;
2623 #endif
2625 if (!use_mutex) {
2626 xconn->smb1.echo_handler.socket_lock_fd =
2627 create_unlink_tmp(lp_lock_directory());
2628 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2629 DEBUG(1, ("Could not create lock fd: %s\n",
2630 strerror(errno)));
2631 goto fail;
2635 child = fork();
2636 if (child == 0) {
2637 NTSTATUS status;
2639 close(listener_pipe[0]);
2640 set_blocking(listener_pipe[1], false);
2642 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2643 xconn->client->raw_ev_ctx,
2644 true);
2645 if (!NT_STATUS_IS_OK(status)) {
2646 DEBUG(1, ("reinit_after_fork failed: %s\n",
2647 nt_errstr(status)));
2648 exit(1);
2650 process_set_title("smbd-echo", "echo handler");
2651 initialize_password_db(true, xconn->client->raw_ev_ctx);
2652 smbd_echo_loop(xconn, listener_pipe[1]);
2653 exit(0);
2655 close(listener_pipe[1]);
2656 listener_pipe[1] = -1;
2657 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2659 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2662 * Without smb signing this is the same as the normal smbd
2663 * listener. This needs to change once signing comes in.
2665 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2666 xconn->client->raw_ev_ctx,
2667 xconn,
2668 xconn->smb1.echo_handler.trusted_fd,
2669 TEVENT_FD_READ,
2670 smbd_server_echo_handler,
2671 xconn);
2672 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2673 DEBUG(1, ("event_add_fd failed\n"));
2674 goto fail;
2677 return true;
2679 fail:
2680 if (listener_pipe[0] != -1) {
2681 close(listener_pipe[0]);
2683 if (listener_pipe[1] != -1) {
2684 close(listener_pipe[1]);
2686 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2687 close(xconn->smb1.echo_handler.socket_lock_fd);
2689 #ifdef HAVE_ROBUST_MUTEXES
2690 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2691 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2692 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2694 #endif
2695 smbd_echo_init(xconn);
2697 return false;
2700 bool req_is_in_chain(const struct smb_request *req)
2702 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2704 * We're right now handling a subsequent request, so we must
2705 * be in a chain
2707 return true;
2710 if (!smb1cli_is_andx_req(req->cmd)) {
2711 return false;
2714 if (req->wct < 2) {
2716 * Okay, an illegal request, but definitely not chained :-)
2718 return false;
2721 return (CVAL(req->vwv+0, 0) != 0xFF);