selftest/knownfail: move some parts to expectedfail.d/ntlm-auth
[Samba.git] / source3 / smbd / smb1_process.c
blobe4f6cdf457819f499bc320bda899a7cad2ff1d4a
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 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &buf_out);
243 if (!NT_STATUS_IS_OK(status)) {
244 DEBUG(0, ("send_smb: SMB encryption failed "
245 "on outgoing packet! Error %s\n",
246 nt_errstr(status) ));
247 ret = -1;
248 goto out;
252 len = smb_len_large(buf_out) + 4;
254 ret = write_data(xconn->transport.sock, buf_out, len);
255 if (ret <= 0) {
256 int saved_errno = errno;
258 * Try and give an error message saying what
259 * client failed.
261 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
262 (int)getpid(), (int)len,
263 smbXsrv_connection_dbg(xconn),
264 (int)ret, strerror(saved_errno)));
265 errno = saved_errno;
267 srv_free_enc_buffer(xconn, buf_out);
268 goto out;
271 srv_free_enc_buffer(xconn, buf_out);
272 out:
273 smbd_unlock_socket(xconn);
274 return (ret > 0);
277 /* Socket functions for smbd packet processing. */
279 static bool valid_packet_size(size_t len)
282 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
283 * of header. Don't print the error if this fits.... JRA.
286 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
287 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
288 (unsigned long)len));
289 return false;
291 return true;
294 /****************************************************************************
295 Attempt a zerocopy writeX read. We know here that len > smb_size-4
296 ****************************************************************************/
299 * Unfortunately, earlier versions of smbclient/libsmbclient
300 * don't send this "standard" writeX header. I've fixed this
301 * for 3.2 but we'll use the old method with earlier versions.
302 * Windows and CIFSFS at least use this standard size. Not
303 * sure about MacOSX.
306 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
307 (2*14) + /* word count (including bcc) */ \
308 1 /* pad byte */)
310 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
311 const char lenbuf[4],
312 struct smbXsrv_connection *xconn,
313 int sock,
314 char **buffer,
315 unsigned int timeout,
316 size_t *p_unread,
317 size_t *len_ret)
319 /* Size of a WRITEX call (+4 byte len). */
320 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
321 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
322 ssize_t toread;
323 NTSTATUS status;
325 memcpy(writeX_header, lenbuf, 4);
327 status = read_fd_with_timeout(
328 sock, writeX_header + 4,
329 STANDARD_WRITE_AND_X_HEADER_SIZE,
330 STANDARD_WRITE_AND_X_HEADER_SIZE,
331 timeout, NULL);
333 if (!NT_STATUS_IS_OK(status)) {
334 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
335 "error = %s.\n",
336 smbXsrv_connection_dbg(xconn),
337 nt_errstr(status)));
338 return status;
342 * Ok - now try and see if this is a possible
343 * valid writeX call.
346 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
348 * If the data offset is beyond what
349 * we've read, drain the extra bytes.
351 uint16_t doff = SVAL(writeX_header,smb_vwv11);
352 ssize_t newlen;
354 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
355 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
356 if (drain_socket(sock, drain) != drain) {
357 smb_panic("receive_smb_raw_talloc_partial_read:"
358 " failed to drain pending bytes");
360 } else {
361 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
364 /* Spoof down the length and null out the bcc. */
365 set_message_bcc(writeX_header, 0);
366 newlen = smb_len(writeX_header);
368 /* Copy the header we've written. */
370 *buffer = (char *)talloc_memdup(mem_ctx,
371 writeX_header,
372 sizeof(writeX_header));
374 if (*buffer == NULL) {
375 DEBUG(0, ("Could not allocate inbuf of length %d\n",
376 (int)sizeof(writeX_header)));
377 return NT_STATUS_NO_MEMORY;
380 /* Work out the remaining bytes. */
381 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
382 *len_ret = newlen + 4;
383 return NT_STATUS_OK;
386 if (!valid_packet_size(len)) {
387 return NT_STATUS_INVALID_PARAMETER;
391 * Not a valid writeX call. Just do the standard
392 * talloc and return.
395 *buffer = talloc_array(mem_ctx, char, len+4);
397 if (*buffer == NULL) {
398 DEBUG(0, ("Could not allocate inbuf of length %d\n",
399 (int)len+4));
400 return NT_STATUS_NO_MEMORY;
403 /* Copy in what we already read. */
404 memcpy(*buffer,
405 writeX_header,
406 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
407 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
409 if(toread > 0) {
410 status = read_packet_remainder(
411 sock,
412 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
413 timeout, toread);
415 if (!NT_STATUS_IS_OK(status)) {
416 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
417 nt_errstr(status)));
418 return status;
422 *len_ret = len + 4;
423 return NT_STATUS_OK;
426 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
427 struct smbXsrv_connection *xconn,
428 int sock,
429 char **buffer, unsigned int timeout,
430 size_t *p_unread, size_t *plen)
432 char lenbuf[4];
433 size_t len;
434 int min_recv_size = lp_min_receive_file_size();
435 NTSTATUS status;
437 *p_unread = 0;
439 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
440 &len);
441 if (!NT_STATUS_IS_OK(status)) {
442 return status;
445 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
446 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
447 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
448 !smb1_srv_is_signing_active(xconn) &&
449 xconn->smb1.echo_handler.trusted_fde == NULL) {
451 return receive_smb_raw_talloc_partial_read(
452 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
453 p_unread, plen);
456 if (!valid_packet_size(len)) {
457 return NT_STATUS_INVALID_PARAMETER;
461 * The +4 here can't wrap, we've checked the length above already.
464 *buffer = talloc_array(mem_ctx, char, len+4);
466 if (*buffer == NULL) {
467 DEBUG(0, ("Could not allocate inbuf of length %d\n",
468 (int)len+4));
469 return NT_STATUS_NO_MEMORY;
472 memcpy(*buffer, lenbuf, sizeof(lenbuf));
474 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
475 if (!NT_STATUS_IS_OK(status)) {
476 return status;
479 *plen = len + 4;
480 return NT_STATUS_OK;
483 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
484 struct smbXsrv_connection *xconn,
485 int sock,
486 char **buffer, unsigned int timeout,
487 size_t *p_unread, bool *p_encrypted,
488 size_t *p_len,
489 uint32_t *seqnum,
490 bool trusted_channel)
492 size_t len = 0;
493 NTSTATUS status;
495 *p_encrypted = false;
497 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
498 p_unread, &len);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
501 ("receive_smb_raw_talloc failed for client %s "
502 "read error = %s.\n",
503 smbXsrv_connection_dbg(xconn),
504 nt_errstr(status)) );
505 return status;
508 if (is_encrypted_packet((uint8_t *)*buffer)) {
509 status = srv_decrypt_buffer(xconn, *buffer);
510 if (!NT_STATUS_IS_OK(status)) {
511 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
512 "incoming packet! Error %s\n",
513 nt_errstr(status) ));
514 return status;
516 *p_encrypted = true;
519 /* Check the incoming SMB signature. */
520 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
521 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
522 "incoming packet!\n"));
523 return NT_STATUS_INVALID_NETWORK_RESPONSE;
526 *p_len = len;
527 return NT_STATUS_OK;
530 /****************************************************************************
531 Function to push a message onto the tail of a linked list of smb messages ready
532 for processing.
533 ****************************************************************************/
535 static bool push_queued_message(struct smb_request *req,
536 struct timeval request_time,
537 struct timeval end_time,
538 struct deferred_open_record *open_rec)
540 int msg_len = smb_len(req->inbuf) + 4;
541 struct pending_message_list *msg;
543 msg = talloc_zero(NULL, struct pending_message_list);
545 if(msg == NULL) {
546 DEBUG(0,("push_message: malloc fail (1)\n"));
547 return False;
549 msg->sconn = req->sconn;
550 msg->xconn = req->xconn;
552 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
553 if(msg->buf.data == NULL) {
554 DEBUG(0,("push_message: malloc fail (2)\n"));
555 TALLOC_FREE(msg);
556 return False;
559 msg->request_time = request_time;
560 msg->seqnum = req->seqnum;
561 msg->encrypted = req->encrypted;
562 msg->processed = false;
564 if (open_rec) {
565 msg->open_rec = talloc_move(msg, &open_rec);
568 #if 0
569 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
570 msg,
571 end_time,
572 smbd_deferred_open_timer,
573 msg);
574 if (!msg->te) {
575 DEBUG(0,("push_message: event_add_timed failed\n"));
576 TALLOC_FREE(msg);
577 return false;
579 #endif
581 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
583 DEBUG(10,("push_message: pushed message length %u on "
584 "deferred_open_queue\n", (unsigned int)msg_len));
586 return True;
589 /****************************************************************************
590 Function to push a deferred open smb message onto a linked list of local smb
591 messages ready for processing.
592 ****************************************************************************/
594 bool push_deferred_open_message_smb1(struct smb_request *req,
595 struct timeval timeout,
596 struct file_id id,
597 struct deferred_open_record *open_rec)
599 struct timeval_buf tvbuf;
600 struct timeval end_time;
602 if (req->unread_bytes) {
603 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
604 "unread_bytes = %u\n",
605 (unsigned int)req->unread_bytes ));
606 smb_panic("push_deferred_open_message_smb: "
607 "logic error unread_bytes != 0" );
610 end_time = timeval_sum(&req->request_time, &timeout);
612 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
613 (unsigned int) smb_len(req->inbuf)+4,
614 req->mid,
615 timeval_str_buf(&end_time, false, true, &tvbuf));
617 return push_queued_message(req, req->request_time, end_time, open_rec);
621 * Only allow 5 outstanding trans requests. We're allocating memory, so
622 * prevent a DoS.
625 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
627 int count = 0;
628 for (; list != NULL; list = list->next) {
630 if (list->mid == mid) {
631 return NT_STATUS_INVALID_PARAMETER;
634 count += 1;
636 if (count > 5) {
637 return NT_STATUS_INSUFFICIENT_RESOURCES;
640 return NT_STATUS_OK;
644 These flags determine some of the permissions required to do an operation
646 Note that I don't set NEED_WRITE on some write operations because they
647 are used by some brain-dead clients when printing, and I don't want to
648 force write permissions on print services.
650 #define AS_USER (1<<0)
651 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
652 #define TIME_INIT (1<<2)
653 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
654 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
655 #define DO_CHDIR (1<<6)
658 define a list of possible SMB messages and their corresponding
659 functions. Any message that has a NULL function is unimplemented -
660 please feel free to contribute implementations!
662 static const struct smb_message_struct {
663 const char *name;
664 void (*fn)(struct smb_request *req);
665 int flags;
666 } smb_messages[256] = {
668 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
669 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
670 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
671 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
672 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
673 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
674 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
675 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
676 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
677 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
678 /* 0x0a */ { "SMBread",reply_read,AS_USER},
679 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
680 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
681 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
682 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
683 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
684 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
685 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
686 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
687 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
688 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
689 /* 0x15 */ { NULL, NULL, 0 },
690 /* 0x16 */ { NULL, NULL, 0 },
691 /* 0x17 */ { NULL, NULL, 0 },
692 /* 0x18 */ { NULL, NULL, 0 },
693 /* 0x19 */ { NULL, NULL, 0 },
694 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
695 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
696 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
697 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
698 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
699 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
700 /* 0x20 */ { "SMBwritec", NULL,0},
701 /* 0x21 */ { NULL, NULL, 0 },
702 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
703 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
704 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
705 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
706 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
707 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
708 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
709 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
710 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
711 /* 0x2b */ { "SMBecho",reply_echo,0},
712 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
713 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
714 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
715 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
716 /* 0x30 */ { NULL, NULL, 0 },
717 /* 0x31 */ { NULL, NULL, 0 },
718 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
719 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
720 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
721 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
722 /* 0x36 */ { NULL, NULL, 0 },
723 /* 0x37 */ { NULL, NULL, 0 },
724 /* 0x38 */ { NULL, NULL, 0 },
725 /* 0x39 */ { NULL, NULL, 0 },
726 /* 0x3a */ { NULL, NULL, 0 },
727 /* 0x3b */ { NULL, NULL, 0 },
728 /* 0x3c */ { NULL, NULL, 0 },
729 /* 0x3d */ { NULL, NULL, 0 },
730 /* 0x3e */ { NULL, NULL, 0 },
731 /* 0x3f */ { NULL, NULL, 0 },
732 /* 0x40 */ { NULL, NULL, 0 },
733 /* 0x41 */ { NULL, NULL, 0 },
734 /* 0x42 */ { NULL, NULL, 0 },
735 /* 0x43 */ { NULL, NULL, 0 },
736 /* 0x44 */ { NULL, NULL, 0 },
737 /* 0x45 */ { NULL, NULL, 0 },
738 /* 0x46 */ { NULL, NULL, 0 },
739 /* 0x47 */ { NULL, NULL, 0 },
740 /* 0x48 */ { NULL, NULL, 0 },
741 /* 0x49 */ { NULL, NULL, 0 },
742 /* 0x4a */ { NULL, NULL, 0 },
743 /* 0x4b */ { NULL, NULL, 0 },
744 /* 0x4c */ { NULL, NULL, 0 },
745 /* 0x4d */ { NULL, NULL, 0 },
746 /* 0x4e */ { NULL, NULL, 0 },
747 /* 0x4f */ { NULL, NULL, 0 },
748 /* 0x50 */ { NULL, NULL, 0 },
749 /* 0x51 */ { NULL, NULL, 0 },
750 /* 0x52 */ { NULL, NULL, 0 },
751 /* 0x53 */ { NULL, NULL, 0 },
752 /* 0x54 */ { NULL, NULL, 0 },
753 /* 0x55 */ { NULL, NULL, 0 },
754 /* 0x56 */ { NULL, NULL, 0 },
755 /* 0x57 */ { NULL, NULL, 0 },
756 /* 0x58 */ { NULL, NULL, 0 },
757 /* 0x59 */ { NULL, NULL, 0 },
758 /* 0x5a */ { NULL, NULL, 0 },
759 /* 0x5b */ { NULL, NULL, 0 },
760 /* 0x5c */ { NULL, NULL, 0 },
761 /* 0x5d */ { NULL, NULL, 0 },
762 /* 0x5e */ { NULL, NULL, 0 },
763 /* 0x5f */ { NULL, NULL, 0 },
764 /* 0x60 */ { NULL, NULL, 0 },
765 /* 0x61 */ { NULL, NULL, 0 },
766 /* 0x62 */ { NULL, NULL, 0 },
767 /* 0x63 */ { NULL, NULL, 0 },
768 /* 0x64 */ { NULL, NULL, 0 },
769 /* 0x65 */ { NULL, NULL, 0 },
770 /* 0x66 */ { NULL, NULL, 0 },
771 /* 0x67 */ { NULL, NULL, 0 },
772 /* 0x68 */ { NULL, NULL, 0 },
773 /* 0x69 */ { NULL, NULL, 0 },
774 /* 0x6a */ { NULL, NULL, 0 },
775 /* 0x6b */ { NULL, NULL, 0 },
776 /* 0x6c */ { NULL, NULL, 0 },
777 /* 0x6d */ { NULL, NULL, 0 },
778 /* 0x6e */ { NULL, NULL, 0 },
779 /* 0x6f */ { NULL, NULL, 0 },
780 /* 0x70 */ { "SMBtcon",reply_tcon,0},
781 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
782 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
783 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
784 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
785 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
786 /* 0x76 */ { NULL, NULL, 0 },
787 /* 0x77 */ { NULL, NULL, 0 },
788 /* 0x78 */ { NULL, NULL, 0 },
789 /* 0x79 */ { NULL, NULL, 0 },
790 /* 0x7a */ { NULL, NULL, 0 },
791 /* 0x7b */ { NULL, NULL, 0 },
792 /* 0x7c */ { NULL, NULL, 0 },
793 /* 0x7d */ { NULL, NULL, 0 },
794 /* 0x7e */ { NULL, NULL, 0 },
795 /* 0x7f */ { NULL, NULL, 0 },
796 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
797 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
798 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
799 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
800 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
801 /* 0x85 */ { NULL, NULL, 0 },
802 /* 0x86 */ { NULL, NULL, 0 },
803 /* 0x87 */ { NULL, NULL, 0 },
804 /* 0x88 */ { NULL, NULL, 0 },
805 /* 0x89 */ { NULL, NULL, 0 },
806 /* 0x8a */ { NULL, NULL, 0 },
807 /* 0x8b */ { NULL, NULL, 0 },
808 /* 0x8c */ { NULL, NULL, 0 },
809 /* 0x8d */ { NULL, NULL, 0 },
810 /* 0x8e */ { NULL, NULL, 0 },
811 /* 0x8f */ { NULL, NULL, 0 },
812 /* 0x90 */ { NULL, NULL, 0 },
813 /* 0x91 */ { NULL, NULL, 0 },
814 /* 0x92 */ { NULL, NULL, 0 },
815 /* 0x93 */ { NULL, NULL, 0 },
816 /* 0x94 */ { NULL, NULL, 0 },
817 /* 0x95 */ { NULL, NULL, 0 },
818 /* 0x96 */ { NULL, NULL, 0 },
819 /* 0x97 */ { NULL, NULL, 0 },
820 /* 0x98 */ { NULL, NULL, 0 },
821 /* 0x99 */ { NULL, NULL, 0 },
822 /* 0x9a */ { NULL, NULL, 0 },
823 /* 0x9b */ { NULL, NULL, 0 },
824 /* 0x9c */ { NULL, NULL, 0 },
825 /* 0x9d */ { NULL, NULL, 0 },
826 /* 0x9e */ { NULL, NULL, 0 },
827 /* 0x9f */ { NULL, NULL, 0 },
828 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
829 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
830 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
831 /* 0xa3 */ { NULL, NULL, 0 },
832 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
833 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
834 /* 0xa6 */ { NULL, NULL, 0 },
835 /* 0xa7 */ { NULL, NULL, 0 },
836 /* 0xa8 */ { NULL, NULL, 0 },
837 /* 0xa9 */ { NULL, NULL, 0 },
838 /* 0xaa */ { NULL, NULL, 0 },
839 /* 0xab */ { NULL, NULL, 0 },
840 /* 0xac */ { NULL, NULL, 0 },
841 /* 0xad */ { NULL, NULL, 0 },
842 /* 0xae */ { NULL, NULL, 0 },
843 /* 0xaf */ { NULL, NULL, 0 },
844 /* 0xb0 */ { NULL, NULL, 0 },
845 /* 0xb1 */ { NULL, NULL, 0 },
846 /* 0xb2 */ { NULL, NULL, 0 },
847 /* 0xb3 */ { NULL, NULL, 0 },
848 /* 0xb4 */ { NULL, NULL, 0 },
849 /* 0xb5 */ { NULL, NULL, 0 },
850 /* 0xb6 */ { NULL, NULL, 0 },
851 /* 0xb7 */ { NULL, NULL, 0 },
852 /* 0xb8 */ { NULL, NULL, 0 },
853 /* 0xb9 */ { NULL, NULL, 0 },
854 /* 0xba */ { NULL, NULL, 0 },
855 /* 0xbb */ { NULL, NULL, 0 },
856 /* 0xbc */ { NULL, NULL, 0 },
857 /* 0xbd */ { NULL, NULL, 0 },
858 /* 0xbe */ { NULL, NULL, 0 },
859 /* 0xbf */ { NULL, NULL, 0 },
860 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
861 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
862 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
863 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
864 /* 0xc4 */ { NULL, NULL, 0 },
865 /* 0xc5 */ { NULL, NULL, 0 },
866 /* 0xc6 */ { NULL, NULL, 0 },
867 /* 0xc7 */ { NULL, NULL, 0 },
868 /* 0xc8 */ { NULL, NULL, 0 },
869 /* 0xc9 */ { NULL, NULL, 0 },
870 /* 0xca */ { NULL, NULL, 0 },
871 /* 0xcb */ { NULL, NULL, 0 },
872 /* 0xcc */ { NULL, NULL, 0 },
873 /* 0xcd */ { NULL, NULL, 0 },
874 /* 0xce */ { NULL, NULL, 0 },
875 /* 0xcf */ { NULL, NULL, 0 },
876 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
877 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
878 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
879 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
880 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
881 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
882 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
883 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
884 /* 0xd8 */ { NULL, NULL, 0 },
885 /* 0xd9 */ { NULL, NULL, 0 },
886 /* 0xda */ { NULL, NULL, 0 },
887 /* 0xdb */ { NULL, NULL, 0 },
888 /* 0xdc */ { NULL, NULL, 0 },
889 /* 0xdd */ { NULL, NULL, 0 },
890 /* 0xde */ { NULL, NULL, 0 },
891 /* 0xdf */ { NULL, NULL, 0 },
892 /* 0xe0 */ { NULL, NULL, 0 },
893 /* 0xe1 */ { NULL, NULL, 0 },
894 /* 0xe2 */ { NULL, NULL, 0 },
895 /* 0xe3 */ { NULL, NULL, 0 },
896 /* 0xe4 */ { NULL, NULL, 0 },
897 /* 0xe5 */ { NULL, NULL, 0 },
898 /* 0xe6 */ { NULL, NULL, 0 },
899 /* 0xe7 */ { NULL, NULL, 0 },
900 /* 0xe8 */ { NULL, NULL, 0 },
901 /* 0xe9 */ { NULL, NULL, 0 },
902 /* 0xea */ { NULL, NULL, 0 },
903 /* 0xeb */ { NULL, NULL, 0 },
904 /* 0xec */ { NULL, NULL, 0 },
905 /* 0xed */ { NULL, NULL, 0 },
906 /* 0xee */ { NULL, NULL, 0 },
907 /* 0xef */ { NULL, NULL, 0 },
908 /* 0xf0 */ { NULL, NULL, 0 },
909 /* 0xf1 */ { NULL, NULL, 0 },
910 /* 0xf2 */ { NULL, NULL, 0 },
911 /* 0xf3 */ { NULL, NULL, 0 },
912 /* 0xf4 */ { NULL, NULL, 0 },
913 /* 0xf5 */ { NULL, NULL, 0 },
914 /* 0xf6 */ { NULL, NULL, 0 },
915 /* 0xf7 */ { NULL, NULL, 0 },
916 /* 0xf8 */ { NULL, NULL, 0 },
917 /* 0xf9 */ { NULL, NULL, 0 },
918 /* 0xfa */ { NULL, NULL, 0 },
919 /* 0xfb */ { NULL, NULL, 0 },
920 /* 0xfc */ { NULL, NULL, 0 },
921 /* 0xfd */ { NULL, NULL, 0 },
922 /* 0xfe */ { NULL, NULL, 0 },
923 /* 0xff */ { NULL, NULL, 0 }
928 /*******************************************************************
929 Dump a packet to a file.
930 ********************************************************************/
932 static void smb_dump(const char *name, int type, const char *data)
934 size_t len;
935 int fd, i;
936 char *fname = NULL;
937 if (DEBUGLEVEL < 50) {
938 return;
941 len = smb_len_tcp(data)+4;
942 for (i=1;i<100;i++) {
943 fname = talloc_asprintf(talloc_tos(),
944 "/tmp/%s.%d.%s",
945 name,
947 type ? "req" : "resp");
948 if (fname == NULL) {
949 return;
951 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
952 if (fd != -1 || errno != EEXIST) break;
953 TALLOC_FREE(fname);
955 if (fd != -1) {
956 ssize_t ret = write(fd, data, len);
957 if (ret != len)
958 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
959 close(fd);
960 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
962 TALLOC_FREE(fname);
965 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
966 struct smb_request *req,
967 uint8_t type,
968 bool *update_session_globalp,
969 bool *update_tcon_globalp)
971 connection_struct *conn = req->conn;
972 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
973 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
974 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
975 bool update_session = false;
976 bool update_tcon = false;
978 if (req->encrypted) {
979 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
982 if (smb1_srv_is_signing_active(req->xconn)) {
983 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
984 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
986 * echo can be unsigned. Session setup except final
987 * session setup response too
989 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
992 update_session |= smbXsrv_set_crypto_flag(
993 &session->global->encryption_flags, encrypt_flag);
994 update_session |= smbXsrv_set_crypto_flag(
995 &session->global->signing_flags, sign_flag);
997 if (tcon) {
998 update_tcon |= smbXsrv_set_crypto_flag(
999 &tcon->global->encryption_flags, encrypt_flag);
1000 update_tcon |= smbXsrv_set_crypto_flag(
1001 &tcon->global->signing_flags, sign_flag);
1004 if (update_session) {
1005 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1008 *update_session_globalp = update_session;
1009 *update_tcon_globalp = update_tcon;
1010 return;
1013 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1015 int snum;
1016 enum remote_arch_types ra_type;
1018 SMB_ASSERT(conn != NULL);
1019 SMB_ASSERT(!conn->sconn->using_smb2);
1021 snum = SNUM(conn);
1024 * Obey the client case sensitivity requests - only for clients that
1025 * support it. */
1026 switch (lp_case_sensitive(snum)) {
1027 case Auto:
1029 * We need this ugliness due to DOS/Win9x clients that lie
1030 * about case insensitivity. */
1031 ra_type = get_remote_arch();
1032 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1034 * Client can't support per-packet case sensitive
1035 * pathnames. */
1036 conn->case_sensitive = false;
1037 } else {
1038 conn->case_sensitive =
1039 !(flags & FLAG_CASELESS_PATHNAMES);
1041 break;
1042 case True:
1043 conn->case_sensitive = true;
1044 break;
1045 default:
1046 conn->case_sensitive = false;
1047 break;
1051 /****************************************************************************
1052 Prepare everything for calling the actual request function, and potentially
1053 call the request function via the "new" interface.
1055 Return False if the "legacy" function needs to be called, everything is
1056 prepared.
1058 Return True if we're done.
1060 I know this API sucks, but it is the one with the least code change I could
1061 find.
1062 ****************************************************************************/
1064 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1066 const struct loadparm_substitution *lp_sub =
1067 loadparm_s3_global_substitution();
1068 int flags;
1069 uint64_t session_tag;
1070 connection_struct *conn = NULL;
1071 struct smbXsrv_connection *xconn = req->xconn;
1072 NTTIME now = timeval_to_nttime(&req->request_time);
1073 struct smbXsrv_session *session = NULL;
1074 NTSTATUS status;
1076 errno = 0;
1078 if (!xconn->smb1.negprot.done) {
1079 switch (type) {
1081 * Without a negprot the request must
1082 * either be a negprot, or one of the
1083 * evil old SMB mailslot messaging types.
1085 case SMBnegprot:
1086 case SMBsendstrt:
1087 case SMBsendend:
1088 case SMBsendtxt:
1089 break;
1090 default:
1091 exit_server_cleanly("The first request "
1092 "should be a negprot");
1096 if (smb_messages[type].fn == NULL) {
1097 DEBUG(0,("Unknown message type %d!\n",type));
1098 smb_dump("Unknown", 1, (const char *)req->inbuf);
1099 reply_unknown_new(req, type);
1100 return NULL;
1103 flags = smb_messages[type].flags;
1105 /* In share mode security we must ignore the vuid. */
1106 session_tag = req->vuid;
1107 conn = req->conn;
1109 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1110 (int)getpid(), (unsigned long)conn));
1112 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1114 /* Ensure this value is replaced in the incoming packet. */
1115 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1118 * Ensure the correct username is in current_user_info. This is a
1119 * really ugly bugfix for problems with multiple session_setup_and_X's
1120 * being done and allowing %U and %G substitutions to work correctly.
1121 * There is a reason this code is done here, don't move it unless you
1122 * know what you're doing... :-).
1123 * JRA.
1127 * lookup an existing session
1129 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1130 * here, the main check is still in change_to_user()
1132 status = smb1srv_session_lookup(xconn,
1133 session_tag,
1134 now,
1135 &session);
1136 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1137 switch (type) {
1138 case SMBsesssetupX:
1139 status = NT_STATUS_OK;
1140 break;
1141 default:
1142 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1143 (unsigned long long)session_tag,
1144 (unsigned long long)req->mid));
1145 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1146 return conn;
1150 if (session != NULL &&
1151 session->global->auth_session_info != NULL &&
1152 !(flags & AS_USER))
1155 * change_to_user() implies set_current_user_info()
1156 * and chdir_connect_service().
1158 * So we only call set_current_user_info if
1159 * we don't have AS_USER specified.
1161 set_current_user_info(
1162 session->global->auth_session_info->unix_info->sanitized_username,
1163 session->global->auth_session_info->unix_info->unix_name,
1164 session->global->auth_session_info->info->domain_name);
1167 /* Does this call need to be run as the connected user? */
1168 if (flags & AS_USER) {
1170 /* Does this call need a valid tree connection? */
1171 if (!conn) {
1173 * Amazingly, the error code depends on the command
1174 * (from Samba4).
1176 if (type == SMBntcreateX) {
1177 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1178 } else {
1179 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1181 return NULL;
1184 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1187 * change_to_user() implies set_current_user_info()
1188 * and chdir_connect_service().
1190 if (!change_to_user_and_service(conn,session_tag)) {
1191 DEBUG(0, ("Error: Could not change to user. Removing "
1192 "deferred open, mid=%llu.\n",
1193 (unsigned long long)req->mid));
1194 reply_force_doserror(req, ERRSRV, ERRbaduid);
1195 return conn;
1198 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1200 /* Does it need write permission? */
1201 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1202 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1203 return conn;
1206 /* IPC services are limited */
1207 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1208 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1209 return conn;
1211 } else if (flags & AS_GUEST) {
1213 * Does this protocol need to be run as guest? (Only archane
1214 * messenger service requests have this...)
1216 if (!change_to_guest()) {
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 return conn;
1220 } else {
1221 /* This call needs to be run as root */
1222 change_to_root_user();
1225 /* load service specific parameters */
1226 if (conn) {
1227 if (req->encrypted) {
1228 conn->encrypted_tid = true;
1229 /* encrypted required from now on. */
1230 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1231 } else if (ENCRYPTION_REQUIRED(conn)) {
1232 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1233 DEBUG(1,("service[%s] requires encryption"
1234 "%s ACCESS_DENIED. mid=%llu\n",
1235 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1236 smb_fn_name(type),
1237 (unsigned long long)req->mid));
1238 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1239 return conn;
1243 if (flags & DO_CHDIR) {
1244 bool ok;
1246 ok = chdir_current_service(conn);
1247 if (!ok) {
1248 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1249 return conn;
1252 conn->num_smb_operations++;
1256 * Update encryption and signing state tracking flags that are
1257 * used by smbstatus to display signing and encryption status.
1259 if (session != NULL) {
1260 bool update_session_global = false;
1261 bool update_tcon_global = false;
1263 req->session = session;
1265 smb1srv_update_crypto_flags(session, req, type,
1266 &update_session_global,
1267 &update_tcon_global);
1269 if (update_session_global) {
1270 status = smbXsrv_session_update(session);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1273 return conn;
1277 if (update_tcon_global) {
1278 status = smbXsrv_tcon_update(req->conn->tcon);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1281 return conn;
1286 smb_messages[type].fn(req);
1287 return req->conn;
1290 /****************************************************************************
1291 Construct a reply to the incoming packet.
1292 ****************************************************************************/
1294 void construct_reply(struct smbXsrv_connection *xconn,
1295 char *inbuf,
1296 int size,
1297 size_t unread_bytes,
1298 uint32_t seqnum,
1299 bool encrypted)
1301 struct smbd_server_connection *sconn = xconn->client->sconn;
1302 struct smb_request *req;
1304 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1305 smb_panic("could not allocate smb_request");
1308 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1309 encrypted, seqnum)) {
1310 exit_server_cleanly("Invalid SMB request");
1313 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1315 req->conn = switch_message(req->cmd, req);
1317 if (req->outbuf == NULL) {
1319 * Request has suspended itself, will come
1320 * back here.
1322 return;
1324 if (CVAL(req->outbuf,0) == 0) {
1325 show_msg((char *)req->outbuf);
1327 smb_request_done(req);
1330 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1331 char *inbuf,
1332 int size,
1333 uint32_t seqnum,
1334 bool encrypted)
1336 struct smb_request **reqs = NULL;
1337 struct smb_request *req;
1338 unsigned num_reqs;
1339 bool ok;
1341 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1342 seqnum, &reqs, &num_reqs);
1343 if (!ok) {
1344 char errbuf[smb_size];
1345 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1346 __LINE__, __FILE__);
1347 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
1348 exit_server_cleanly("construct_reply_chain: "
1349 "smb1_srv_send failed.");
1351 return;
1354 req = reqs[0];
1355 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1357 req->conn = switch_message(req->cmd, req);
1359 if (req->outbuf == NULL) {
1361 * Request has suspended itself, will come
1362 * back here.
1364 return;
1366 smb_request_done(req);
1370 * To be called from an async SMB handler that is potentially chained
1371 * when it is finished for shipping.
1374 void smb_request_done(struct smb_request *req)
1376 struct smb_request **reqs = NULL;
1377 struct smb_request *first_req;
1378 size_t i, num_reqs, next_index;
1379 NTSTATUS status;
1381 if (req->chain == NULL) {
1382 first_req = req;
1383 goto shipit;
1386 reqs = req->chain;
1387 num_reqs = talloc_array_length(reqs);
1389 for (i=0; i<num_reqs; i++) {
1390 if (reqs[i] == req) {
1391 break;
1394 if (i == num_reqs) {
1396 * Invalid chain, should not happen
1398 status = NT_STATUS_INTERNAL_ERROR;
1399 goto error;
1401 next_index = i+1;
1403 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1404 struct smb_request *next = reqs[next_index];
1405 struct smbXsrv_tcon *tcon;
1406 NTTIME now = timeval_to_nttime(&req->request_time);
1408 next->vuid = SVAL(req->outbuf, smb_uid);
1409 next->tid = SVAL(req->outbuf, smb_tid);
1410 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1411 now, &tcon);
1413 if (NT_STATUS_IS_OK(status)) {
1414 next->conn = tcon->compat;
1415 } else {
1416 next->conn = NULL;
1418 next->chain_fsp = req->chain_fsp;
1419 next->inbuf = req->inbuf;
1421 req = next;
1422 req->conn = switch_message(req->cmd, req);
1424 if (req->outbuf == NULL) {
1426 * Request has suspended itself, will come
1427 * back here.
1429 return;
1431 next_index += 1;
1434 first_req = reqs[0];
1436 for (i=1; i<next_index; i++) {
1437 bool ok;
1439 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1440 if (!ok) {
1441 status = NT_STATUS_INTERNAL_ERROR;
1442 goto error;
1446 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1447 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1450 * This scary statement intends to set the
1451 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1452 * to the value last_req->outbuf carries
1454 SSVAL(first_req->outbuf, smb_flg2,
1455 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1456 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1459 * Transfer the error codes from the subrequest to the main one
1461 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1462 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1464 _smb_setlen_large(
1465 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1467 shipit:
1468 if (!smb1_srv_send(first_req->xconn,
1469 (char *)first_req->outbuf,
1470 true,
1471 first_req->seqnum + 1,
1472 IS_CONN_ENCRYPTED(req->conn) ||
1473 first_req->encrypted)) {
1474 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1475 "failed.");
1477 TALLOC_FREE(req); /* non-chained case */
1478 TALLOC_FREE(reqs); /* chained case */
1479 return;
1481 error:
1483 char errbuf[smb_size];
1484 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1485 if (!smb1_srv_send(req->xconn,
1486 errbuf,
1487 true,
1488 req->seqnum + 1,
1489 req->encrypted)) {
1490 exit_server_cleanly("construct_reply_chain: "
1491 "smb1_srv_send failed.");
1494 TALLOC_FREE(req); /* non-chained case */
1495 TALLOC_FREE(reqs); /* chained case */
1498 /****************************************************************************
1499 Process an smb from the client
1500 ****************************************************************************/
1502 void process_smb1(struct smbXsrv_connection *xconn,
1503 uint8_t *inbuf,
1504 size_t nread,
1505 size_t unread_bytes,
1506 uint32_t seqnum,
1507 bool encrypted)
1509 struct smbd_server_connection *sconn = xconn->client->sconn;
1511 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1512 * so subtract 4 from it. */
1513 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1514 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1515 smb_len(inbuf)));
1517 /* special magic for immediate exit */
1518 if ((nread == 9) &&
1519 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1520 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1521 uint8_t exitcode = CVAL(inbuf, 8);
1522 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1523 (int)exitcode);
1524 exit(exitcode);
1527 exit_server_cleanly("Non-SMB packet");
1530 show_msg((char *)inbuf);
1532 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1533 construct_reply_chain(xconn,
1534 (char *)inbuf,
1535 nread,
1536 seqnum,
1537 encrypted);
1538 } else {
1539 construct_reply(xconn,
1540 (char *)inbuf,
1541 nread,
1542 unread_bytes,
1543 seqnum,
1544 encrypted);
1547 sconn->trans_num++;
1550 /****************************************************************************
1551 Return a string containing the function name of a SMB command.
1552 ****************************************************************************/
1554 const char *smb_fn_name(int type)
1556 const char *unknown_name = "SMBunknown";
1558 if (smb_messages[type].name == NULL)
1559 return(unknown_name);
1561 return(smb_messages[type].name);
1564 /****************************************************************************
1565 Helper functions for contruct_reply.
1566 ****************************************************************************/
1568 void add_to_common_flags2(uint32_t v)
1570 common_flags2 |= v;
1573 void remove_from_common_flags2(uint32_t v)
1575 common_flags2 &= ~v;
1579 * @brief Find the smb_cmd offset of the last command pushed
1580 * @param[in] buf The buffer we're building up
1581 * @retval Where can we put our next andx cmd?
1583 * While chaining requests, the "next" request we're looking at needs to put
1584 * its SMB_Command before the data the previous request already built up added
1585 * to the chain. Find the offset to the place where we have to put our cmd.
1588 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1590 uint8_t cmd;
1591 size_t ofs;
1593 cmd = CVAL(buf, smb_com);
1595 if (!smb1cli_is_andx_req(cmd)) {
1596 return false;
1599 ofs = smb_vwv0;
1601 while (CVAL(buf, ofs) != 0xff) {
1603 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1604 return false;
1608 * ofs is from start of smb header, so add the 4 length
1609 * bytes. The next cmd is right after the wct field.
1611 ofs = SVAL(buf, ofs+2) + 4 + 1;
1613 if (ofs+4 >= talloc_get_size(buf)) {
1614 return false;
1618 *pofs = ofs;
1619 return true;
1623 * @brief Do the smb chaining at a buffer level
1624 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1625 * @param[in] andx_buf Buffer to be appended
1628 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1630 uint8_t smb_command = CVAL(andx_buf, smb_com);
1631 uint8_t wct = CVAL(andx_buf, smb_wct);
1632 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1633 uint32_t num_bytes = smb_buflen(andx_buf);
1634 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1636 uint8_t *outbuf;
1637 size_t old_size, new_size;
1638 size_t ofs;
1639 size_t chain_padding = 0;
1640 size_t andx_cmd_ofs;
1643 old_size = talloc_get_size(*poutbuf);
1645 if ((old_size % 4) != 0) {
1647 * Align the wct field of subsequent requests to a 4-byte
1648 * boundary
1650 chain_padding = 4 - (old_size % 4);
1654 * After the old request comes the new wct field (1 byte), the vwv's
1655 * and the num_bytes field.
1658 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1659 new_size += num_bytes;
1661 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1662 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1663 (unsigned)new_size));
1664 return false;
1667 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1668 if (outbuf == NULL) {
1669 DEBUG(0, ("talloc failed\n"));
1670 return false;
1672 *poutbuf = outbuf;
1674 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1675 DEBUG(1, ("invalid command chain\n"));
1676 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1677 return false;
1680 if (chain_padding != 0) {
1681 memset(outbuf + old_size, 0, chain_padding);
1682 old_size += chain_padding;
1685 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1686 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1688 ofs = old_size;
1691 * Push the chained request:
1693 * wct field
1696 SCVAL(outbuf, ofs, wct);
1697 ofs += 1;
1700 * vwv array
1703 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1706 * HACK ALERT
1708 * Read&X has an offset into its data buffer at
1709 * vwv[6]. reply_read_andx has no idea anymore that it's
1710 * running from within a chain, so we have to fix up the
1711 * offset here.
1713 * Although it looks disgusting at this place, I want to keep
1714 * it here. The alternative would be to push knowledge about
1715 * the andx chain down into read&x again.
1718 if (smb_command == SMBreadX) {
1719 uint8_t *bytes_addr;
1721 if (wct < 7) {
1723 * Invalid read&x response
1725 return false;
1728 bytes_addr = outbuf + ofs /* vwv start */
1729 + sizeof(uint16_t) * wct /* vwv array */
1730 + sizeof(uint16_t) /* bcc */
1731 + 1; /* padding byte */
1733 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1734 bytes_addr - outbuf - 4);
1737 ofs += sizeof(uint16_t) * wct;
1740 * bcc (byte count)
1743 SSVAL(outbuf, ofs, num_bytes);
1744 ofs += sizeof(uint16_t);
1747 * The bytes field
1750 memcpy(outbuf + ofs, bytes, num_bytes);
1752 return true;
1755 bool smb1_is_chain(const uint8_t *buf)
1757 uint8_t cmd, wct, andx_cmd;
1759 cmd = CVAL(buf, smb_com);
1760 if (!smb1cli_is_andx_req(cmd)) {
1761 return false;
1763 wct = CVAL(buf, smb_wct);
1764 if (wct < 2) {
1765 return false;
1767 andx_cmd = CVAL(buf, smb_vwv);
1768 return (andx_cmd != 0xFF);
1771 bool smb1_walk_chain(const uint8_t *buf,
1772 bool (*fn)(uint8_t cmd,
1773 uint8_t wct, const uint16_t *vwv,
1774 uint16_t num_bytes, const uint8_t *bytes,
1775 void *private_data),
1776 void *private_data)
1778 size_t smblen = smb_len(buf);
1779 const char *smb_buf = smb_base(buf);
1780 uint8_t cmd, chain_cmd;
1781 uint8_t wct;
1782 const uint16_t *vwv;
1783 uint16_t num_bytes;
1784 const uint8_t *bytes;
1786 cmd = CVAL(buf, smb_com);
1787 wct = CVAL(buf, smb_wct);
1788 vwv = (const uint16_t *)(buf + smb_vwv);
1789 num_bytes = smb_buflen(buf);
1790 bytes = (const uint8_t *)smb_buf_const(buf);
1792 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1793 return false;
1796 if (!smb1cli_is_andx_req(cmd)) {
1797 return true;
1799 if (wct < 2) {
1800 return false;
1803 chain_cmd = CVAL(vwv, 0);
1805 while (chain_cmd != 0xff) {
1806 uint32_t chain_offset; /* uint32_t to avoid overflow */
1807 size_t length_needed;
1808 ptrdiff_t vwv_offset;
1810 chain_offset = SVAL(vwv+1, 0);
1813 * Check if the client tries to fool us. The chain
1814 * offset needs to point beyond the current request in
1815 * the chain, it needs to strictly grow. Otherwise we
1816 * might be tricked into an endless loop always
1817 * processing the same request over and over again. We
1818 * used to assume that vwv and the byte buffer array
1819 * in a chain are always attached, but OS/2 the
1820 * Write&X/Read&X chain puts the Read&X vwv array
1821 * right behind the Write&X vwv chain. The Write&X bcc
1822 * array is put behind the Read&X vwv array. So now we
1823 * check whether the chain offset points strictly
1824 * behind the previous vwv array. req->buf points
1825 * right after the vwv array of the previous
1826 * request. See
1827 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1828 * more information.
1831 vwv_offset = ((const char *)vwv - smb_buf);
1832 if (chain_offset <= vwv_offset) {
1833 return false;
1837 * Next check: Make sure the chain offset does not
1838 * point beyond the overall smb request length.
1841 length_needed = chain_offset+1; /* wct */
1842 if (length_needed > smblen) {
1843 return false;
1847 * Now comes the pointer magic. Goal here is to set up
1848 * vwv and buf correctly again. The chain offset (the
1849 * former vwv[1]) points at the new wct field.
1852 wct = CVAL(smb_buf, chain_offset);
1854 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1855 return false;
1859 * Next consistency check: Make the new vwv array fits
1860 * in the overall smb request.
1863 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1864 if (length_needed > smblen) {
1865 return false;
1867 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1870 * Now grab the new byte buffer....
1873 num_bytes = SVAL(vwv+wct, 0);
1876 * .. and check that it fits.
1879 length_needed += num_bytes;
1880 if (length_needed > smblen) {
1881 return false;
1883 bytes = (const uint8_t *)(vwv+wct+1);
1885 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1886 return false;
1889 if (!smb1cli_is_andx_req(chain_cmd)) {
1890 return true;
1892 chain_cmd = CVAL(vwv, 0);
1894 return true;
1897 static bool smb1_chain_length_cb(uint8_t cmd,
1898 uint8_t wct, const uint16_t *vwv,
1899 uint16_t num_bytes, const uint8_t *bytes,
1900 void *private_data)
1902 unsigned *count = (unsigned *)private_data;
1903 *count += 1;
1904 return true;
1907 unsigned smb1_chain_length(const uint8_t *buf)
1909 unsigned count = 0;
1911 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1912 return 0;
1914 return count;
1917 struct smb1_parse_chain_state {
1918 TALLOC_CTX *mem_ctx;
1919 const uint8_t *buf;
1920 struct smbd_server_connection *sconn;
1921 struct smbXsrv_connection *xconn;
1922 bool encrypted;
1923 uint32_t seqnum;
1925 struct smb_request **reqs;
1926 unsigned num_reqs;
1929 static bool smb1_parse_chain_cb(uint8_t cmd,
1930 uint8_t wct, const uint16_t *vwv,
1931 uint16_t num_bytes, const uint8_t *bytes,
1932 void *private_data)
1934 struct smb1_parse_chain_state *state =
1935 (struct smb1_parse_chain_state *)private_data;
1936 struct smb_request **reqs;
1937 struct smb_request *req;
1938 bool ok;
1940 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1941 struct smb_request *, state->num_reqs+1);
1942 if (reqs == NULL) {
1943 return false;
1945 state->reqs = reqs;
1947 req = talloc(reqs, struct smb_request);
1948 if (req == NULL) {
1949 return false;
1952 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1953 state->encrypted, state->seqnum);
1954 if (!ok) {
1955 return false;
1957 req->cmd = cmd;
1958 req->wct = wct;
1959 req->vwv = vwv;
1960 req->buflen = num_bytes;
1961 req->buf = bytes;
1963 reqs[state->num_reqs] = req;
1964 state->num_reqs += 1;
1965 return true;
1968 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1969 struct smbXsrv_connection *xconn,
1970 bool encrypted, uint32_t seqnum,
1971 struct smb_request ***reqs, unsigned *num_reqs)
1973 struct smbd_server_connection *sconn = NULL;
1974 struct smb1_parse_chain_state state;
1975 unsigned i;
1977 if (xconn != NULL) {
1978 sconn = xconn->client->sconn;
1981 state.mem_ctx = mem_ctx;
1982 state.buf = buf;
1983 state.sconn = sconn;
1984 state.xconn = xconn;
1985 state.encrypted = encrypted;
1986 state.seqnum = seqnum;
1987 state.reqs = NULL;
1988 state.num_reqs = 0;
1990 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1991 TALLOC_FREE(state.reqs);
1992 return false;
1994 for (i=0; i<state.num_reqs; i++) {
1995 state.reqs[i]->chain = state.reqs;
1997 *reqs = state.reqs;
1998 *num_reqs = state.num_reqs;
1999 return true;
2002 static bool fd_is_readable(int fd)
2004 int ret, revents;
2006 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2008 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2012 static void smbd_server_connection_write_handler(
2013 struct smbXsrv_connection *xconn)
2015 /* TODO: make write nonblocking */
2018 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2019 int fd)
2021 uint8_t *inbuf = NULL;
2022 size_t inbuf_len = 0;
2023 size_t unread_bytes = 0;
2024 bool encrypted = false;
2025 TALLOC_CTX *mem_ctx = talloc_tos();
2026 NTSTATUS status;
2027 uint32_t seqnum;
2029 bool async_echo = lp_async_smb_echo_handler();
2030 bool from_client = false;
2032 if (async_echo) {
2033 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
2035 * This is the super-ugly hack to prefer the packets
2036 * forwarded by the echo handler over the ones by the
2037 * client directly
2039 fd = xconn->smb1.echo_handler.trusted_fd;
2043 from_client = (xconn->transport.sock == fd);
2045 if (async_echo && from_client) {
2046 smbd_lock_socket(xconn);
2048 if (!fd_is_readable(fd)) {
2049 DEBUG(10,("the echo listener was faster\n"));
2050 smbd_unlock_socket(xconn);
2051 return;
2055 /* TODO: make this completely nonblocking */
2056 status = receive_smb_talloc(mem_ctx, xconn, fd,
2057 (char **)(void *)&inbuf,
2058 0, /* timeout */
2059 &unread_bytes,
2060 &encrypted,
2061 &inbuf_len, &seqnum,
2062 !from_client /* trusted channel */);
2064 if (async_echo && from_client) {
2065 smbd_unlock_socket(xconn);
2068 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2069 goto process;
2071 if (NT_STATUS_IS_ERR(status)) {
2072 exit_server_cleanly("failed to receive smb request");
2074 if (!NT_STATUS_IS_OK(status)) {
2075 return;
2078 process:
2079 process_smb(xconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted);
2082 static void smbd_server_echo_handler(struct tevent_context *ev,
2083 struct tevent_fd *fde,
2084 uint16_t flags,
2085 void *private_data)
2087 struct smbXsrv_connection *xconn =
2088 talloc_get_type_abort(private_data,
2089 struct smbXsrv_connection);
2091 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2093 * we're not supposed to do any io
2095 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2096 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2097 return;
2100 if (flags & TEVENT_FD_WRITE) {
2101 smbd_server_connection_write_handler(xconn);
2102 return;
2104 if (flags & TEVENT_FD_READ) {
2105 smbd_smb1_server_connection_read_handler(
2106 xconn, xconn->smb1.echo_handler.trusted_fd);
2107 return;
2112 * Send keepalive packets to our client
2114 bool keepalive_fn(const struct timeval *now, void *private_data)
2116 struct smbd_server_connection *sconn = talloc_get_type_abort(
2117 private_data, struct smbd_server_connection);
2118 struct smbXsrv_connection *xconn = NULL;
2119 bool ret;
2121 if (sconn->using_smb2) {
2122 /* Don't do keepalives on an SMB2 connection. */
2123 return false;
2127 * With SMB1 we only have 1 connection
2129 xconn = sconn->client->connections;
2130 smbd_lock_socket(xconn);
2131 ret = send_keepalive(xconn->transport.sock);
2132 smbd_unlock_socket(xconn);
2134 if (!ret) {
2135 int saved_errno = errno;
2137 * Try and give an error message saying what
2138 * client failed.
2140 DEBUG(0, ("send_keepalive failed for client %s. "
2141 "Error %s - exiting\n",
2142 smbXsrv_connection_dbg(xconn),
2143 strerror(saved_errno)));
2144 errno = saved_errno;
2145 return False;
2147 return True;
2151 * Read an smb packet in the echo handler child, giving the parent
2152 * smbd one second to react once the socket becomes readable.
2155 struct smbd_echo_read_state {
2156 struct tevent_context *ev;
2157 struct smbXsrv_connection *xconn;
2159 char *buf;
2160 size_t buflen;
2161 uint32_t seqnum;
2164 static void smbd_echo_read_readable(struct tevent_req *subreq);
2165 static void smbd_echo_read_waited(struct tevent_req *subreq);
2167 static struct tevent_req *smbd_echo_read_send(
2168 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2169 struct smbXsrv_connection *xconn)
2171 struct tevent_req *req, *subreq;
2172 struct smbd_echo_read_state *state;
2174 req = tevent_req_create(mem_ctx, &state,
2175 struct smbd_echo_read_state);
2176 if (req == NULL) {
2177 return NULL;
2179 state->ev = ev;
2180 state->xconn = xconn;
2182 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2183 if (tevent_req_nomem(subreq, req)) {
2184 return tevent_req_post(req, ev);
2186 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2187 return req;
2190 static void smbd_echo_read_readable(struct tevent_req *subreq)
2192 struct tevent_req *req = tevent_req_callback_data(
2193 subreq, struct tevent_req);
2194 struct smbd_echo_read_state *state = tevent_req_data(
2195 req, struct smbd_echo_read_state);
2196 bool ok;
2197 int err;
2199 ok = wait_for_read_recv(subreq, &err);
2200 TALLOC_FREE(subreq);
2201 if (!ok) {
2202 tevent_req_nterror(req, map_nt_error_from_unix(err));
2203 return;
2207 * Give the parent smbd one second to step in
2210 subreq = tevent_wakeup_send(
2211 state, state->ev, timeval_current_ofs(1, 0));
2212 if (tevent_req_nomem(subreq, req)) {
2213 return;
2215 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2218 static void smbd_echo_read_waited(struct tevent_req *subreq)
2220 struct tevent_req *req = tevent_req_callback_data(
2221 subreq, struct tevent_req);
2222 struct smbd_echo_read_state *state = tevent_req_data(
2223 req, struct smbd_echo_read_state);
2224 struct smbXsrv_connection *xconn = state->xconn;
2225 bool ok;
2226 NTSTATUS status;
2227 size_t unread = 0;
2228 bool encrypted;
2230 ok = tevent_wakeup_recv(subreq);
2231 TALLOC_FREE(subreq);
2232 if (!ok) {
2233 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2234 return;
2237 ok = smbd_lock_socket_internal(xconn);
2238 if (!ok) {
2239 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2240 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2241 return;
2244 if (!fd_is_readable(xconn->transport.sock)) {
2245 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2246 (int)getpid()));
2248 ok = smbd_unlock_socket_internal(xconn);
2249 if (!ok) {
2250 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2251 DEBUG(1, ("%s: failed to unlock socket\n",
2252 __location__));
2253 return;
2256 subreq = wait_for_read_send(state, state->ev,
2257 xconn->transport.sock, false);
2258 if (tevent_req_nomem(subreq, req)) {
2259 return;
2261 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2262 return;
2265 status = receive_smb_talloc(state, xconn,
2266 xconn->transport.sock,
2267 &state->buf,
2268 0 /* timeout */,
2269 &unread,
2270 &encrypted,
2271 &state->buflen,
2272 &state->seqnum,
2273 false /* trusted_channel*/);
2275 if (tevent_req_nterror(req, status)) {
2276 tevent_req_nterror(req, status);
2277 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2278 (int)getpid(), nt_errstr(status)));
2279 return;
2282 ok = smbd_unlock_socket_internal(xconn);
2283 if (!ok) {
2284 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2285 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2286 return;
2288 tevent_req_done(req);
2291 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2292 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2294 struct smbd_echo_read_state *state = tevent_req_data(
2295 req, struct smbd_echo_read_state);
2296 NTSTATUS status;
2298 if (tevent_req_is_nterror(req, &status)) {
2299 return status;
2301 *pbuf = talloc_move(mem_ctx, &state->buf);
2302 *pbuflen = state->buflen;
2303 *pseqnum = state->seqnum;
2304 return NT_STATUS_OK;
2307 struct smbd_echo_state {
2308 struct tevent_context *ev;
2309 struct iovec *pending;
2310 struct smbd_server_connection *sconn;
2311 struct smbXsrv_connection *xconn;
2312 int parent_pipe;
2314 struct tevent_fd *parent_fde;
2316 struct tevent_req *write_req;
2319 static void smbd_echo_writer_done(struct tevent_req *req);
2321 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2323 int num_pending;
2325 if (state->write_req != NULL) {
2326 return;
2329 num_pending = talloc_array_length(state->pending);
2330 if (num_pending == 0) {
2331 return;
2334 state->write_req = writev_send(state, state->ev, NULL,
2335 state->parent_pipe, false,
2336 state->pending, num_pending);
2337 if (state->write_req == NULL) {
2338 DEBUG(1, ("writev_send failed\n"));
2339 exit(1);
2342 talloc_steal(state->write_req, state->pending);
2343 state->pending = NULL;
2345 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2346 state);
2349 static void smbd_echo_writer_done(struct tevent_req *req)
2351 struct smbd_echo_state *state = tevent_req_callback_data(
2352 req, struct smbd_echo_state);
2353 ssize_t written;
2354 int err;
2356 written = writev_recv(req, &err);
2357 TALLOC_FREE(req);
2358 state->write_req = NULL;
2359 if (written == -1) {
2360 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2361 exit(1);
2363 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2364 smbd_echo_activate_writer(state);
2367 static bool smbd_echo_reply(struct smbd_echo_state *state,
2368 uint8_t *inbuf, size_t inbuf_len,
2369 uint32_t seqnum)
2371 struct smb_request req;
2372 uint16_t num_replies;
2373 char *outbuf;
2374 bool ok;
2376 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2377 DEBUG(10, ("Got netbios keepalive\n"));
2379 * Just swallow it
2381 return true;
2384 if (inbuf_len < smb_size) {
2385 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2386 return false;
2388 if (!valid_smb1_header(inbuf)) {
2389 DEBUG(10, ("Got invalid SMB header\n"));
2390 return false;
2393 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2394 seqnum)) {
2395 return false;
2397 req.inbuf = inbuf;
2399 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2400 smb_fn_name(req.cmd)));
2402 if (req.cmd != SMBecho) {
2403 return false;
2405 if (req.wct < 1) {
2406 return false;
2409 num_replies = SVAL(req.vwv+0, 0);
2410 if (num_replies != 1) {
2411 /* Not a Windows "Hey, you're still there?" request */
2412 return false;
2415 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2416 1, req.buflen)) {
2417 DEBUG(10, ("create_smb1_outbuf failed\n"));
2418 return false;
2420 req.outbuf = (uint8_t *)outbuf;
2422 SSVAL(req.outbuf, smb_vwv0, num_replies);
2424 if (req.buflen > 0) {
2425 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2428 ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
2429 TALLOC_FREE(outbuf);
2430 if (!ok) {
2431 exit(1);
2434 return true;
2437 static void smbd_echo_exit(struct tevent_context *ev,
2438 struct tevent_fd *fde, uint16_t flags,
2439 void *private_data)
2441 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2442 exit(0);
2445 static void smbd_echo_got_packet(struct tevent_req *req);
2447 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2448 int parent_pipe)
2450 struct smbd_echo_state *state;
2451 struct tevent_req *read_req;
2453 state = talloc_zero(xconn, struct smbd_echo_state);
2454 if (state == NULL) {
2455 DEBUG(1, ("talloc failed\n"));
2456 return;
2458 state->xconn = xconn;
2459 state->parent_pipe = parent_pipe;
2460 state->ev = samba_tevent_context_init(state);
2461 if (state->ev == NULL) {
2462 DEBUG(1, ("samba_tevent_context_init failed\n"));
2463 TALLOC_FREE(state);
2464 return;
2466 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2467 TEVENT_FD_READ, smbd_echo_exit,
2468 state);
2469 if (state->parent_fde == NULL) {
2470 DEBUG(1, ("tevent_add_fd failed\n"));
2471 TALLOC_FREE(state);
2472 return;
2475 read_req = smbd_echo_read_send(state, state->ev, xconn);
2476 if (read_req == NULL) {
2477 DEBUG(1, ("smbd_echo_read_send failed\n"));
2478 TALLOC_FREE(state);
2479 return;
2481 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2483 while (true) {
2484 if (tevent_loop_once(state->ev) == -1) {
2485 DEBUG(1, ("tevent_loop_once failed: %s\n",
2486 strerror(errno)));
2487 break;
2490 TALLOC_FREE(state);
2493 static void smbd_echo_got_packet(struct tevent_req *req)
2495 struct smbd_echo_state *state = tevent_req_callback_data(
2496 req, struct smbd_echo_state);
2497 NTSTATUS status;
2498 char *buf = NULL;
2499 size_t buflen = 0;
2500 uint32_t seqnum = 0;
2501 bool reply;
2503 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2504 TALLOC_FREE(req);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2507 nt_errstr(status)));
2508 exit(1);
2511 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2512 if (!reply) {
2513 size_t num_pending;
2514 struct iovec *tmp;
2515 struct iovec *iov;
2517 num_pending = talloc_array_length(state->pending);
2518 tmp = talloc_realloc(state, state->pending, struct iovec,
2519 num_pending+1);
2520 if (tmp == NULL) {
2521 DEBUG(1, ("talloc_realloc failed\n"));
2522 exit(1);
2524 state->pending = tmp;
2526 if (buflen >= smb_size) {
2528 * place the seqnum in the packet so that the main process
2529 * can reply with signing
2531 SIVAL(buf, smb_ss_field, seqnum);
2532 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2535 iov = &state->pending[num_pending];
2536 iov->iov_base = talloc_move(state->pending, &buf);
2537 iov->iov_len = buflen;
2539 DEBUG(10,("echo_handler[%d]: forward to main\n",
2540 (int)getpid()));
2541 smbd_echo_activate_writer(state);
2544 req = smbd_echo_read_send(state, state->ev, state->xconn);
2545 if (req == NULL) {
2546 DEBUG(1, ("smbd_echo_read_send failed\n"));
2547 exit(1);
2549 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2554 * Handle SMBecho requests in a forked child process
2556 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2558 int listener_pipe[2];
2559 int res;
2560 pid_t child;
2561 bool use_mutex = false;
2563 res = pipe(listener_pipe);
2564 if (res == -1) {
2565 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2566 return false;
2569 #ifdef HAVE_ROBUST_MUTEXES
2570 use_mutex = tdb_runtime_check_for_robust_mutexes();
2572 if (use_mutex) {
2573 pthread_mutexattr_t a;
2575 xconn->smb1.echo_handler.socket_mutex =
2576 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2577 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2578 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2579 strerror(errno)));
2580 goto fail;
2583 res = pthread_mutexattr_init(&a);
2584 if (res != 0) {
2585 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2586 strerror(res)));
2587 goto fail;
2589 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2590 if (res != 0) {
2591 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2592 strerror(res)));
2593 pthread_mutexattr_destroy(&a);
2594 goto fail;
2596 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2597 if (res != 0) {
2598 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2599 strerror(res)));
2600 pthread_mutexattr_destroy(&a);
2601 goto fail;
2603 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2604 if (res != 0) {
2605 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2606 "%s\n", strerror(res)));
2607 pthread_mutexattr_destroy(&a);
2608 goto fail;
2610 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2611 &a);
2612 pthread_mutexattr_destroy(&a);
2613 if (res != 0) {
2614 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2615 strerror(res)));
2616 goto fail;
2619 #endif
2621 if (!use_mutex) {
2622 xconn->smb1.echo_handler.socket_lock_fd =
2623 create_unlink_tmp(lp_lock_directory());
2624 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2625 DEBUG(1, ("Could not create lock fd: %s\n",
2626 strerror(errno)));
2627 goto fail;
2631 child = fork();
2632 if (child == 0) {
2633 NTSTATUS status;
2635 close(listener_pipe[0]);
2636 set_blocking(listener_pipe[1], false);
2638 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2639 xconn->client->raw_ev_ctx,
2640 true);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 DEBUG(1, ("reinit_after_fork failed: %s\n",
2643 nt_errstr(status)));
2644 exit(1);
2646 process_set_title("smbd-echo", "echo handler");
2647 initialize_password_db(true, xconn->client->raw_ev_ctx);
2648 smbd_echo_loop(xconn, listener_pipe[1]);
2649 exit(0);
2651 close(listener_pipe[1]);
2652 listener_pipe[1] = -1;
2653 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2655 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2658 * Without smb signing this is the same as the normal smbd
2659 * listener. This needs to change once signing comes in.
2661 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2662 xconn->client->raw_ev_ctx,
2663 xconn,
2664 xconn->smb1.echo_handler.trusted_fd,
2665 TEVENT_FD_READ,
2666 smbd_server_echo_handler,
2667 xconn);
2668 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2669 DEBUG(1, ("event_add_fd failed\n"));
2670 goto fail;
2673 return true;
2675 fail:
2676 if (listener_pipe[0] != -1) {
2677 close(listener_pipe[0]);
2679 if (listener_pipe[1] != -1) {
2680 close(listener_pipe[1]);
2682 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2683 close(xconn->smb1.echo_handler.socket_lock_fd);
2685 #ifdef HAVE_ROBUST_MUTEXES
2686 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2687 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2688 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2690 #endif
2691 smbd_echo_init(xconn);
2693 return false;
2696 bool req_is_in_chain(const struct smb_request *req)
2698 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2700 * We're right now handling a subsequent request, so we must
2701 * be in a chain
2703 return true;
2706 if (!smb1cli_is_andx_req(req->cmd)) {
2707 return false;
2710 if (req->wct < 2) {
2712 * Okay, an illegal request, but definitely not chained :-)
2714 return false;
2717 return (CVAL(req->vwv+0, 0) != 0xFF);