s3:utils: Fix 'Usage:' for 'net ads enctypes'
[samba4-gss.git] / source3 / smbd / smb1_process.c
bloba1970b9e252a46281cb361d1235bab4edb2f5d5c
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "../lib/tsocket/tsocket.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "source3/smbd/smbXsrv_session.h"
27 #include "smbd/smbXsrv_open.h"
28 #include "librpc/gen_ndr/netlogon.h"
29 #include "../lib/async_req/async_sock.h"
30 #include "ctdbd_conn.h"
31 #include "../lib/util/select.h"
32 #include "printing/queue_process.h"
33 #include "system/select.h"
34 #include "passdb.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "lib/messages_ctdb.h"
38 #include "smbprofile.h"
39 #include "rpc_server/spoolss/srv_spoolss_nt.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "../libcli/security/dom_sid.h"
42 #include "../libcli/security/security_token.h"
43 #include "lib/id_cache.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "system/threads.h"
46 #include "lib/pthreadpool/pthreadpool_tevent.h"
47 #include "util_event.h"
48 #include "libcli/smb/smbXcli_base.h"
49 #include "lib/util/time_basic.h"
50 #include "source3/lib/substitute.h"
51 #include "lib/util/util_process.h"
53 /* Internal message queue for deferred opens. */
54 struct pending_message_list {
55 struct pending_message_list *next, *prev;
56 struct timeval request_time; /* When was this first issued? */
57 struct smbd_server_connection *sconn;
58 struct smbXsrv_connection *xconn;
59 struct tevent_timer *te;
60 uint32_t seqnum;
61 bool encrypted;
62 bool processed;
63 DATA_BLOB buf;
64 struct deferred_open_record *open_rec;
67 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
69 void smbd_echo_init(struct smbXsrv_connection *xconn)
71 xconn->smb1.echo_handler.trusted_fd = -1;
72 xconn->smb1.echo_handler.socket_lock_fd = -1;
73 #ifdef HAVE_ROBUST_MUTEXES
74 xconn->smb1.echo_handler.socket_mutex = NULL;
75 #endif
78 static bool smbd_echo_active(struct smbXsrv_connection *xconn)
80 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
81 return true;
84 #ifdef HAVE_ROBUST_MUTEXES
85 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
86 return true;
88 #endif
90 return false;
93 static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
95 if (!smbd_echo_active(xconn)) {
96 return true;
99 xconn->smb1.echo_handler.ref_count++;
101 if (xconn->smb1.echo_handler.ref_count > 1) {
102 return true;
105 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
107 #ifdef HAVE_ROBUST_MUTEXES
108 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
109 int ret = EINTR;
111 while (ret == EINTR) {
112 ret = pthread_mutex_lock(
113 xconn->smb1.echo_handler.socket_mutex);
114 if (ret == 0) {
115 break;
118 if (ret != 0) {
119 DEBUG(1, ("pthread_mutex_lock failed: %s\n",
120 strerror(ret)));
121 return false;
124 #endif
126 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
127 bool ok;
129 do {
130 ok = fcntl_lock(
131 xconn->smb1.echo_handler.socket_lock_fd,
132 F_SETLKW, 0, 0, F_WRLCK);
133 } while (!ok && (errno == EINTR));
135 if (!ok) {
136 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
137 return false;
141 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
143 return true;
146 void smbd_lock_socket(struct smbXsrv_connection *xconn)
148 if (!smbd_lock_socket_internal(xconn)) {
149 exit_server_cleanly("failed to lock socket");
153 static bool smbd_unlock_socket_internal(struct smbXsrv_connection *xconn)
155 if (!smbd_echo_active(xconn)) {
156 return true;
159 xconn->smb1.echo_handler.ref_count--;
161 if (xconn->smb1.echo_handler.ref_count > 0) {
162 return true;
165 #ifdef HAVE_ROBUST_MUTEXES
166 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
167 int ret;
168 ret = pthread_mutex_unlock(
169 xconn->smb1.echo_handler.socket_mutex);
170 if (ret != 0) {
171 DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
172 strerror(ret)));
173 return false;
176 #endif
178 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
179 bool ok;
181 do {
182 ok = fcntl_lock(
183 xconn->smb1.echo_handler.socket_lock_fd,
184 F_SETLKW, 0, 0, F_UNLCK);
185 } while (!ok && (errno == EINTR));
187 if (!ok) {
188 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
189 return false;
193 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
195 return true;
198 void smbd_unlock_socket(struct smbXsrv_connection *xconn)
200 if (!smbd_unlock_socket_internal(xconn)) {
201 exit_server_cleanly("failed to unlock socket");
205 /* Accessor function for smb_read_error for smbd functions. */
207 /****************************************************************************
208 Send an smb to a fd.
209 ****************************************************************************/
211 bool smb1_srv_send(struct smbXsrv_connection *xconn,
212 char *buffer,
213 bool do_signing,
214 uint32_t seqnum,
215 bool do_encrypt)
217 size_t len = 0;
218 ssize_t ret;
219 char *buf_out = buffer;
220 char *encrypted_buf = NULL;
222 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
224 * we're not supposed to do any io
226 return true;
229 smbd_lock_socket(xconn);
231 if (do_signing) {
232 NTSTATUS status;
234 /* Sign the outgoing packet if required. */
235 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
236 if (!NT_STATUS_IS_OK(status)) {
237 DBG_ERR("Failed to calculate signing mac: %s\n",
238 nt_errstr(status));
239 return false;
243 if (do_encrypt) {
244 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &encrypted_buf);
245 if (!NT_STATUS_IS_OK(status)) {
246 DEBUG(0, ("send_smb: SMB encryption failed "
247 "on outgoing packet! Error %s\n",
248 nt_errstr(status) ));
249 ret = -1;
250 goto out;
252 buf_out = encrypted_buf;
255 len = smb_len_large(buf_out) + 4;
257 ret = write_data(xconn->transport.sock, buf_out, len);
258 srv_free_enc_buffer(xconn, encrypted_buf);
259 if (ret <= 0) {
260 int saved_errno = errno;
262 * Try and give an error message saying what
263 * client failed.
265 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
266 (int)getpid(), (int)len,
267 smbXsrv_connection_dbg(xconn),
268 (int)ret, strerror(saved_errno)));
269 errno = saved_errno;
271 goto out;
274 out:
275 smbd_unlock_socket(xconn);
276 return (ret > 0);
279 /* Socket functions for smbd packet processing. */
281 static bool valid_packet_size(size_t len)
284 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
285 * of header. Don't print the error if this fits.... JRA.
288 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
289 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
290 (unsigned long)len));
291 return false;
293 return true;
296 /****************************************************************************
297 Attempt a zerocopy writeX read. We know here that len > smb_size-4
298 ****************************************************************************/
301 * Unfortunately, earlier versions of smbclient/libsmbclient
302 * don't send this "standard" writeX header. I've fixed this
303 * for 3.2 but we'll use the old method with earlier versions.
304 * Windows and CIFSFS at least use this standard size. Not
305 * sure about MacOSX.
308 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
309 (2*14) + /* word count (including bcc) */ \
310 1 /* pad byte */)
312 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
313 const char lenbuf[4],
314 struct smbXsrv_connection *xconn,
315 int sock,
316 char **buffer,
317 unsigned int timeout,
318 size_t *p_unread,
319 size_t *len_ret)
321 /* Size of a WRITEX call (+4 byte len). */
322 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
323 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
324 ssize_t toread;
325 NTSTATUS status;
327 memcpy(writeX_header, lenbuf, 4);
329 status = read_fd_with_timeout(
330 sock, writeX_header + 4,
331 STANDARD_WRITE_AND_X_HEADER_SIZE,
332 STANDARD_WRITE_AND_X_HEADER_SIZE,
333 timeout, NULL);
335 if (!NT_STATUS_IS_OK(status)) {
336 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
337 "error = %s.\n",
338 smbXsrv_connection_dbg(xconn),
339 nt_errstr(status)));
340 return status;
344 * Ok - now try and see if this is a possible
345 * valid writeX call.
348 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
350 * If the data offset is beyond what
351 * we've read, drain the extra bytes.
353 uint16_t doff = SVAL(writeX_header,smb_vwv11);
354 ssize_t newlen;
356 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
357 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
358 if (drain_socket(sock, drain) != drain) {
359 smb_panic("receive_smb_raw_talloc_partial_read:"
360 " failed to drain pending bytes");
362 } else {
363 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
366 /* Spoof down the length and null out the bcc. */
367 set_message_bcc(writeX_header, 0);
368 newlen = smb_len(writeX_header);
370 /* Copy the header we've written. */
372 *buffer = (char *)talloc_memdup(mem_ctx,
373 writeX_header,
374 sizeof(writeX_header));
376 if (*buffer == NULL) {
377 DEBUG(0, ("Could not allocate inbuf of length %d\n",
378 (int)sizeof(writeX_header)));
379 return NT_STATUS_NO_MEMORY;
382 /* Work out the remaining bytes. */
383 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
384 *len_ret = newlen + 4;
385 return NT_STATUS_OK;
388 if (!valid_packet_size(len)) {
389 return NT_STATUS_INVALID_PARAMETER;
393 * Not a valid writeX call. Just do the standard
394 * talloc and return.
397 *buffer = talloc_array(mem_ctx, char, len+4);
399 if (*buffer == NULL) {
400 DEBUG(0, ("Could not allocate inbuf of length %d\n",
401 (int)len+4));
402 return NT_STATUS_NO_MEMORY;
405 /* Copy in what we already read. */
406 memcpy(*buffer,
407 writeX_header,
408 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
409 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
411 if(toread > 0) {
412 status = read_packet_remainder(
413 sock,
414 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
415 timeout, toread);
417 if (!NT_STATUS_IS_OK(status)) {
418 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
419 nt_errstr(status)));
420 return status;
424 *len_ret = len + 4;
425 return NT_STATUS_OK;
428 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
429 struct smbXsrv_connection *xconn,
430 int sock,
431 char **buffer, unsigned int timeout,
432 size_t *p_unread, size_t *plen)
434 char lenbuf[4];
435 size_t len;
436 int min_recv_size = lp_min_receive_file_size();
437 NTSTATUS status;
439 *p_unread = 0;
441 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
442 &len);
443 if (!NT_STATUS_IS_OK(status)) {
444 return status;
447 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
448 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
449 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
450 !smb1_srv_is_signing_active(xconn) &&
451 xconn->smb1.echo_handler.trusted_fde == NULL) {
453 return receive_smb_raw_talloc_partial_read(
454 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
455 p_unread, plen);
458 if (!valid_packet_size(len)) {
459 return NT_STATUS_INVALID_PARAMETER;
463 * The +4 here can't wrap, we've checked the length above already.
466 *buffer = talloc_array(mem_ctx, char, len+4);
468 if (*buffer == NULL) {
469 DEBUG(0, ("Could not allocate inbuf of length %d\n",
470 (int)len+4));
471 return NT_STATUS_NO_MEMORY;
474 memcpy(*buffer, lenbuf, sizeof(lenbuf));
476 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
477 if (!NT_STATUS_IS_OK(status)) {
478 return status;
481 *plen = len + 4;
482 return NT_STATUS_OK;
485 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
486 struct smbXsrv_connection *xconn,
487 int sock,
488 char **buffer, unsigned int timeout,
489 size_t *p_unread, bool *p_encrypted,
490 size_t *p_len,
491 uint32_t *seqnum,
492 bool trusted_channel)
494 size_t len = 0;
495 NTSTATUS status;
497 *p_encrypted = false;
499 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
500 p_unread, &len);
501 if (!NT_STATUS_IS_OK(status)) {
502 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
503 ("receive_smb_raw_talloc failed for client %s "
504 "read error = %s.\n",
505 smbXsrv_connection_dbg(xconn),
506 nt_errstr(status)) );
507 return status;
510 if (is_encrypted_packet((uint8_t *)*buffer)) {
511 status = srv_decrypt_buffer(xconn, *buffer);
512 if (!NT_STATUS_IS_OK(status)) {
513 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
514 "incoming packet! Error %s\n",
515 nt_errstr(status) ));
516 return status;
518 *p_encrypted = true;
521 /* Check the incoming SMB signature. */
522 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
523 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
524 "incoming packet!\n"));
525 return NT_STATUS_INVALID_NETWORK_RESPONSE;
528 *p_len = len;
529 return NT_STATUS_OK;
532 /****************************************************************************
533 Function to push a message onto the tail of a linked list of smb messages ready
534 for processing.
535 ****************************************************************************/
537 static bool push_queued_message(struct smb_request *req,
538 struct timeval request_time,
539 struct timeval end_time,
540 struct deferred_open_record *open_rec)
542 int msg_len = smb_len(req->inbuf) + 4;
543 struct pending_message_list *msg;
545 msg = talloc_zero(NULL, struct pending_message_list);
547 if(msg == NULL) {
548 DEBUG(0,("push_message: malloc fail (1)\n"));
549 return False;
551 msg->sconn = req->sconn;
552 msg->xconn = req->xconn;
554 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
555 if(msg->buf.data == NULL) {
556 DEBUG(0,("push_message: malloc fail (2)\n"));
557 TALLOC_FREE(msg);
558 return False;
561 msg->request_time = request_time;
562 msg->seqnum = req->seqnum;
563 msg->encrypted = req->encrypted;
564 msg->processed = false;
566 if (open_rec) {
567 msg->open_rec = talloc_move(msg, &open_rec);
570 #if 0
571 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
572 msg,
573 end_time,
574 smbd_deferred_open_timer,
575 msg);
576 if (!msg->te) {
577 DEBUG(0,("push_message: event_add_timed failed\n"));
578 TALLOC_FREE(msg);
579 return false;
581 #endif
583 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
585 DEBUG(10,("push_message: pushed message length %u on "
586 "deferred_open_queue\n", (unsigned int)msg_len));
588 return True;
591 /****************************************************************************
592 Function to push a deferred open smb message onto a linked list of local smb
593 messages ready for processing.
594 ****************************************************************************/
596 bool push_deferred_open_message_smb1(struct smb_request *req,
597 struct timeval timeout,
598 struct file_id id,
599 struct deferred_open_record *open_rec)
601 struct timeval_buf tvbuf;
602 struct timeval end_time;
604 if (req->unread_bytes) {
605 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
606 "unread_bytes = %u\n",
607 (unsigned int)req->unread_bytes ));
608 smb_panic("push_deferred_open_message_smb: "
609 "logic error unread_bytes != 0" );
612 end_time = timeval_sum(&req->request_time, &timeout);
614 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
615 (unsigned int) smb_len(req->inbuf)+4,
616 req->mid,
617 timeval_str_buf(&end_time, false, true, &tvbuf));
619 return push_queued_message(req, req->request_time, end_time, open_rec);
623 * Only allow 5 outstanding trans requests. We're allocating memory, so
624 * prevent a DoS.
627 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
629 int count = 0;
630 for (; list != NULL; list = list->next) {
632 if (list->mid == mid) {
633 return NT_STATUS_INVALID_PARAMETER;
636 count += 1;
638 if (count > 5) {
639 return NT_STATUS_INSUFFICIENT_RESOURCES;
642 return NT_STATUS_OK;
646 These flags determine some of the permissions required to do an operation
648 Note that I don't set NEED_WRITE on some write operations because they
649 are used by some brain-dead clients when printing, and I don't want to
650 force write permissions on print services.
652 #define AS_USER (1<<0)
653 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
654 #define TIME_INIT (1<<2)
655 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
656 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
657 #define DO_CHDIR (1<<6)
660 define a list of possible SMB messages and their corresponding
661 functions. Any message that has a NULL function is unimplemented -
662 please feel free to contribute implementations!
664 static const struct smb_message_struct {
665 const char *name;
666 void (*fn)(struct smb_request *req);
667 int flags;
668 } smb_messages[256] = {
670 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
671 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
672 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
673 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
674 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
675 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
676 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
677 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
678 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
679 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
680 /* 0x0a */ { "SMBread",reply_read,AS_USER},
681 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
682 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
683 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
684 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
685 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
686 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
687 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
688 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
689 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
690 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
691 /* 0x15 */ { NULL, NULL, 0 },
692 /* 0x16 */ { NULL, NULL, 0 },
693 /* 0x17 */ { NULL, NULL, 0 },
694 /* 0x18 */ { NULL, NULL, 0 },
695 /* 0x19 */ { NULL, NULL, 0 },
696 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
697 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
698 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
699 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
700 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
701 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
702 /* 0x20 */ { "SMBwritec", NULL,0},
703 /* 0x21 */ { NULL, NULL, 0 },
704 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
705 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
706 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
707 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
708 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
709 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
710 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
711 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
712 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
713 /* 0x2b */ { "SMBecho",reply_echo,0},
714 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
715 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
716 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
717 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
718 /* 0x30 */ { NULL, NULL, 0 },
719 /* 0x31 */ { NULL, NULL, 0 },
720 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
721 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
722 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
723 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
724 /* 0x36 */ { NULL, NULL, 0 },
725 /* 0x37 */ { NULL, NULL, 0 },
726 /* 0x38 */ { NULL, NULL, 0 },
727 /* 0x39 */ { NULL, NULL, 0 },
728 /* 0x3a */ { NULL, NULL, 0 },
729 /* 0x3b */ { NULL, NULL, 0 },
730 /* 0x3c */ { NULL, NULL, 0 },
731 /* 0x3d */ { NULL, NULL, 0 },
732 /* 0x3e */ { NULL, NULL, 0 },
733 /* 0x3f */ { NULL, NULL, 0 },
734 /* 0x40 */ { NULL, NULL, 0 },
735 /* 0x41 */ { NULL, NULL, 0 },
736 /* 0x42 */ { NULL, NULL, 0 },
737 /* 0x43 */ { NULL, NULL, 0 },
738 /* 0x44 */ { NULL, NULL, 0 },
739 /* 0x45 */ { NULL, NULL, 0 },
740 /* 0x46 */ { NULL, NULL, 0 },
741 /* 0x47 */ { NULL, NULL, 0 },
742 /* 0x48 */ { NULL, NULL, 0 },
743 /* 0x49 */ { NULL, NULL, 0 },
744 /* 0x4a */ { NULL, NULL, 0 },
745 /* 0x4b */ { NULL, NULL, 0 },
746 /* 0x4c */ { NULL, NULL, 0 },
747 /* 0x4d */ { NULL, NULL, 0 },
748 /* 0x4e */ { NULL, NULL, 0 },
749 /* 0x4f */ { NULL, NULL, 0 },
750 /* 0x50 */ { NULL, NULL, 0 },
751 /* 0x51 */ { NULL, NULL, 0 },
752 /* 0x52 */ { NULL, NULL, 0 },
753 /* 0x53 */ { NULL, NULL, 0 },
754 /* 0x54 */ { NULL, NULL, 0 },
755 /* 0x55 */ { NULL, NULL, 0 },
756 /* 0x56 */ { NULL, NULL, 0 },
757 /* 0x57 */ { NULL, NULL, 0 },
758 /* 0x58 */ { NULL, NULL, 0 },
759 /* 0x59 */ { NULL, NULL, 0 },
760 /* 0x5a */ { NULL, NULL, 0 },
761 /* 0x5b */ { NULL, NULL, 0 },
762 /* 0x5c */ { NULL, NULL, 0 },
763 /* 0x5d */ { NULL, NULL, 0 },
764 /* 0x5e */ { NULL, NULL, 0 },
765 /* 0x5f */ { NULL, NULL, 0 },
766 /* 0x60 */ { NULL, NULL, 0 },
767 /* 0x61 */ { NULL, NULL, 0 },
768 /* 0x62 */ { NULL, NULL, 0 },
769 /* 0x63 */ { NULL, NULL, 0 },
770 /* 0x64 */ { NULL, NULL, 0 },
771 /* 0x65 */ { NULL, NULL, 0 },
772 /* 0x66 */ { NULL, NULL, 0 },
773 /* 0x67 */ { NULL, NULL, 0 },
774 /* 0x68 */ { NULL, NULL, 0 },
775 /* 0x69 */ { NULL, NULL, 0 },
776 /* 0x6a */ { NULL, NULL, 0 },
777 /* 0x6b */ { NULL, NULL, 0 },
778 /* 0x6c */ { NULL, NULL, 0 },
779 /* 0x6d */ { NULL, NULL, 0 },
780 /* 0x6e */ { NULL, NULL, 0 },
781 /* 0x6f */ { NULL, NULL, 0 },
782 /* 0x70 */ { "SMBtcon",reply_tcon,0},
783 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
784 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
785 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
786 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
787 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
788 /* 0x76 */ { NULL, NULL, 0 },
789 /* 0x77 */ { NULL, NULL, 0 },
790 /* 0x78 */ { NULL, NULL, 0 },
791 /* 0x79 */ { NULL, NULL, 0 },
792 /* 0x7a */ { NULL, NULL, 0 },
793 /* 0x7b */ { NULL, NULL, 0 },
794 /* 0x7c */ { NULL, NULL, 0 },
795 /* 0x7d */ { NULL, NULL, 0 },
796 /* 0x7e */ { NULL, NULL, 0 },
797 /* 0x7f */ { NULL, NULL, 0 },
798 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
799 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
800 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
801 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
802 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
803 /* 0x85 */ { NULL, NULL, 0 },
804 /* 0x86 */ { NULL, NULL, 0 },
805 /* 0x87 */ { NULL, NULL, 0 },
806 /* 0x88 */ { NULL, NULL, 0 },
807 /* 0x89 */ { NULL, NULL, 0 },
808 /* 0x8a */ { NULL, NULL, 0 },
809 /* 0x8b */ { NULL, NULL, 0 },
810 /* 0x8c */ { NULL, NULL, 0 },
811 /* 0x8d */ { NULL, NULL, 0 },
812 /* 0x8e */ { NULL, NULL, 0 },
813 /* 0x8f */ { NULL, NULL, 0 },
814 /* 0x90 */ { NULL, NULL, 0 },
815 /* 0x91 */ { NULL, NULL, 0 },
816 /* 0x92 */ { NULL, NULL, 0 },
817 /* 0x93 */ { NULL, NULL, 0 },
818 /* 0x94 */ { NULL, NULL, 0 },
819 /* 0x95 */ { NULL, NULL, 0 },
820 /* 0x96 */ { NULL, NULL, 0 },
821 /* 0x97 */ { NULL, NULL, 0 },
822 /* 0x98 */ { NULL, NULL, 0 },
823 /* 0x99 */ { NULL, NULL, 0 },
824 /* 0x9a */ { NULL, NULL, 0 },
825 /* 0x9b */ { NULL, NULL, 0 },
826 /* 0x9c */ { NULL, NULL, 0 },
827 /* 0x9d */ { NULL, NULL, 0 },
828 /* 0x9e */ { NULL, NULL, 0 },
829 /* 0x9f */ { NULL, NULL, 0 },
830 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
831 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
832 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
833 /* 0xa3 */ { NULL, NULL, 0 },
834 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
835 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
836 /* 0xa6 */ { NULL, NULL, 0 },
837 /* 0xa7 */ { NULL, NULL, 0 },
838 /* 0xa8 */ { NULL, NULL, 0 },
839 /* 0xa9 */ { NULL, NULL, 0 },
840 /* 0xaa */ { NULL, NULL, 0 },
841 /* 0xab */ { NULL, NULL, 0 },
842 /* 0xac */ { NULL, NULL, 0 },
843 /* 0xad */ { NULL, NULL, 0 },
844 /* 0xae */ { NULL, NULL, 0 },
845 /* 0xaf */ { NULL, NULL, 0 },
846 /* 0xb0 */ { NULL, NULL, 0 },
847 /* 0xb1 */ { NULL, NULL, 0 },
848 /* 0xb2 */ { NULL, NULL, 0 },
849 /* 0xb3 */ { NULL, NULL, 0 },
850 /* 0xb4 */ { NULL, NULL, 0 },
851 /* 0xb5 */ { NULL, NULL, 0 },
852 /* 0xb6 */ { NULL, NULL, 0 },
853 /* 0xb7 */ { NULL, NULL, 0 },
854 /* 0xb8 */ { NULL, NULL, 0 },
855 /* 0xb9 */ { NULL, NULL, 0 },
856 /* 0xba */ { NULL, NULL, 0 },
857 /* 0xbb */ { NULL, NULL, 0 },
858 /* 0xbc */ { NULL, NULL, 0 },
859 /* 0xbd */ { NULL, NULL, 0 },
860 /* 0xbe */ { NULL, NULL, 0 },
861 /* 0xbf */ { NULL, NULL, 0 },
862 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
863 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
864 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
865 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
866 /* 0xc4 */ { NULL, NULL, 0 },
867 /* 0xc5 */ { NULL, NULL, 0 },
868 /* 0xc6 */ { NULL, NULL, 0 },
869 /* 0xc7 */ { NULL, NULL, 0 },
870 /* 0xc8 */ { NULL, NULL, 0 },
871 /* 0xc9 */ { NULL, NULL, 0 },
872 /* 0xca */ { NULL, NULL, 0 },
873 /* 0xcb */ { NULL, NULL, 0 },
874 /* 0xcc */ { NULL, NULL, 0 },
875 /* 0xcd */ { NULL, NULL, 0 },
876 /* 0xce */ { NULL, NULL, 0 },
877 /* 0xcf */ { NULL, NULL, 0 },
878 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
879 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
880 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
881 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
882 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
883 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
884 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
885 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
886 /* 0xd8 */ { NULL, NULL, 0 },
887 /* 0xd9 */ { NULL, NULL, 0 },
888 /* 0xda */ { NULL, NULL, 0 },
889 /* 0xdb */ { NULL, NULL, 0 },
890 /* 0xdc */ { NULL, NULL, 0 },
891 /* 0xdd */ { NULL, NULL, 0 },
892 /* 0xde */ { NULL, NULL, 0 },
893 /* 0xdf */ { NULL, NULL, 0 },
894 /* 0xe0 */ { NULL, NULL, 0 },
895 /* 0xe1 */ { NULL, NULL, 0 },
896 /* 0xe2 */ { NULL, NULL, 0 },
897 /* 0xe3 */ { NULL, NULL, 0 },
898 /* 0xe4 */ { NULL, NULL, 0 },
899 /* 0xe5 */ { NULL, NULL, 0 },
900 /* 0xe6 */ { NULL, NULL, 0 },
901 /* 0xe7 */ { NULL, NULL, 0 },
902 /* 0xe8 */ { NULL, NULL, 0 },
903 /* 0xe9 */ { NULL, NULL, 0 },
904 /* 0xea */ { NULL, NULL, 0 },
905 /* 0xeb */ { NULL, NULL, 0 },
906 /* 0xec */ { NULL, NULL, 0 },
907 /* 0xed */ { NULL, NULL, 0 },
908 /* 0xee */ { NULL, NULL, 0 },
909 /* 0xef */ { NULL, NULL, 0 },
910 /* 0xf0 */ { NULL, NULL, 0 },
911 /* 0xf1 */ { NULL, NULL, 0 },
912 /* 0xf2 */ { NULL, NULL, 0 },
913 /* 0xf3 */ { NULL, NULL, 0 },
914 /* 0xf4 */ { NULL, NULL, 0 },
915 /* 0xf5 */ { NULL, NULL, 0 },
916 /* 0xf6 */ { NULL, NULL, 0 },
917 /* 0xf7 */ { NULL, NULL, 0 },
918 /* 0xf8 */ { NULL, NULL, 0 },
919 /* 0xf9 */ { NULL, NULL, 0 },
920 /* 0xfa */ { NULL, NULL, 0 },
921 /* 0xfb */ { NULL, NULL, 0 },
922 /* 0xfc */ { NULL, NULL, 0 },
923 /* 0xfd */ { NULL, NULL, 0 },
924 /* 0xfe */ { NULL, NULL, 0 },
925 /* 0xff */ { NULL, NULL, 0 }
930 /*******************************************************************
931 Dump a packet to a file.
932 ********************************************************************/
934 static void smb_dump(const char *name, int type, const char *data)
936 size_t len;
937 int fd, i;
938 char *fname = NULL;
939 if (DEBUGLEVEL < 50) {
940 return;
943 len = smb_len_tcp(data)+4;
944 for (i=1;i<100;i++) {
945 fname = talloc_asprintf(talloc_tos(),
946 "/tmp/%s.%d.%s",
947 name,
949 type ? "req" : "resp");
950 if (fname == NULL) {
951 return;
953 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
954 if (fd != -1 || errno != EEXIST) break;
955 TALLOC_FREE(fname);
957 if (fd != -1) {
958 ssize_t ret = write(fd, data, len);
959 if (ret != len)
960 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
961 close(fd);
962 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
964 TALLOC_FREE(fname);
967 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
968 struct smb_request *req,
969 uint8_t type,
970 bool *update_session_globalp,
971 bool *update_tcon_globalp)
973 connection_struct *conn = req->conn;
974 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
975 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
976 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
977 bool update_session = false;
978 bool update_tcon = false;
980 if (req->encrypted) {
981 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
984 if (smb1_srv_is_signing_active(req->xconn)) {
985 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
986 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
988 * echo can be unsigned. Session setup except final
989 * session setup response too
991 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
994 update_session |= smbXsrv_set_crypto_flag(
995 &session->global->encryption_flags, encrypt_flag);
996 update_session |= smbXsrv_set_crypto_flag(
997 &session->global->signing_flags, sign_flag);
999 if (tcon) {
1000 update_tcon |= smbXsrv_set_crypto_flag(
1001 &tcon->global->encryption_flags, encrypt_flag);
1002 update_tcon |= smbXsrv_set_crypto_flag(
1003 &tcon->global->signing_flags, sign_flag);
1006 if (update_session) {
1007 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1010 *update_session_globalp = update_session;
1011 *update_tcon_globalp = update_tcon;
1012 return;
1015 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1017 int snum;
1018 enum remote_arch_types ra_type;
1020 SMB_ASSERT(conn != NULL);
1021 SMB_ASSERT(!conn_using_smb2(conn->sconn));
1023 snum = SNUM(conn);
1026 * Obey the client case sensitivity requests - only for clients that
1027 * support it. */
1028 switch (lp_case_sensitive(snum)) {
1029 case Auto:
1031 * We need this ugliness due to DOS/Win9x clients that lie
1032 * about case insensitivity. */
1033 ra_type = get_remote_arch();
1034 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1036 * Client can't support per-packet case sensitive
1037 * pathnames. */
1038 conn->case_sensitive = false;
1039 } else {
1040 conn->case_sensitive =
1041 !(flags & FLAG_CASELESS_PATHNAMES);
1043 break;
1044 case True:
1045 conn->case_sensitive = true;
1046 break;
1047 default:
1048 conn->case_sensitive = false;
1049 break;
1053 /****************************************************************************
1054 Prepare everything for calling the actual request function, and potentially
1055 call the request function via the "new" interface.
1057 Return False if the "legacy" function needs to be called, everything is
1058 prepared.
1060 Return True if we're done.
1062 I know this API sucks, but it is the one with the least code change I could
1063 find.
1064 ****************************************************************************/
1066 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1068 const struct loadparm_substitution *lp_sub =
1069 loadparm_s3_global_substitution();
1070 int flags;
1071 uint64_t session_tag;
1072 connection_struct *conn = NULL;
1073 struct smbXsrv_connection *xconn = req->xconn;
1074 NTTIME now = timeval_to_nttime(&req->request_time);
1075 struct smbXsrv_session *session = NULL;
1076 NTSTATUS status;
1078 errno = 0;
1080 if (!xconn->smb1.negprot.done) {
1081 switch (type) {
1083 * Without a negprot the request must
1084 * either be a negprot, or one of the
1085 * evil old SMB mailslot messaging types.
1087 case SMBnegprot:
1088 case SMBsendstrt:
1089 case SMBsendend:
1090 case SMBsendtxt:
1091 break;
1092 default:
1093 exit_server_cleanly("The first request "
1094 "should be a negprot");
1098 if (smb_messages[type].fn == NULL) {
1099 DEBUG(0,("Unknown message type %d!\n",type));
1100 smb_dump("Unknown", 1, (const char *)req->inbuf);
1101 reply_unknown_new(req, type);
1102 return NULL;
1105 flags = smb_messages[type].flags;
1107 /* In share mode security we must ignore the vuid. */
1108 session_tag = req->vuid;
1109 conn = req->conn;
1111 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1112 (int)getpid(), (unsigned long)conn));
1114 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1116 /* Ensure this value is replaced in the incoming packet. */
1117 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1120 * Ensure the correct username is in current_user_info. This is a
1121 * really ugly bugfix for problems with multiple session_setup_and_X's
1122 * being done and allowing %U and %G substitutions to work correctly.
1123 * There is a reason this code is done here, don't move it unless you
1124 * know what you're doing... :-).
1125 * JRA.
1129 * lookup an existing session
1131 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1132 * here, the main check is still in change_to_user()
1134 status = smb1srv_session_lookup(xconn,
1135 session_tag,
1136 now,
1137 &session);
1138 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1139 switch (type) {
1140 case SMBsesssetupX:
1141 status = NT_STATUS_OK;
1142 break;
1143 default:
1144 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1145 (unsigned long long)session_tag,
1146 (unsigned long long)req->mid));
1147 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1148 return conn;
1152 if (session != NULL &&
1153 session->global->auth_session_info != NULL &&
1154 !(flags & AS_USER))
1157 * change_to_user() implies set_current_user_info()
1158 * and chdir_connect_service().
1160 * So we only call set_current_user_info if
1161 * we don't have AS_USER specified.
1163 set_current_user_info(
1164 session->global->auth_session_info->unix_info->sanitized_username,
1165 session->global->auth_session_info->unix_info->unix_name,
1166 session->global->auth_session_info->info->domain_name);
1169 /* Does this call need to be run as the connected user? */
1170 if (flags & AS_USER) {
1172 /* Does this call need a valid tree connection? */
1173 if (!conn) {
1175 * Amazingly, the error code depends on the command
1176 * (from Samba4).
1178 if (type == SMBntcreateX) {
1179 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1180 } else {
1181 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1183 return NULL;
1186 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1189 * change_to_user() implies set_current_user_info()
1190 * and chdir_connect_service().
1192 if (!change_to_user_and_service(conn,session_tag)) {
1193 DEBUG(0, ("Error: Could not change to user. Removing "
1194 "deferred open, mid=%llu.\n",
1195 (unsigned long long)req->mid));
1196 reply_force_doserror(req, ERRSRV, ERRbaduid);
1197 return conn;
1200 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1202 /* Does it need write permission? */
1203 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1204 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1205 return conn;
1208 /* IPC services are limited */
1209 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1210 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1211 return conn;
1213 } else if (flags & AS_GUEST) {
1215 * Does this protocol need to be run as guest? (Only archane
1216 * messenger service requests have this...)
1218 if (!change_to_guest()) {
1219 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1220 return conn;
1222 } else {
1223 /* This call needs to be run as root */
1224 change_to_root_user();
1227 /* load service specific parameters */
1228 if (conn) {
1229 if (req->encrypted) {
1230 conn->encrypted_tid = true;
1231 /* encrypted required from now on. */
1232 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1233 } else if (ENCRYPTION_REQUIRED(conn)) {
1234 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1235 DEBUG(1,("service[%s] requires encryption"
1236 "%s ACCESS_DENIED. mid=%llu\n",
1237 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1238 smb_fn_name(type),
1239 (unsigned long long)req->mid));
1240 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1241 return conn;
1245 if (flags & DO_CHDIR) {
1246 bool ok;
1248 ok = chdir_current_service(conn);
1249 if (!ok) {
1250 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1251 return conn;
1254 conn->num_smb_operations++;
1258 * Update encryption and signing state tracking flags that are
1259 * used by smbstatus to display signing and encryption status.
1261 if (session != NULL) {
1262 bool update_session_global = false;
1263 bool update_tcon_global = false;
1265 req->session = session;
1267 smb1srv_update_crypto_flags(session, req, type,
1268 &update_session_global,
1269 &update_tcon_global);
1271 if (update_session_global) {
1272 status = smbXsrv_session_update(session);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1275 return conn;
1279 if (update_tcon_global) {
1280 status = smbXsrv_tcon_update(req->conn->tcon);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1283 return conn;
1288 smb_messages[type].fn(req);
1289 return req->conn;
1292 /****************************************************************************
1293 Construct a reply to the incoming packet.
1294 ****************************************************************************/
1296 void construct_reply(struct smbXsrv_connection *xconn,
1297 char *inbuf,
1298 int size,
1299 size_t unread_bytes,
1300 uint32_t seqnum,
1301 bool encrypted)
1303 struct smbd_server_connection *sconn = xconn->client->sconn;
1304 struct smb_request *req;
1306 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1307 smb_panic("could not allocate smb_request");
1310 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1311 encrypted, seqnum)) {
1312 exit_server_cleanly("Invalid SMB request");
1315 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1317 req->conn = switch_message(req->cmd, req);
1319 if (req->outbuf == NULL) {
1321 * Request has suspended itself, will come
1322 * back here.
1324 return;
1326 if (CVAL(req->outbuf,0) == 0) {
1327 show_msg((char *)req->outbuf);
1329 smb_request_done(req);
1332 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1333 char *inbuf,
1334 int size,
1335 uint32_t seqnum,
1336 bool encrypted)
1338 struct smb_request **reqs = NULL;
1339 struct smb_request *req;
1340 unsigned num_reqs;
1341 bool ok;
1343 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1344 seqnum, &reqs, &num_reqs);
1345 if (!ok) {
1346 char errbuf[smb_size];
1347 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1348 __LINE__, __FILE__);
1349 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
1350 exit_server_cleanly("construct_reply_chain: "
1351 "smb1_srv_send failed.");
1353 return;
1356 req = reqs[0];
1357 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1359 req->conn = switch_message(req->cmd, req);
1361 if (req->outbuf == NULL) {
1363 * Request has suspended itself, will come
1364 * back here.
1366 return;
1368 smb_request_done(req);
1372 * To be called from an async SMB handler that is potentially chained
1373 * when it is finished for shipping.
1376 void smb_request_done(struct smb_request *req)
1378 struct smb_request **reqs = NULL;
1379 struct smb_request *first_req;
1380 size_t i, num_reqs, next_index;
1381 NTSTATUS status;
1383 if (req->chain == NULL) {
1384 first_req = req;
1385 goto shipit;
1388 reqs = req->chain;
1389 num_reqs = talloc_array_length(reqs);
1391 for (i=0; i<num_reqs; i++) {
1392 if (reqs[i] == req) {
1393 break;
1396 if (i == num_reqs) {
1398 * Invalid chain, should not happen
1400 status = NT_STATUS_INTERNAL_ERROR;
1401 goto error;
1403 next_index = i+1;
1405 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1406 struct smb_request *next = reqs[next_index];
1407 struct smbXsrv_tcon *tcon;
1408 NTTIME now = timeval_to_nttime(&req->request_time);
1410 next->vuid = SVAL(req->outbuf, smb_uid);
1411 next->tid = SVAL(req->outbuf, smb_tid);
1412 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1413 now, &tcon);
1415 if (NT_STATUS_IS_OK(status)) {
1416 next->conn = tcon->compat;
1417 } else {
1418 next->conn = NULL;
1420 next->chain_fsp = req->chain_fsp;
1421 next->inbuf = req->inbuf;
1423 req = next;
1424 req->conn = switch_message(req->cmd, req);
1426 if (req->outbuf == NULL) {
1428 * Request has suspended itself, will come
1429 * back here.
1431 return;
1433 next_index += 1;
1436 first_req = reqs[0];
1438 for (i=1; i<next_index; i++) {
1439 bool ok;
1441 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1442 if (!ok) {
1443 status = NT_STATUS_INTERNAL_ERROR;
1444 goto error;
1448 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1449 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1452 * This scary statement intends to set the
1453 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1454 * to the value last_req->outbuf carries
1456 SSVAL(first_req->outbuf, smb_flg2,
1457 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1458 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1461 * Transfer the error codes from the subrequest to the main one
1463 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1464 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1466 _smb_setlen_large(
1467 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1469 shipit:
1470 if (!smb1_srv_send(first_req->xconn,
1471 (char *)first_req->outbuf,
1472 true,
1473 first_req->seqnum + 1,
1474 IS_CONN_ENCRYPTED(req->conn) ||
1475 first_req->encrypted)) {
1476 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1477 "failed.");
1479 TALLOC_FREE(req); /* non-chained case */
1480 TALLOC_FREE(reqs); /* chained case */
1481 return;
1483 error:
1485 char errbuf[smb_size];
1486 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1487 if (!smb1_srv_send(req->xconn,
1488 errbuf,
1489 true,
1490 req->seqnum + 1,
1491 req->encrypted)) {
1492 exit_server_cleanly("construct_reply_chain: "
1493 "smb1_srv_send failed.");
1496 TALLOC_FREE(req); /* non-chained case */
1497 TALLOC_FREE(reqs); /* chained case */
1500 /****************************************************************************
1501 Process an smb from the client
1502 ****************************************************************************/
1504 void process_smb1(struct smbXsrv_connection *xconn,
1505 uint8_t *inbuf,
1506 size_t nread,
1507 size_t unread_bytes,
1508 uint32_t seqnum,
1509 bool encrypted)
1511 struct smbd_server_connection *sconn = xconn->client->sconn;
1513 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1514 * so subtract 4 from it. */
1515 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1516 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1517 smb_len(inbuf)));
1519 /* special magic for immediate exit */
1520 if ((nread == 9) &&
1521 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1522 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1523 uint8_t exitcode = CVAL(inbuf, 8);
1524 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1525 (int)exitcode);
1526 exit(exitcode);
1529 exit_server_cleanly("Non-SMB packet");
1532 show_msg((char *)inbuf);
1534 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1535 construct_reply_chain(xconn,
1536 (char *)inbuf,
1537 nread,
1538 seqnum,
1539 encrypted);
1540 } else {
1541 construct_reply(xconn,
1542 (char *)inbuf,
1543 nread,
1544 unread_bytes,
1545 seqnum,
1546 encrypted);
1549 sconn->trans_num++;
1552 /****************************************************************************
1553 Return a string containing the function name of a SMB command.
1554 ****************************************************************************/
1556 const char *smb_fn_name(int type)
1558 const char *unknown_name = "SMBunknown";
1560 if (smb_messages[type].name == NULL)
1561 return(unknown_name);
1563 return(smb_messages[type].name);
1566 /****************************************************************************
1567 Helper functions for contruct_reply.
1568 ****************************************************************************/
1570 void add_to_common_flags2(uint32_t v)
1572 common_flags2 |= v;
1575 void remove_from_common_flags2(uint32_t v)
1577 common_flags2 &= ~v;
1581 * @brief Find the smb_cmd offset of the last command pushed
1582 * @param[in] buf The buffer we're building up
1583 * @retval Where can we put our next andx cmd?
1585 * While chaining requests, the "next" request we're looking at needs to put
1586 * its SMB_Command before the data the previous request already built up added
1587 * to the chain. Find the offset to the place where we have to put our cmd.
1590 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1592 uint8_t cmd;
1593 size_t ofs;
1595 cmd = CVAL(buf, smb_com);
1597 if (!smb1cli_is_andx_req(cmd)) {
1598 return false;
1601 ofs = smb_vwv0;
1603 while (CVAL(buf, ofs) != 0xff) {
1605 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1606 return false;
1610 * ofs is from start of smb header, so add the 4 length
1611 * bytes. The next cmd is right after the wct field.
1613 ofs = SVAL(buf, ofs+2) + 4 + 1;
1615 if (ofs+4 >= talloc_get_size(buf)) {
1616 return false;
1620 *pofs = ofs;
1621 return true;
1625 * @brief Do the smb chaining at a buffer level
1626 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1627 * @param[in] andx_buf Buffer to be appended
1630 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1632 uint8_t smb_command = CVAL(andx_buf, smb_com);
1633 uint8_t wct = CVAL(andx_buf, smb_wct);
1634 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1635 uint32_t num_bytes = smb_buflen(andx_buf);
1636 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1638 uint8_t *outbuf;
1639 size_t old_size, new_size;
1640 size_t ofs;
1641 size_t chain_padding = 0;
1642 size_t andx_cmd_ofs;
1645 old_size = talloc_get_size(*poutbuf);
1647 if ((old_size % 4) != 0) {
1649 * Align the wct field of subsequent requests to a 4-byte
1650 * boundary
1652 chain_padding = 4 - (old_size % 4);
1656 * After the old request comes the new wct field (1 byte), the vwv's
1657 * and the num_bytes field.
1660 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1661 new_size += num_bytes;
1663 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1664 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1665 (unsigned)new_size));
1666 return false;
1669 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1670 if (outbuf == NULL) {
1671 DEBUG(0, ("talloc failed\n"));
1672 return false;
1674 *poutbuf = outbuf;
1676 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1677 DEBUG(1, ("invalid command chain\n"));
1678 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1679 return false;
1682 if (chain_padding != 0) {
1683 memset(outbuf + old_size, 0, chain_padding);
1684 old_size += chain_padding;
1687 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1688 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1690 ofs = old_size;
1693 * Push the chained request:
1695 * wct field
1698 SCVAL(outbuf, ofs, wct);
1699 ofs += 1;
1702 * vwv array
1705 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1708 * HACK ALERT
1710 * Read&X has an offset into its data buffer at
1711 * vwv[6]. reply_read_andx has no idea anymore that it's
1712 * running from within a chain, so we have to fix up the
1713 * offset here.
1715 * Although it looks disgusting at this place, I want to keep
1716 * it here. The alternative would be to push knowledge about
1717 * the andx chain down into read&x again.
1720 if (smb_command == SMBreadX) {
1721 uint8_t *bytes_addr;
1723 if (wct < 7) {
1725 * Invalid read&x response
1727 return false;
1730 bytes_addr = outbuf + ofs /* vwv start */
1731 + sizeof(uint16_t) * wct /* vwv array */
1732 + sizeof(uint16_t) /* bcc */
1733 + 1; /* padding byte */
1735 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1736 bytes_addr - outbuf - 4);
1739 ofs += sizeof(uint16_t) * wct;
1742 * bcc (byte count)
1745 SSVAL(outbuf, ofs, num_bytes);
1746 ofs += sizeof(uint16_t);
1749 * The bytes field
1752 memcpy(outbuf + ofs, bytes, num_bytes);
1754 return true;
1757 bool smb1_is_chain(const uint8_t *buf)
1759 uint8_t cmd, wct, andx_cmd;
1761 cmd = CVAL(buf, smb_com);
1762 if (!smb1cli_is_andx_req(cmd)) {
1763 return false;
1765 wct = CVAL(buf, smb_wct);
1766 if (wct < 2) {
1767 return false;
1769 andx_cmd = CVAL(buf, smb_vwv);
1770 return (andx_cmd != 0xFF);
1773 bool smb1_walk_chain(const uint8_t *buf,
1774 bool (*fn)(uint8_t cmd,
1775 uint8_t wct, const uint16_t *vwv,
1776 uint16_t num_bytes, const uint8_t *bytes,
1777 void *private_data),
1778 void *private_data)
1780 size_t smblen = smb_len(buf);
1781 const char *smb_buf = smb_base(buf);
1782 uint8_t cmd, chain_cmd;
1783 uint8_t wct;
1784 const uint16_t *vwv;
1785 uint16_t num_bytes;
1786 const uint8_t *bytes;
1788 cmd = CVAL(buf, smb_com);
1789 wct = CVAL(buf, smb_wct);
1790 vwv = (const uint16_t *)(buf + smb_vwv);
1791 num_bytes = smb_buflen(buf);
1792 bytes = (const uint8_t *)smb_buf_const(buf);
1794 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1795 return false;
1798 if (!smb1cli_is_andx_req(cmd)) {
1799 return true;
1801 if (wct < 2) {
1802 return false;
1805 chain_cmd = CVAL(vwv, 0);
1807 while (chain_cmd != 0xff) {
1808 uint32_t chain_offset; /* uint32_t to avoid overflow */
1809 size_t length_needed;
1810 ptrdiff_t vwv_offset;
1812 chain_offset = SVAL(vwv+1, 0);
1815 * Check if the client tries to fool us. The chain
1816 * offset needs to point beyond the current request in
1817 * the chain, it needs to strictly grow. Otherwise we
1818 * might be tricked into an endless loop always
1819 * processing the same request over and over again. We
1820 * used to assume that vwv and the byte buffer array
1821 * in a chain are always attached, but OS/2 the
1822 * Write&X/Read&X chain puts the Read&X vwv array
1823 * right behind the Write&X vwv chain. The Write&X bcc
1824 * array is put behind the Read&X vwv array. So now we
1825 * check whether the chain offset points strictly
1826 * behind the previous vwv array. req->buf points
1827 * right after the vwv array of the previous
1828 * request. See
1829 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1830 * more information.
1833 vwv_offset = ((const char *)vwv - smb_buf);
1834 if (chain_offset <= vwv_offset) {
1835 return false;
1839 * Next check: Make sure the chain offset does not
1840 * point beyond the overall smb request length.
1843 length_needed = chain_offset+1; /* wct */
1844 if (length_needed > smblen) {
1845 return false;
1849 * Now comes the pointer magic. Goal here is to set up
1850 * vwv and buf correctly again. The chain offset (the
1851 * former vwv[1]) points at the new wct field.
1854 wct = CVAL(smb_buf, chain_offset);
1856 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1857 return false;
1861 * Next consistency check: Make the new vwv array fits
1862 * in the overall smb request.
1865 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1866 if (length_needed > smblen) {
1867 return false;
1869 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1872 * Now grab the new byte buffer....
1875 num_bytes = SVAL(vwv+wct, 0);
1878 * .. and check that it fits.
1881 length_needed += num_bytes;
1882 if (length_needed > smblen) {
1883 return false;
1885 bytes = (const uint8_t *)(vwv+wct+1);
1887 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1888 return false;
1891 if (!smb1cli_is_andx_req(chain_cmd)) {
1892 return true;
1894 chain_cmd = CVAL(vwv, 0);
1896 return true;
1899 static bool smb1_chain_length_cb(uint8_t cmd,
1900 uint8_t wct, const uint16_t *vwv,
1901 uint16_t num_bytes, const uint8_t *bytes,
1902 void *private_data)
1904 unsigned *count = (unsigned *)private_data;
1905 *count += 1;
1906 return true;
1909 unsigned smb1_chain_length(const uint8_t *buf)
1911 unsigned count = 0;
1913 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1914 return 0;
1916 return count;
1919 struct smb1_parse_chain_state {
1920 TALLOC_CTX *mem_ctx;
1921 const uint8_t *buf;
1922 struct smbd_server_connection *sconn;
1923 struct smbXsrv_connection *xconn;
1924 bool encrypted;
1925 uint32_t seqnum;
1927 struct smb_request **reqs;
1928 unsigned num_reqs;
1931 static bool smb1_parse_chain_cb(uint8_t cmd,
1932 uint8_t wct, const uint16_t *vwv,
1933 uint16_t num_bytes, const uint8_t *bytes,
1934 void *private_data)
1936 struct smb1_parse_chain_state *state =
1937 (struct smb1_parse_chain_state *)private_data;
1938 struct smb_request **reqs;
1939 struct smb_request *req;
1940 bool ok;
1942 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1943 struct smb_request *, state->num_reqs+1);
1944 if (reqs == NULL) {
1945 return false;
1947 state->reqs = reqs;
1949 req = talloc(reqs, struct smb_request);
1950 if (req == NULL) {
1951 return false;
1954 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1955 state->encrypted, state->seqnum);
1956 if (!ok) {
1957 return false;
1959 req->cmd = cmd;
1960 req->wct = wct;
1961 req->vwv = vwv;
1962 req->buflen = num_bytes;
1963 req->buf = bytes;
1965 reqs[state->num_reqs] = req;
1966 state->num_reqs += 1;
1967 return true;
1970 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1971 struct smbXsrv_connection *xconn,
1972 bool encrypted, uint32_t seqnum,
1973 struct smb_request ***reqs, unsigned *num_reqs)
1975 struct smbd_server_connection *sconn = NULL;
1976 struct smb1_parse_chain_state state;
1977 unsigned i;
1979 if (xconn != NULL) {
1980 sconn = xconn->client->sconn;
1983 state.mem_ctx = mem_ctx;
1984 state.buf = buf;
1985 state.sconn = sconn;
1986 state.xconn = xconn;
1987 state.encrypted = encrypted;
1988 state.seqnum = seqnum;
1989 state.reqs = NULL;
1990 state.num_reqs = 0;
1992 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1993 TALLOC_FREE(state.reqs);
1994 return false;
1996 for (i=0; i<state.num_reqs; i++) {
1997 state.reqs[i]->chain = state.reqs;
1999 *reqs = state.reqs;
2000 *num_reqs = state.num_reqs;
2001 return true;
2004 static bool fd_is_readable(int fd)
2006 int ret, revents;
2008 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2010 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2014 static void smbd_server_connection_write_handler(
2015 struct smbXsrv_connection *xconn)
2017 /* TODO: make write nonblocking */
2020 void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2021 int fd)
2023 uint8_t *inbuf = NULL;
2024 size_t inbuf_len = 0;
2025 size_t unread_bytes = 0;
2026 bool encrypted = false;
2027 TALLOC_CTX *mem_ctx = talloc_tos();
2028 NTSTATUS status;
2029 uint32_t seqnum;
2031 bool async_echo = lp_async_smb_echo_handler();
2032 bool from_client = false;
2034 if (async_echo) {
2035 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
2037 * This is the super-ugly hack to prefer the packets
2038 * forwarded by the echo handler over the ones by the
2039 * client directly
2041 fd = xconn->smb1.echo_handler.trusted_fd;
2045 from_client = (xconn->transport.sock == fd);
2047 if (async_echo && from_client) {
2048 smbd_lock_socket(xconn);
2050 if (!fd_is_readable(fd)) {
2051 DEBUG(10,("the echo listener was faster\n"));
2052 smbd_unlock_socket(xconn);
2053 return;
2057 /* TODO: make this completely nonblocking */
2058 status = receive_smb_talloc(mem_ctx, xconn, fd,
2059 (char **)(void *)&inbuf,
2060 0, /* timeout */
2061 &unread_bytes,
2062 &encrypted,
2063 &inbuf_len, &seqnum,
2064 !from_client /* trusted channel */);
2066 if (async_echo && from_client) {
2067 smbd_unlock_socket(xconn);
2070 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2071 goto process;
2073 if (NT_STATUS_IS_ERR(status)) {
2074 exit_server_cleanly("failed to receive smb request");
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return;
2080 process:
2081 process_smb(xconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted);
2084 static void smbd_server_echo_handler(struct tevent_context *ev,
2085 struct tevent_fd *fde,
2086 uint16_t flags,
2087 void *private_data)
2089 struct smbXsrv_connection *xconn =
2090 talloc_get_type_abort(private_data,
2091 struct smbXsrv_connection);
2093 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2095 * we're not supposed to do any io
2097 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2098 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2099 return;
2102 if (flags & TEVENT_FD_WRITE) {
2103 smbd_server_connection_write_handler(xconn);
2104 return;
2106 if (flags & TEVENT_FD_READ) {
2107 smbd_smb1_server_connection_read_handler(
2108 xconn, xconn->smb1.echo_handler.trusted_fd);
2109 return;
2114 * Send keepalive packets to our client
2116 bool keepalive_fn(const struct timeval *now, void *private_data)
2118 struct smbd_server_connection *sconn = talloc_get_type_abort(
2119 private_data, struct smbd_server_connection);
2120 struct smbXsrv_connection *xconn = NULL;
2121 bool ret;
2123 if (conn_using_smb2(sconn)) {
2124 /* Don't do keepalives on an SMB2 connection. */
2125 return false;
2129 * With SMB1 we only have 1 connection
2131 xconn = sconn->client->connections;
2132 smbd_lock_socket(xconn);
2133 ret = send_keepalive(xconn->transport.sock);
2134 smbd_unlock_socket(xconn);
2136 if (!ret) {
2137 int saved_errno = errno;
2139 * Try and give an error message saying what
2140 * client failed.
2142 DEBUG(0, ("send_keepalive failed for client %s. "
2143 "Error %s - exiting\n",
2144 smbXsrv_connection_dbg(xconn),
2145 strerror(saved_errno)));
2146 errno = saved_errno;
2147 return False;
2149 return True;
2153 * Read an smb packet in the echo handler child, giving the parent
2154 * smbd one second to react once the socket becomes readable.
2157 struct smbd_echo_read_state {
2158 struct tevent_context *ev;
2159 struct smbXsrv_connection *xconn;
2161 char *buf;
2162 size_t buflen;
2163 uint32_t seqnum;
2166 static void smbd_echo_read_readable(struct tevent_req *subreq);
2167 static void smbd_echo_read_waited(struct tevent_req *subreq);
2169 static struct tevent_req *smbd_echo_read_send(
2170 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2171 struct smbXsrv_connection *xconn)
2173 struct tevent_req *req, *subreq;
2174 struct smbd_echo_read_state *state;
2176 req = tevent_req_create(mem_ctx, &state,
2177 struct smbd_echo_read_state);
2178 if (req == NULL) {
2179 return NULL;
2181 state->ev = ev;
2182 state->xconn = xconn;
2184 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2185 if (tevent_req_nomem(subreq, req)) {
2186 return tevent_req_post(req, ev);
2188 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2189 return req;
2192 static void smbd_echo_read_readable(struct tevent_req *subreq)
2194 struct tevent_req *req = tevent_req_callback_data(
2195 subreq, struct tevent_req);
2196 struct smbd_echo_read_state *state = tevent_req_data(
2197 req, struct smbd_echo_read_state);
2198 bool ok;
2199 int err;
2201 ok = wait_for_read_recv(subreq, &err);
2202 TALLOC_FREE(subreq);
2203 if (!ok) {
2204 tevent_req_nterror(req, map_nt_error_from_unix(err));
2205 return;
2209 * Give the parent smbd one second to step in
2212 subreq = tevent_wakeup_send(
2213 state, state->ev, timeval_current_ofs(1, 0));
2214 if (tevent_req_nomem(subreq, req)) {
2215 return;
2217 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2220 static void smbd_echo_read_waited(struct tevent_req *subreq)
2222 struct tevent_req *req = tevent_req_callback_data(
2223 subreq, struct tevent_req);
2224 struct smbd_echo_read_state *state = tevent_req_data(
2225 req, struct smbd_echo_read_state);
2226 struct smbXsrv_connection *xconn = state->xconn;
2227 bool ok;
2228 NTSTATUS status;
2229 size_t unread = 0;
2230 bool encrypted;
2232 ok = tevent_wakeup_recv(subreq);
2233 TALLOC_FREE(subreq);
2234 if (!ok) {
2235 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2236 return;
2239 ok = smbd_lock_socket_internal(xconn);
2240 if (!ok) {
2241 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2242 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2243 return;
2246 if (!fd_is_readable(xconn->transport.sock)) {
2247 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2248 (int)getpid()));
2250 ok = smbd_unlock_socket_internal(xconn);
2251 if (!ok) {
2252 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2253 DEBUG(1, ("%s: failed to unlock socket\n",
2254 __location__));
2255 return;
2258 subreq = wait_for_read_send(state, state->ev,
2259 xconn->transport.sock, false);
2260 if (tevent_req_nomem(subreq, req)) {
2261 return;
2263 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2264 return;
2267 status = receive_smb_talloc(state, xconn,
2268 xconn->transport.sock,
2269 &state->buf,
2270 0 /* timeout */,
2271 &unread,
2272 &encrypted,
2273 &state->buflen,
2274 &state->seqnum,
2275 false /* trusted_channel*/);
2277 if (tevent_req_nterror(req, status)) {
2278 tevent_req_nterror(req, status);
2279 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2280 (int)getpid(), nt_errstr(status)));
2281 return;
2284 ok = smbd_unlock_socket_internal(xconn);
2285 if (!ok) {
2286 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2287 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2288 return;
2290 tevent_req_done(req);
2293 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2294 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2296 struct smbd_echo_read_state *state = tevent_req_data(
2297 req, struct smbd_echo_read_state);
2298 NTSTATUS status;
2300 if (tevent_req_is_nterror(req, &status)) {
2301 return status;
2303 *pbuf = talloc_move(mem_ctx, &state->buf);
2304 *pbuflen = state->buflen;
2305 *pseqnum = state->seqnum;
2306 return NT_STATUS_OK;
2309 struct smbd_echo_state {
2310 struct tevent_context *ev;
2311 struct iovec *pending;
2312 struct smbd_server_connection *sconn;
2313 struct smbXsrv_connection *xconn;
2314 int parent_pipe;
2316 struct tevent_fd *parent_fde;
2318 struct tevent_req *write_req;
2321 static void smbd_echo_writer_done(struct tevent_req *req);
2323 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2325 int num_pending;
2327 if (state->write_req != NULL) {
2328 return;
2331 num_pending = talloc_array_length(state->pending);
2332 if (num_pending == 0) {
2333 return;
2336 state->write_req = writev_send(state, state->ev, NULL,
2337 state->parent_pipe, false,
2338 state->pending, num_pending);
2339 if (state->write_req == NULL) {
2340 DEBUG(1, ("writev_send failed\n"));
2341 exit(1);
2344 talloc_steal(state->write_req, state->pending);
2345 state->pending = NULL;
2347 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2348 state);
2351 static void smbd_echo_writer_done(struct tevent_req *req)
2353 struct smbd_echo_state *state = tevent_req_callback_data(
2354 req, struct smbd_echo_state);
2355 ssize_t written;
2356 int err;
2358 written = writev_recv(req, &err);
2359 TALLOC_FREE(req);
2360 state->write_req = NULL;
2361 if (written == -1) {
2362 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2363 exit(1);
2365 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2366 smbd_echo_activate_writer(state);
2369 static bool smbd_echo_reply(struct smbd_echo_state *state,
2370 uint8_t *inbuf, size_t inbuf_len,
2371 uint32_t seqnum)
2373 struct smb_request req;
2374 uint16_t num_replies;
2375 char *outbuf;
2376 bool ok;
2378 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2379 DEBUG(10, ("Got netbios keepalive\n"));
2381 * Just swallow it
2383 return true;
2386 if (inbuf_len < smb_size) {
2387 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2388 return false;
2390 if (!valid_smb1_header(inbuf)) {
2391 DEBUG(10, ("Got invalid SMB header\n"));
2392 return false;
2395 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2396 seqnum)) {
2397 return false;
2399 req.inbuf = inbuf;
2401 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2402 smb_fn_name(req.cmd)));
2404 if (req.cmd != SMBecho) {
2405 return false;
2407 if (req.wct < 1) {
2408 return false;
2411 num_replies = SVAL(req.vwv+0, 0);
2412 if (num_replies != 1) {
2413 /* Not a Windows "Hey, you're still there?" request */
2414 return false;
2417 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2418 1, req.buflen)) {
2419 DEBUG(10, ("create_smb1_outbuf failed\n"));
2420 return false;
2422 req.outbuf = (uint8_t *)outbuf;
2424 SSVAL(req.outbuf, smb_vwv0, num_replies);
2426 if (req.buflen > 0) {
2427 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2430 ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
2431 TALLOC_FREE(outbuf);
2432 if (!ok) {
2433 exit(1);
2436 return true;
2439 static void smbd_echo_exit(struct tevent_context *ev,
2440 struct tevent_fd *fde, uint16_t flags,
2441 void *private_data)
2443 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2444 exit(0);
2447 static void smbd_echo_got_packet(struct tevent_req *req);
2449 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2450 int parent_pipe)
2452 struct smbd_echo_state *state;
2453 struct tevent_req *read_req;
2455 state = talloc_zero(xconn, struct smbd_echo_state);
2456 if (state == NULL) {
2457 DEBUG(1, ("talloc failed\n"));
2458 return;
2460 state->xconn = xconn;
2461 state->parent_pipe = parent_pipe;
2462 state->ev = samba_tevent_context_init(state);
2463 if (state->ev == NULL) {
2464 DEBUG(1, ("samba_tevent_context_init failed\n"));
2465 TALLOC_FREE(state);
2466 return;
2468 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2469 TEVENT_FD_READ, smbd_echo_exit,
2470 state);
2471 if (state->parent_fde == NULL) {
2472 DEBUG(1, ("tevent_add_fd failed\n"));
2473 TALLOC_FREE(state);
2474 return;
2477 read_req = smbd_echo_read_send(state, state->ev, xconn);
2478 if (read_req == NULL) {
2479 DEBUG(1, ("smbd_echo_read_send failed\n"));
2480 TALLOC_FREE(state);
2481 return;
2483 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2485 while (true) {
2486 if (tevent_loop_once(state->ev) == -1) {
2487 DEBUG(1, ("tevent_loop_once failed: %s\n",
2488 strerror(errno)));
2489 break;
2492 TALLOC_FREE(state);
2495 static void smbd_echo_got_packet(struct tevent_req *req)
2497 struct smbd_echo_state *state = tevent_req_callback_data(
2498 req, struct smbd_echo_state);
2499 NTSTATUS status;
2500 char *buf = NULL;
2501 size_t buflen = 0;
2502 uint32_t seqnum = 0;
2503 bool reply;
2505 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2506 TALLOC_FREE(req);
2507 if (!NT_STATUS_IS_OK(status)) {
2508 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2509 nt_errstr(status)));
2510 exit(1);
2513 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2514 if (!reply) {
2515 size_t num_pending;
2516 struct iovec *tmp;
2517 struct iovec *iov;
2519 num_pending = talloc_array_length(state->pending);
2520 tmp = talloc_realloc(state, state->pending, struct iovec,
2521 num_pending+1);
2522 if (tmp == NULL) {
2523 DEBUG(1, ("talloc_realloc failed\n"));
2524 exit(1);
2526 state->pending = tmp;
2528 if (buflen >= smb_size) {
2530 * place the seqnum in the packet so that the main process
2531 * can reply with signing
2533 SIVAL(buf, smb_ss_field, seqnum);
2534 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2537 iov = &state->pending[num_pending];
2538 iov->iov_base = talloc_move(state->pending, &buf);
2539 iov->iov_len = buflen;
2541 DEBUG(10,("echo_handler[%d]: forward to main\n",
2542 (int)getpid()));
2543 smbd_echo_activate_writer(state);
2546 req = smbd_echo_read_send(state, state->ev, state->xconn);
2547 if (req == NULL) {
2548 DEBUG(1, ("smbd_echo_read_send failed\n"));
2549 exit(1);
2551 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2556 * Handle SMBecho requests in a forked child process
2558 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2560 int listener_pipe[2];
2561 int res;
2562 pid_t child;
2563 bool use_mutex = false;
2565 res = pipe(listener_pipe);
2566 if (res == -1) {
2567 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2568 return false;
2571 #ifdef HAVE_ROBUST_MUTEXES
2572 use_mutex = tdb_runtime_check_for_robust_mutexes();
2574 if (use_mutex) {
2575 pthread_mutexattr_t a;
2577 xconn->smb1.echo_handler.socket_mutex =
2578 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2579 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2580 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2581 strerror(errno)));
2582 goto fail;
2585 res = pthread_mutexattr_init(&a);
2586 if (res != 0) {
2587 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2588 strerror(res)));
2589 goto fail;
2591 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2592 if (res != 0) {
2593 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2594 strerror(res)));
2595 pthread_mutexattr_destroy(&a);
2596 goto fail;
2598 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2599 if (res != 0) {
2600 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2601 strerror(res)));
2602 pthread_mutexattr_destroy(&a);
2603 goto fail;
2605 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2606 if (res != 0) {
2607 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2608 "%s\n", strerror(res)));
2609 pthread_mutexattr_destroy(&a);
2610 goto fail;
2612 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2613 &a);
2614 pthread_mutexattr_destroy(&a);
2615 if (res != 0) {
2616 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2617 strerror(res)));
2618 goto fail;
2621 #endif
2623 if (!use_mutex) {
2624 xconn->smb1.echo_handler.socket_lock_fd =
2625 create_unlink_tmp(lp_lock_directory());
2626 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2627 DEBUG(1, ("Could not create lock fd: %s\n",
2628 strerror(errno)));
2629 goto fail;
2633 child = fork();
2634 if (child == 0) {
2635 NTSTATUS status;
2637 close(listener_pipe[0]);
2638 set_blocking(listener_pipe[1], false);
2640 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2641 xconn->client->raw_ev_ctx,
2642 true);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 DEBUG(1, ("reinit_after_fork failed: %s\n",
2645 nt_errstr(status)));
2646 exit(1);
2648 process_set_title("smbd-echo", "echo handler");
2649 initialize_password_db(true, xconn->client->raw_ev_ctx);
2650 smbd_echo_loop(xconn, listener_pipe[1]);
2651 exit(0);
2653 close(listener_pipe[1]);
2654 listener_pipe[1] = -1;
2655 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2657 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2660 * Without smb signing this is the same as the normal smbd
2661 * listener. This needs to change once signing comes in.
2663 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2664 xconn->client->raw_ev_ctx,
2665 xconn,
2666 xconn->smb1.echo_handler.trusted_fd,
2667 TEVENT_FD_READ,
2668 smbd_server_echo_handler,
2669 xconn);
2670 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2671 DEBUG(1, ("event_add_fd failed\n"));
2672 goto fail;
2675 return true;
2677 fail:
2678 if (listener_pipe[0] != -1) {
2679 close(listener_pipe[0]);
2681 if (listener_pipe[1] != -1) {
2682 close(listener_pipe[1]);
2684 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2685 close(xconn->smb1.echo_handler.socket_lock_fd);
2687 #ifdef HAVE_ROBUST_MUTEXES
2688 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2689 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2690 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2692 #endif
2693 smbd_echo_init(xconn);
2695 return false;
2698 bool req_is_in_chain(const struct smb_request *req)
2700 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2702 * We're right now handling a subsequent request, so we must
2703 * be in a chain
2705 return true;
2708 if (!smb1cli_is_andx_req(req->cmd)) {
2709 return false;
2712 if (req->wct < 2) {
2714 * Okay, an illegal request, but definitely not chained :-)
2716 return false;
2719 return (CVAL(req->vwv+0, 0) != 0xFF);