s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / smbd / smb1_process.c
blob1834c67b91f5de912f6299ca5700964ac31843b6
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 struct smb_perfcount_data pcd;
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, char *buffer,
212 bool do_signing, uint32_t seqnum,
213 bool do_encrypt,
214 struct smb_perfcount_data *pcd)
216 size_t len = 0;
217 ssize_t ret;
218 char *buf_out = buffer;
220 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
222 * we're not supposed to do any io
224 return true;
227 smbd_lock_socket(xconn);
229 if (do_signing) {
230 NTSTATUS status;
232 /* Sign the outgoing packet if required. */
233 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
234 if (!NT_STATUS_IS_OK(status)) {
235 DBG_ERR("Failed to calculate signing mac: %s\n",
236 nt_errstr(status));
237 return false;
241 if (do_encrypt) {
242 char *enc = NULL;
243 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &enc);
244 if (!NT_STATUS_IS_OK(status)) {
245 DEBUG(0, ("send_smb: SMB encryption failed "
246 "on outgoing packet! Error %s\n",
247 nt_errstr(status) ));
248 SAFE_FREE(enc);
249 ret = -1;
250 goto out;
252 buf_out = enc;
255 len = smb_len_large(buf_out) + 4;
257 ret = write_data(xconn->transport.sock, buf_out, len);
258 if (ret <= 0) {
259 int saved_errno = errno;
261 * Try and give an error message saying what
262 * client failed.
264 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
265 (int)getpid(), (int)len,
266 smbXsrv_connection_dbg(xconn),
267 (int)ret, strerror(saved_errno)));
268 errno = saved_errno;
270 srv_free_enc_buffer(xconn, buf_out);
271 goto out;
274 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
275 srv_free_enc_buffer(xconn, buf_out);
276 out:
277 SMB_PERFCOUNT_END(pcd);
279 smbd_unlock_socket(xconn);
280 return (ret > 0);
283 /* Socket functions for smbd packet processing. */
285 static bool valid_packet_size(size_t len)
288 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
289 * of header. Don't print the error if this fits.... JRA.
292 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
293 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
294 (unsigned long)len));
295 return false;
297 return true;
300 /****************************************************************************
301 Attempt a zerocopy writeX read. We know here that len > smb_size-4
302 ****************************************************************************/
305 * Unfortunately, earlier versions of smbclient/libsmbclient
306 * don't send this "standard" writeX header. I've fixed this
307 * for 3.2 but we'll use the old method with earlier versions.
308 * Windows and CIFSFS at least use this standard size. Not
309 * sure about MacOSX.
312 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
313 (2*14) + /* word count (including bcc) */ \
314 1 /* pad byte */)
316 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
317 const char lenbuf[4],
318 struct smbXsrv_connection *xconn,
319 int sock,
320 char **buffer,
321 unsigned int timeout,
322 size_t *p_unread,
323 size_t *len_ret)
325 /* Size of a WRITEX call (+4 byte len). */
326 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
327 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
328 ssize_t toread;
329 NTSTATUS status;
331 memcpy(writeX_header, lenbuf, 4);
333 status = read_fd_with_timeout(
334 sock, writeX_header + 4,
335 STANDARD_WRITE_AND_X_HEADER_SIZE,
336 STANDARD_WRITE_AND_X_HEADER_SIZE,
337 timeout, NULL);
339 if (!NT_STATUS_IS_OK(status)) {
340 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
341 "error = %s.\n",
342 smbXsrv_connection_dbg(xconn),
343 nt_errstr(status)));
344 return status;
348 * Ok - now try and see if this is a possible
349 * valid writeX call.
352 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
354 * If the data offset is beyond what
355 * we've read, drain the extra bytes.
357 uint16_t doff = SVAL(writeX_header,smb_vwv11);
358 ssize_t newlen;
360 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
361 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
362 if (drain_socket(sock, drain) != drain) {
363 smb_panic("receive_smb_raw_talloc_partial_read:"
364 " failed to drain pending bytes");
366 } else {
367 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
370 /* Spoof down the length and null out the bcc. */
371 set_message_bcc(writeX_header, 0);
372 newlen = smb_len(writeX_header);
374 /* Copy the header we've written. */
376 *buffer = (char *)talloc_memdup(mem_ctx,
377 writeX_header,
378 sizeof(writeX_header));
380 if (*buffer == NULL) {
381 DEBUG(0, ("Could not allocate inbuf of length %d\n",
382 (int)sizeof(writeX_header)));
383 return NT_STATUS_NO_MEMORY;
386 /* Work out the remaining bytes. */
387 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
388 *len_ret = newlen + 4;
389 return NT_STATUS_OK;
392 if (!valid_packet_size(len)) {
393 return NT_STATUS_INVALID_PARAMETER;
397 * Not a valid writeX call. Just do the standard
398 * talloc and return.
401 *buffer = talloc_array(mem_ctx, char, len+4);
403 if (*buffer == NULL) {
404 DEBUG(0, ("Could not allocate inbuf of length %d\n",
405 (int)len+4));
406 return NT_STATUS_NO_MEMORY;
409 /* Copy in what we already read. */
410 memcpy(*buffer,
411 writeX_header,
412 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
413 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
415 if(toread > 0) {
416 status = read_packet_remainder(
417 sock,
418 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
419 timeout, toread);
421 if (!NT_STATUS_IS_OK(status)) {
422 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
423 nt_errstr(status)));
424 return status;
428 *len_ret = len + 4;
429 return NT_STATUS_OK;
432 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
433 struct smbXsrv_connection *xconn,
434 int sock,
435 char **buffer, unsigned int timeout,
436 size_t *p_unread, size_t *plen)
438 char lenbuf[4];
439 size_t len;
440 int min_recv_size = lp_min_receive_file_size();
441 NTSTATUS status;
443 *p_unread = 0;
445 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
446 &len);
447 if (!NT_STATUS_IS_OK(status)) {
448 return status;
451 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
452 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
453 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
454 !smb1_srv_is_signing_active(xconn) &&
455 xconn->smb1.echo_handler.trusted_fde == NULL) {
457 return receive_smb_raw_talloc_partial_read(
458 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
459 p_unread, plen);
462 if (!valid_packet_size(len)) {
463 return NT_STATUS_INVALID_PARAMETER;
467 * The +4 here can't wrap, we've checked the length above already.
470 *buffer = talloc_array(mem_ctx, char, len+4);
472 if (*buffer == NULL) {
473 DEBUG(0, ("Could not allocate inbuf of length %d\n",
474 (int)len+4));
475 return NT_STATUS_NO_MEMORY;
478 memcpy(*buffer, lenbuf, sizeof(lenbuf));
480 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
481 if (!NT_STATUS_IS_OK(status)) {
482 return status;
485 *plen = len + 4;
486 return NT_STATUS_OK;
489 NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
490 struct smbXsrv_connection *xconn,
491 int sock,
492 char **buffer, unsigned int timeout,
493 size_t *p_unread, bool *p_encrypted,
494 size_t *p_len,
495 uint32_t *seqnum,
496 bool trusted_channel)
498 size_t len = 0;
499 NTSTATUS status;
501 *p_encrypted = false;
503 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
504 p_unread, &len);
505 if (!NT_STATUS_IS_OK(status)) {
506 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
507 ("receive_smb_raw_talloc failed for client %s "
508 "read error = %s.\n",
509 smbXsrv_connection_dbg(xconn),
510 nt_errstr(status)) );
511 return status;
514 if (is_encrypted_packet((uint8_t *)*buffer)) {
515 status = srv_decrypt_buffer(xconn, *buffer);
516 if (!NT_STATUS_IS_OK(status)) {
517 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
518 "incoming packet! Error %s\n",
519 nt_errstr(status) ));
520 return status;
522 *p_encrypted = true;
525 /* Check the incoming SMB signature. */
526 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
527 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
528 "incoming packet!\n"));
529 return NT_STATUS_INVALID_NETWORK_RESPONSE;
532 *p_len = len;
533 return NT_STATUS_OK;
536 /****************************************************************************
537 Function to push a message onto the tail of a linked list of smb messages ready
538 for processing.
539 ****************************************************************************/
541 static bool push_queued_message(struct smb_request *req,
542 struct timeval request_time,
543 struct timeval end_time,
544 struct deferred_open_record *open_rec)
546 int msg_len = smb_len(req->inbuf) + 4;
547 struct pending_message_list *msg;
549 msg = talloc_zero(NULL, struct pending_message_list);
551 if(msg == NULL) {
552 DEBUG(0,("push_message: malloc fail (1)\n"));
553 return False;
555 msg->sconn = req->sconn;
556 msg->xconn = req->xconn;
558 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
559 if(msg->buf.data == NULL) {
560 DEBUG(0,("push_message: malloc fail (2)\n"));
561 TALLOC_FREE(msg);
562 return False;
565 msg->request_time = request_time;
566 msg->seqnum = req->seqnum;
567 msg->encrypted = req->encrypted;
568 msg->processed = false;
569 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
571 if (open_rec) {
572 msg->open_rec = talloc_move(msg, &open_rec);
575 #if 0
576 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
577 msg,
578 end_time,
579 smbd_deferred_open_timer,
580 msg);
581 if (!msg->te) {
582 DEBUG(0,("push_message: event_add_timed failed\n"));
583 TALLOC_FREE(msg);
584 return false;
586 #endif
588 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
590 DEBUG(10,("push_message: pushed message length %u on "
591 "deferred_open_queue\n", (unsigned int)msg_len));
593 return True;
596 /****************************************************************************
597 Function to push a deferred open smb message onto a linked list of local smb
598 messages ready for processing.
599 ****************************************************************************/
601 bool push_deferred_open_message_smb1(struct smb_request *req,
602 struct timeval timeout,
603 struct file_id id,
604 struct deferred_open_record *open_rec)
606 struct timeval_buf tvbuf;
607 struct timeval end_time;
609 if (req->unread_bytes) {
610 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
611 "unread_bytes = %u\n",
612 (unsigned int)req->unread_bytes ));
613 smb_panic("push_deferred_open_message_smb: "
614 "logic error unread_bytes != 0" );
617 end_time = timeval_sum(&req->request_time, &timeout);
619 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
620 (unsigned int) smb_len(req->inbuf)+4,
621 req->mid,
622 timeval_str_buf(&end_time, false, true, &tvbuf));
624 return push_queued_message(req, req->request_time, end_time, open_rec);
628 * Only allow 5 outstanding trans requests. We're allocating memory, so
629 * prevent a DoS.
632 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
634 int count = 0;
635 for (; list != NULL; list = list->next) {
637 if (list->mid == mid) {
638 return NT_STATUS_INVALID_PARAMETER;
641 count += 1;
643 if (count > 5) {
644 return NT_STATUS_INSUFFICIENT_RESOURCES;
647 return NT_STATUS_OK;
651 These flags determine some of the permissions required to do an operation
653 Note that I don't set NEED_WRITE on some write operations because they
654 are used by some brain-dead clients when printing, and I don't want to
655 force write permissions on print services.
657 #define AS_USER (1<<0)
658 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
659 #define TIME_INIT (1<<2)
660 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
661 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
662 #define DO_CHDIR (1<<6)
665 define a list of possible SMB messages and their corresponding
666 functions. Any message that has a NULL function is unimplemented -
667 please feel free to contribute implementations!
669 static const struct smb_message_struct {
670 const char *name;
671 void (*fn)(struct smb_request *req);
672 int flags;
673 } smb_messages[256] = {
675 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
676 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
677 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
678 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
679 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
680 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
681 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
682 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
683 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
684 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
685 /* 0x0a */ { "SMBread",reply_read,AS_USER},
686 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
687 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
688 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
689 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
690 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
691 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
692 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
693 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
694 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
695 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
696 /* 0x15 */ { NULL, NULL, 0 },
697 /* 0x16 */ { NULL, NULL, 0 },
698 /* 0x17 */ { NULL, NULL, 0 },
699 /* 0x18 */ { NULL, NULL, 0 },
700 /* 0x19 */ { NULL, NULL, 0 },
701 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
702 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
703 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
704 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
705 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
706 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
707 /* 0x20 */ { "SMBwritec", NULL,0},
708 /* 0x21 */ { NULL, NULL, 0 },
709 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
710 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
711 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
712 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
713 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
714 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
715 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
716 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
717 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
718 /* 0x2b */ { "SMBecho",reply_echo,0},
719 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
720 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
721 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
722 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
723 /* 0x30 */ { NULL, NULL, 0 },
724 /* 0x31 */ { NULL, NULL, 0 },
725 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
726 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
727 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
728 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
729 /* 0x36 */ { NULL, NULL, 0 },
730 /* 0x37 */ { NULL, NULL, 0 },
731 /* 0x38 */ { NULL, NULL, 0 },
732 /* 0x39 */ { NULL, NULL, 0 },
733 /* 0x3a */ { NULL, NULL, 0 },
734 /* 0x3b */ { NULL, NULL, 0 },
735 /* 0x3c */ { NULL, NULL, 0 },
736 /* 0x3d */ { NULL, NULL, 0 },
737 /* 0x3e */ { NULL, NULL, 0 },
738 /* 0x3f */ { NULL, NULL, 0 },
739 /* 0x40 */ { NULL, NULL, 0 },
740 /* 0x41 */ { NULL, NULL, 0 },
741 /* 0x42 */ { NULL, NULL, 0 },
742 /* 0x43 */ { NULL, NULL, 0 },
743 /* 0x44 */ { NULL, NULL, 0 },
744 /* 0x45 */ { NULL, NULL, 0 },
745 /* 0x46 */ { NULL, NULL, 0 },
746 /* 0x47 */ { NULL, NULL, 0 },
747 /* 0x48 */ { NULL, NULL, 0 },
748 /* 0x49 */ { NULL, NULL, 0 },
749 /* 0x4a */ { NULL, NULL, 0 },
750 /* 0x4b */ { NULL, NULL, 0 },
751 /* 0x4c */ { NULL, NULL, 0 },
752 /* 0x4d */ { NULL, NULL, 0 },
753 /* 0x4e */ { NULL, NULL, 0 },
754 /* 0x4f */ { NULL, NULL, 0 },
755 /* 0x50 */ { NULL, NULL, 0 },
756 /* 0x51 */ { NULL, NULL, 0 },
757 /* 0x52 */ { NULL, NULL, 0 },
758 /* 0x53 */ { NULL, NULL, 0 },
759 /* 0x54 */ { NULL, NULL, 0 },
760 /* 0x55 */ { NULL, NULL, 0 },
761 /* 0x56 */ { NULL, NULL, 0 },
762 /* 0x57 */ { NULL, NULL, 0 },
763 /* 0x58 */ { NULL, NULL, 0 },
764 /* 0x59 */ { NULL, NULL, 0 },
765 /* 0x5a */ { NULL, NULL, 0 },
766 /* 0x5b */ { NULL, NULL, 0 },
767 /* 0x5c */ { NULL, NULL, 0 },
768 /* 0x5d */ { NULL, NULL, 0 },
769 /* 0x5e */ { NULL, NULL, 0 },
770 /* 0x5f */ { NULL, NULL, 0 },
771 /* 0x60 */ { NULL, NULL, 0 },
772 /* 0x61 */ { NULL, NULL, 0 },
773 /* 0x62 */ { NULL, NULL, 0 },
774 /* 0x63 */ { NULL, NULL, 0 },
775 /* 0x64 */ { NULL, NULL, 0 },
776 /* 0x65 */ { NULL, NULL, 0 },
777 /* 0x66 */ { NULL, NULL, 0 },
778 /* 0x67 */ { NULL, NULL, 0 },
779 /* 0x68 */ { NULL, NULL, 0 },
780 /* 0x69 */ { NULL, NULL, 0 },
781 /* 0x6a */ { NULL, NULL, 0 },
782 /* 0x6b */ { NULL, NULL, 0 },
783 /* 0x6c */ { NULL, NULL, 0 },
784 /* 0x6d */ { NULL, NULL, 0 },
785 /* 0x6e */ { NULL, NULL, 0 },
786 /* 0x6f */ { NULL, NULL, 0 },
787 /* 0x70 */ { "SMBtcon",reply_tcon,0},
788 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
789 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
790 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
791 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
792 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
793 /* 0x76 */ { NULL, NULL, 0 },
794 /* 0x77 */ { NULL, NULL, 0 },
795 /* 0x78 */ { NULL, NULL, 0 },
796 /* 0x79 */ { NULL, NULL, 0 },
797 /* 0x7a */ { NULL, NULL, 0 },
798 /* 0x7b */ { NULL, NULL, 0 },
799 /* 0x7c */ { NULL, NULL, 0 },
800 /* 0x7d */ { NULL, NULL, 0 },
801 /* 0x7e */ { NULL, NULL, 0 },
802 /* 0x7f */ { NULL, NULL, 0 },
803 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
804 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
805 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
806 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
807 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
808 /* 0x85 */ { NULL, NULL, 0 },
809 /* 0x86 */ { NULL, NULL, 0 },
810 /* 0x87 */ { NULL, NULL, 0 },
811 /* 0x88 */ { NULL, NULL, 0 },
812 /* 0x89 */ { NULL, NULL, 0 },
813 /* 0x8a */ { NULL, NULL, 0 },
814 /* 0x8b */ { NULL, NULL, 0 },
815 /* 0x8c */ { NULL, NULL, 0 },
816 /* 0x8d */ { NULL, NULL, 0 },
817 /* 0x8e */ { NULL, NULL, 0 },
818 /* 0x8f */ { NULL, NULL, 0 },
819 /* 0x90 */ { NULL, NULL, 0 },
820 /* 0x91 */ { NULL, NULL, 0 },
821 /* 0x92 */ { NULL, NULL, 0 },
822 /* 0x93 */ { NULL, NULL, 0 },
823 /* 0x94 */ { NULL, NULL, 0 },
824 /* 0x95 */ { NULL, NULL, 0 },
825 /* 0x96 */ { NULL, NULL, 0 },
826 /* 0x97 */ { NULL, NULL, 0 },
827 /* 0x98 */ { NULL, NULL, 0 },
828 /* 0x99 */ { NULL, NULL, 0 },
829 /* 0x9a */ { NULL, NULL, 0 },
830 /* 0x9b */ { NULL, NULL, 0 },
831 /* 0x9c */ { NULL, NULL, 0 },
832 /* 0x9d */ { NULL, NULL, 0 },
833 /* 0x9e */ { NULL, NULL, 0 },
834 /* 0x9f */ { NULL, NULL, 0 },
835 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
836 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
837 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
838 /* 0xa3 */ { NULL, NULL, 0 },
839 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
840 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
841 /* 0xa6 */ { NULL, NULL, 0 },
842 /* 0xa7 */ { NULL, NULL, 0 },
843 /* 0xa8 */ { NULL, NULL, 0 },
844 /* 0xa9 */ { NULL, NULL, 0 },
845 /* 0xaa */ { NULL, NULL, 0 },
846 /* 0xab */ { NULL, NULL, 0 },
847 /* 0xac */ { NULL, NULL, 0 },
848 /* 0xad */ { NULL, NULL, 0 },
849 /* 0xae */ { NULL, NULL, 0 },
850 /* 0xaf */ { NULL, NULL, 0 },
851 /* 0xb0 */ { NULL, NULL, 0 },
852 /* 0xb1 */ { NULL, NULL, 0 },
853 /* 0xb2 */ { NULL, NULL, 0 },
854 /* 0xb3 */ { NULL, NULL, 0 },
855 /* 0xb4 */ { NULL, NULL, 0 },
856 /* 0xb5 */ { NULL, NULL, 0 },
857 /* 0xb6 */ { NULL, NULL, 0 },
858 /* 0xb7 */ { NULL, NULL, 0 },
859 /* 0xb8 */ { NULL, NULL, 0 },
860 /* 0xb9 */ { NULL, NULL, 0 },
861 /* 0xba */ { NULL, NULL, 0 },
862 /* 0xbb */ { NULL, NULL, 0 },
863 /* 0xbc */ { NULL, NULL, 0 },
864 /* 0xbd */ { NULL, NULL, 0 },
865 /* 0xbe */ { NULL, NULL, 0 },
866 /* 0xbf */ { NULL, NULL, 0 },
867 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
868 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
869 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
870 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
871 /* 0xc4 */ { NULL, NULL, 0 },
872 /* 0xc5 */ { NULL, NULL, 0 },
873 /* 0xc6 */ { NULL, NULL, 0 },
874 /* 0xc7 */ { NULL, NULL, 0 },
875 /* 0xc8 */ { NULL, NULL, 0 },
876 /* 0xc9 */ { NULL, NULL, 0 },
877 /* 0xca */ { NULL, NULL, 0 },
878 /* 0xcb */ { NULL, NULL, 0 },
879 /* 0xcc */ { NULL, NULL, 0 },
880 /* 0xcd */ { NULL, NULL, 0 },
881 /* 0xce */ { NULL, NULL, 0 },
882 /* 0xcf */ { NULL, NULL, 0 },
883 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
884 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
885 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
886 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
887 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
888 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
889 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
890 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
891 /* 0xd8 */ { NULL, NULL, 0 },
892 /* 0xd9 */ { NULL, NULL, 0 },
893 /* 0xda */ { NULL, NULL, 0 },
894 /* 0xdb */ { NULL, NULL, 0 },
895 /* 0xdc */ { NULL, NULL, 0 },
896 /* 0xdd */ { NULL, NULL, 0 },
897 /* 0xde */ { NULL, NULL, 0 },
898 /* 0xdf */ { NULL, NULL, 0 },
899 /* 0xe0 */ { NULL, NULL, 0 },
900 /* 0xe1 */ { NULL, NULL, 0 },
901 /* 0xe2 */ { NULL, NULL, 0 },
902 /* 0xe3 */ { NULL, NULL, 0 },
903 /* 0xe4 */ { NULL, NULL, 0 },
904 /* 0xe5 */ { NULL, NULL, 0 },
905 /* 0xe6 */ { NULL, NULL, 0 },
906 /* 0xe7 */ { NULL, NULL, 0 },
907 /* 0xe8 */ { NULL, NULL, 0 },
908 /* 0xe9 */ { NULL, NULL, 0 },
909 /* 0xea */ { NULL, NULL, 0 },
910 /* 0xeb */ { NULL, NULL, 0 },
911 /* 0xec */ { NULL, NULL, 0 },
912 /* 0xed */ { NULL, NULL, 0 },
913 /* 0xee */ { NULL, NULL, 0 },
914 /* 0xef */ { NULL, NULL, 0 },
915 /* 0xf0 */ { NULL, NULL, 0 },
916 /* 0xf1 */ { NULL, NULL, 0 },
917 /* 0xf2 */ { NULL, NULL, 0 },
918 /* 0xf3 */ { NULL, NULL, 0 },
919 /* 0xf4 */ { NULL, NULL, 0 },
920 /* 0xf5 */ { NULL, NULL, 0 },
921 /* 0xf6 */ { NULL, NULL, 0 },
922 /* 0xf7 */ { NULL, NULL, 0 },
923 /* 0xf8 */ { NULL, NULL, 0 },
924 /* 0xf9 */ { NULL, NULL, 0 },
925 /* 0xfa */ { NULL, NULL, 0 },
926 /* 0xfb */ { NULL, NULL, 0 },
927 /* 0xfc */ { NULL, NULL, 0 },
928 /* 0xfd */ { NULL, NULL, 0 },
929 /* 0xfe */ { NULL, NULL, 0 },
930 /* 0xff */ { NULL, NULL, 0 }
935 /*******************************************************************
936 Dump a packet to a file.
937 ********************************************************************/
939 static void smb_dump(const char *name, int type, const char *data)
941 size_t len;
942 int fd, i;
943 char *fname = NULL;
944 if (DEBUGLEVEL < 50) {
945 return;
948 len = smb_len_tcp(data)+4;
949 for (i=1;i<100;i++) {
950 fname = talloc_asprintf(talloc_tos(),
951 "/tmp/%s.%d.%s",
952 name,
954 type ? "req" : "resp");
955 if (fname == NULL) {
956 return;
958 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
959 if (fd != -1 || errno != EEXIST) break;
960 TALLOC_FREE(fname);
962 if (fd != -1) {
963 ssize_t ret = write(fd, data, len);
964 if (ret != len)
965 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
966 close(fd);
967 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
969 TALLOC_FREE(fname);
972 static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
973 struct smb_request *req,
974 uint8_t type,
975 bool *update_session_globalp,
976 bool *update_tcon_globalp)
978 connection_struct *conn = req->conn;
979 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
980 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
981 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
982 bool update_session = false;
983 bool update_tcon = false;
985 if (req->encrypted) {
986 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
989 if (smb1_srv_is_signing_active(req->xconn)) {
990 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
991 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
993 * echo can be unsigned. Sesssion setup except final
994 * session setup response too
996 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
999 update_session |= smbXsrv_set_crypto_flag(
1000 &session->global->encryption_flags, encrypt_flag);
1001 update_session |= smbXsrv_set_crypto_flag(
1002 &session->global->signing_flags, sign_flag);
1004 if (tcon) {
1005 update_tcon |= smbXsrv_set_crypto_flag(
1006 &tcon->global->encryption_flags, encrypt_flag);
1007 update_tcon |= smbXsrv_set_crypto_flag(
1008 &tcon->global->signing_flags, sign_flag);
1011 if (update_session) {
1012 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1015 *update_session_globalp = update_session;
1016 *update_tcon_globalp = update_tcon;
1017 return;
1020 static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1022 int snum;
1023 enum remote_arch_types ra_type;
1025 SMB_ASSERT(conn != NULL);
1026 SMB_ASSERT(!conn->sconn->using_smb2);
1028 snum = SNUM(conn);
1031 * Obey the client case sensitivity requests - only for clients that
1032 * support it. */
1033 switch (lp_case_sensitive(snum)) {
1034 case Auto:
1036 * We need this uglyness due to DOS/Win9x clients that lie
1037 * about case insensitivity. */
1038 ra_type = get_remote_arch();
1039 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1041 * Client can't support per-packet case sensitive
1042 * pathnames. */
1043 conn->case_sensitive = false;
1044 } else {
1045 conn->case_sensitive =
1046 !(flags & FLAG_CASELESS_PATHNAMES);
1048 break;
1049 case True:
1050 conn->case_sensitive = true;
1051 break;
1052 default:
1053 conn->case_sensitive = false;
1054 break;
1058 /****************************************************************************
1059 Prepare everything for calling the actual request function, and potentially
1060 call the request function via the "new" interface.
1062 Return False if the "legacy" function needs to be called, everything is
1063 prepared.
1065 Return True if we're done.
1067 I know this API sucks, but it is the one with the least code change I could
1068 find.
1069 ****************************************************************************/
1071 static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1073 const struct loadparm_substitution *lp_sub =
1074 loadparm_s3_global_substitution();
1075 int flags;
1076 uint64_t session_tag;
1077 connection_struct *conn = NULL;
1078 struct smbXsrv_connection *xconn = req->xconn;
1079 NTTIME now = timeval_to_nttime(&req->request_time);
1080 struct smbXsrv_session *session = NULL;
1081 NTSTATUS status;
1083 errno = 0;
1085 if (!xconn->smb1.negprot.done) {
1086 switch (type) {
1088 * Without a negprot the request must
1089 * either be a negprot, or one of the
1090 * evil old SMB mailslot messaging types.
1092 case SMBnegprot:
1093 case SMBsendstrt:
1094 case SMBsendend:
1095 case SMBsendtxt:
1096 break;
1097 default:
1098 exit_server_cleanly("The first request "
1099 "should be a negprot");
1103 if (smb_messages[type].fn == NULL) {
1104 DEBUG(0,("Unknown message type %d!\n",type));
1105 smb_dump("Unknown", 1, (const char *)req->inbuf);
1106 reply_unknown_new(req, type);
1107 return NULL;
1110 flags = smb_messages[type].flags;
1112 /* In share mode security we must ignore the vuid. */
1113 session_tag = req->vuid;
1114 conn = req->conn;
1116 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1117 (int)getpid(), (unsigned long)conn));
1119 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1121 /* Ensure this value is replaced in the incoming packet. */
1122 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1125 * Ensure the correct username is in current_user_info. This is a
1126 * really ugly bugfix for problems with multiple session_setup_and_X's
1127 * being done and allowing %U and %G substitutions to work correctly.
1128 * There is a reason this code is done here, don't move it unless you
1129 * know what you're doing... :-).
1130 * JRA.
1134 * lookup an existing session
1136 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1137 * here, the main check is still in change_to_user()
1139 status = smb1srv_session_lookup(xconn,
1140 session_tag,
1141 now,
1142 &session);
1143 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1144 switch (type) {
1145 case SMBsesssetupX:
1146 status = NT_STATUS_OK;
1147 break;
1148 default:
1149 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1150 (unsigned long long)session_tag,
1151 (unsigned long long)req->mid));
1152 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1153 return conn;
1157 if (session != NULL &&
1158 session->global->auth_session_info != NULL &&
1159 !(flags & AS_USER))
1162 * change_to_user() implies set_current_user_info()
1163 * and chdir_connect_service().
1165 * So we only call set_current_user_info if
1166 * we don't have AS_USER specified.
1168 set_current_user_info(
1169 session->global->auth_session_info->unix_info->sanitized_username,
1170 session->global->auth_session_info->unix_info->unix_name,
1171 session->global->auth_session_info->info->domain_name);
1174 /* Does this call need to be run as the connected user? */
1175 if (flags & AS_USER) {
1177 /* Does this call need a valid tree connection? */
1178 if (!conn) {
1180 * Amazingly, the error code depends on the command
1181 * (from Samba4).
1183 if (type == SMBntcreateX) {
1184 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1185 } else {
1186 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1188 return NULL;
1191 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1194 * change_to_user() implies set_current_user_info()
1195 * and chdir_connect_service().
1197 if (!change_to_user_and_service(conn,session_tag)) {
1198 DEBUG(0, ("Error: Could not change to user. Removing "
1199 "deferred open, mid=%llu.\n",
1200 (unsigned long long)req->mid));
1201 reply_force_doserror(req, ERRSRV, ERRbaduid);
1202 return conn;
1205 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1207 /* Does it need write permission? */
1208 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1209 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1210 return conn;
1213 /* IPC services are limited */
1214 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1215 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1216 return conn;
1218 } else if (flags & AS_GUEST) {
1220 * Does this protocol need to be run as guest? (Only archane
1221 * messenger service requests have this...)
1223 if (!change_to_guest()) {
1224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1225 return conn;
1227 } else {
1228 /* This call needs to be run as root */
1229 change_to_root_user();
1232 /* load service specific parameters */
1233 if (conn) {
1234 if (req->encrypted) {
1235 conn->encrypted_tid = true;
1236 /* encrypted required from now on. */
1237 conn->encrypt_level = SMB_SIGNING_REQUIRED;
1238 } else if (ENCRYPTION_REQUIRED(conn)) {
1239 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1240 DEBUG(1,("service[%s] requires encryption"
1241 "%s ACCESS_DENIED. mid=%llu\n",
1242 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1243 smb_fn_name(type),
1244 (unsigned long long)req->mid));
1245 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1246 return conn;
1250 if (flags & DO_CHDIR) {
1251 bool ok;
1253 ok = chdir_current_service(conn);
1254 if (!ok) {
1255 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1256 return conn;
1259 conn->num_smb_operations++;
1263 * Update encryption and signing state tracking flags that are
1264 * used by smbstatus to display signing and encryption status.
1266 if (session != NULL) {
1267 bool update_session_global = false;
1268 bool update_tcon_global = false;
1270 req->session = session;
1272 smb1srv_update_crypto_flags(session, req, type,
1273 &update_session_global,
1274 &update_tcon_global);
1276 if (update_session_global) {
1277 status = smbXsrv_session_update(session);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1280 return conn;
1284 if (update_tcon_global) {
1285 status = smbXsrv_tcon_update(req->conn->tcon);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1288 return conn;
1293 smb_messages[type].fn(req);
1294 return req->conn;
1297 /****************************************************************************
1298 Construct a reply to the incoming packet.
1299 ****************************************************************************/
1301 void construct_reply(struct smbXsrv_connection *xconn,
1302 char *inbuf, int size, size_t unread_bytes,
1303 uint32_t seqnum, bool encrypted,
1304 struct smb_perfcount_data *deferred_pcd)
1306 struct smbd_server_connection *sconn = xconn->client->sconn;
1307 struct smb_request *req;
1309 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1310 smb_panic("could not allocate smb_request");
1313 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1314 encrypted, seqnum)) {
1315 exit_server_cleanly("Invalid SMB request");
1318 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1320 /* we popped this message off the queue - keep original perf data */
1321 if (deferred_pcd)
1322 req->pcd = *deferred_pcd;
1323 else {
1324 SMB_PERFCOUNT_START(&req->pcd);
1325 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1326 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1329 req->conn = switch_message(req->cmd, req);
1331 if (req->outbuf == NULL) {
1333 * Request has suspended itself, will come
1334 * back here.
1336 return;
1338 if (CVAL(req->outbuf,0) == 0) {
1339 show_msg((char *)req->outbuf);
1341 smb_request_done(req);
1344 static void construct_reply_chain(struct smbXsrv_connection *xconn,
1345 char *inbuf, int size, uint32_t seqnum,
1346 bool encrypted,
1347 struct smb_perfcount_data *deferred_pcd)
1349 struct smb_request **reqs = NULL;
1350 struct smb_request *req;
1351 unsigned num_reqs;
1352 bool ok;
1354 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1355 seqnum, &reqs, &num_reqs);
1356 if (!ok) {
1357 char errbuf[smb_size];
1358 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1359 __LINE__, __FILE__);
1360 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted,
1361 NULL)) {
1362 exit_server_cleanly("construct_reply_chain: "
1363 "smb1_srv_send failed.");
1365 return;
1368 req = reqs[0];
1369 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1371 req->conn = switch_message(req->cmd, req);
1373 if (req->outbuf == NULL) {
1375 * Request has suspended itself, will come
1376 * back here.
1378 return;
1380 smb_request_done(req);
1384 * To be called from an async SMB handler that is potentially chained
1385 * when it is finished for shipping.
1388 void smb_request_done(struct smb_request *req)
1390 struct smb_request **reqs = NULL;
1391 struct smb_request *first_req;
1392 size_t i, num_reqs, next_index;
1393 NTSTATUS status;
1395 if (req->chain == NULL) {
1396 first_req = req;
1397 goto shipit;
1400 reqs = req->chain;
1401 num_reqs = talloc_array_length(reqs);
1403 for (i=0; i<num_reqs; i++) {
1404 if (reqs[i] == req) {
1405 break;
1408 if (i == num_reqs) {
1410 * Invalid chain, should not happen
1412 status = NT_STATUS_INTERNAL_ERROR;
1413 goto error;
1415 next_index = i+1;
1417 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1418 struct smb_request *next = reqs[next_index];
1419 struct smbXsrv_tcon *tcon;
1420 NTTIME now = timeval_to_nttime(&req->request_time);
1422 next->vuid = SVAL(req->outbuf, smb_uid);
1423 next->tid = SVAL(req->outbuf, smb_tid);
1424 status = smb1srv_tcon_lookup(req->xconn, next->tid,
1425 now, &tcon);
1427 if (NT_STATUS_IS_OK(status)) {
1428 next->conn = tcon->compat;
1429 } else {
1430 next->conn = NULL;
1432 next->chain_fsp = req->chain_fsp;
1433 next->inbuf = req->inbuf;
1435 req = next;
1436 req->conn = switch_message(req->cmd, req);
1438 if (req->outbuf == NULL) {
1440 * Request has suspended itself, will come
1441 * back here.
1443 return;
1445 next_index += 1;
1448 first_req = reqs[0];
1450 for (i=1; i<next_index; i++) {
1451 bool ok;
1453 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1454 if (!ok) {
1455 status = NT_STATUS_INTERNAL_ERROR;
1456 goto error;
1460 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1461 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1464 * This scary statement intends to set the
1465 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1466 * to the value last_req->outbuf carries
1468 SSVAL(first_req->outbuf, smb_flg2,
1469 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1470 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1473 * Transfer the error codes from the subrequest to the main one
1475 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1476 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1478 _smb_setlen_large(
1479 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1481 shipit:
1482 if (!smb1_srv_send(first_req->xconn,
1483 (char *)first_req->outbuf,
1484 true, first_req->seqnum+1,
1485 IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
1486 &first_req->pcd)) {
1487 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1488 "failed.");
1490 TALLOC_FREE(req); /* non-chained case */
1491 TALLOC_FREE(reqs); /* chained case */
1492 return;
1494 error:
1496 char errbuf[smb_size];
1497 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1498 if (!smb1_srv_send(req->xconn, errbuf, true,
1499 req->seqnum+1, req->encrypted,
1500 NULL)) {
1501 exit_server_cleanly("construct_reply_chain: "
1502 "smb1_srv_send failed.");
1505 TALLOC_FREE(req); /* non-chained case */
1506 TALLOC_FREE(reqs); /* chained case */
1509 /****************************************************************************
1510 Process an smb from the client
1511 ****************************************************************************/
1513 void process_smb1(struct smbXsrv_connection *xconn,
1514 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1515 uint32_t seqnum, bool encrypted,
1516 struct smb_perfcount_data *deferred_pcd)
1518 struct smbd_server_connection *sconn = xconn->client->sconn;
1520 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1521 * so subtract 4 from it. */
1522 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1523 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1524 smb_len(inbuf)));
1526 /* special magic for immediate exit */
1527 if ((nread == 9) &&
1528 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1529 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1530 uint8_t exitcode = CVAL(inbuf, 8);
1531 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1532 (int)exitcode);
1533 exit(exitcode);
1536 exit_server_cleanly("Non-SMB packet");
1539 show_msg((char *)inbuf);
1541 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1542 construct_reply_chain(xconn, (char *)inbuf, nread,
1543 seqnum, encrypted, deferred_pcd);
1544 } else {
1545 construct_reply(xconn, (char *)inbuf, nread, unread_bytes,
1546 seqnum, encrypted, deferred_pcd);
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,
2082 seqnum, encrypted, NULL);
2085 static void smbd_server_echo_handler(struct tevent_context *ev,
2086 struct tevent_fd *fde,
2087 uint16_t flags,
2088 void *private_data)
2090 struct smbXsrv_connection *xconn =
2091 talloc_get_type_abort(private_data,
2092 struct smbXsrv_connection);
2094 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2096 * we're not supposed to do any io
2098 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2099 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2100 return;
2103 if (flags & TEVENT_FD_WRITE) {
2104 smbd_server_connection_write_handler(xconn);
2105 return;
2107 if (flags & TEVENT_FD_READ) {
2108 smbd_smb1_server_connection_read_handler(
2109 xconn, xconn->smb1.echo_handler.trusted_fd);
2110 return;
2115 * Send keepalive packets to our client
2117 bool keepalive_fn(const struct timeval *now, void *private_data)
2119 struct smbd_server_connection *sconn = talloc_get_type_abort(
2120 private_data, struct smbd_server_connection);
2121 struct smbXsrv_connection *xconn = NULL;
2122 bool ret;
2124 if (sconn->using_smb2) {
2125 /* Don't do keepalives on an SMB2 connection. */
2126 return false;
2130 * With SMB1 we only have 1 connection
2132 xconn = sconn->client->connections;
2133 smbd_lock_socket(xconn);
2134 ret = send_keepalive(xconn->transport.sock);
2135 smbd_unlock_socket(xconn);
2137 if (!ret) {
2138 int saved_errno = errno;
2140 * Try and give an error message saying what
2141 * client failed.
2143 DEBUG(0, ("send_keepalive failed for client %s. "
2144 "Error %s - exiting\n",
2145 smbXsrv_connection_dbg(xconn),
2146 strerror(saved_errno)));
2147 errno = saved_errno;
2148 return False;
2150 return True;
2154 * Read an smb packet in the echo handler child, giving the parent
2155 * smbd one second to react once the socket becomes readable.
2158 struct smbd_echo_read_state {
2159 struct tevent_context *ev;
2160 struct smbXsrv_connection *xconn;
2162 char *buf;
2163 size_t buflen;
2164 uint32_t seqnum;
2167 static void smbd_echo_read_readable(struct tevent_req *subreq);
2168 static void smbd_echo_read_waited(struct tevent_req *subreq);
2170 static struct tevent_req *smbd_echo_read_send(
2171 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2172 struct smbXsrv_connection *xconn)
2174 struct tevent_req *req, *subreq;
2175 struct smbd_echo_read_state *state;
2177 req = tevent_req_create(mem_ctx, &state,
2178 struct smbd_echo_read_state);
2179 if (req == NULL) {
2180 return NULL;
2182 state->ev = ev;
2183 state->xconn = xconn;
2185 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2186 if (tevent_req_nomem(subreq, req)) {
2187 return tevent_req_post(req, ev);
2189 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2190 return req;
2193 static void smbd_echo_read_readable(struct tevent_req *subreq)
2195 struct tevent_req *req = tevent_req_callback_data(
2196 subreq, struct tevent_req);
2197 struct smbd_echo_read_state *state = tevent_req_data(
2198 req, struct smbd_echo_read_state);
2199 bool ok;
2200 int err;
2202 ok = wait_for_read_recv(subreq, &err);
2203 TALLOC_FREE(subreq);
2204 if (!ok) {
2205 tevent_req_nterror(req, map_nt_error_from_unix(err));
2206 return;
2210 * Give the parent smbd one second to step in
2213 subreq = tevent_wakeup_send(
2214 state, state->ev, timeval_current_ofs(1, 0));
2215 if (tevent_req_nomem(subreq, req)) {
2216 return;
2218 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2221 static void smbd_echo_read_waited(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2225 struct smbd_echo_read_state *state = tevent_req_data(
2226 req, struct smbd_echo_read_state);
2227 struct smbXsrv_connection *xconn = state->xconn;
2228 bool ok;
2229 NTSTATUS status;
2230 size_t unread = 0;
2231 bool encrypted;
2233 ok = tevent_wakeup_recv(subreq);
2234 TALLOC_FREE(subreq);
2235 if (!ok) {
2236 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2237 return;
2240 ok = smbd_lock_socket_internal(xconn);
2241 if (!ok) {
2242 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2243 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2244 return;
2247 if (!fd_is_readable(xconn->transport.sock)) {
2248 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2249 (int)getpid()));
2251 ok = smbd_unlock_socket_internal(xconn);
2252 if (!ok) {
2253 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2254 DEBUG(1, ("%s: failed to unlock socket\n",
2255 __location__));
2256 return;
2259 subreq = wait_for_read_send(state, state->ev,
2260 xconn->transport.sock, false);
2261 if (tevent_req_nomem(subreq, req)) {
2262 return;
2264 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2265 return;
2268 status = receive_smb_talloc(state, xconn,
2269 xconn->transport.sock,
2270 &state->buf,
2271 0 /* timeout */,
2272 &unread,
2273 &encrypted,
2274 &state->buflen,
2275 &state->seqnum,
2276 false /* trusted_channel*/);
2278 if (tevent_req_nterror(req, status)) {
2279 tevent_req_nterror(req, status);
2280 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2281 (int)getpid(), nt_errstr(status)));
2282 return;
2285 ok = smbd_unlock_socket_internal(xconn);
2286 if (!ok) {
2287 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2288 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2289 return;
2291 tevent_req_done(req);
2294 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2295 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2297 struct smbd_echo_read_state *state = tevent_req_data(
2298 req, struct smbd_echo_read_state);
2299 NTSTATUS status;
2301 if (tevent_req_is_nterror(req, &status)) {
2302 return status;
2304 *pbuf = talloc_move(mem_ctx, &state->buf);
2305 *pbuflen = state->buflen;
2306 *pseqnum = state->seqnum;
2307 return NT_STATUS_OK;
2310 struct smbd_echo_state {
2311 struct tevent_context *ev;
2312 struct iovec *pending;
2313 struct smbd_server_connection *sconn;
2314 struct smbXsrv_connection *xconn;
2315 int parent_pipe;
2317 struct tevent_fd *parent_fde;
2319 struct tevent_req *write_req;
2322 static void smbd_echo_writer_done(struct tevent_req *req);
2324 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2326 int num_pending;
2328 if (state->write_req != NULL) {
2329 return;
2332 num_pending = talloc_array_length(state->pending);
2333 if (num_pending == 0) {
2334 return;
2337 state->write_req = writev_send(state, state->ev, NULL,
2338 state->parent_pipe, false,
2339 state->pending, num_pending);
2340 if (state->write_req == NULL) {
2341 DEBUG(1, ("writev_send failed\n"));
2342 exit(1);
2345 talloc_steal(state->write_req, state->pending);
2346 state->pending = NULL;
2348 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2349 state);
2352 static void smbd_echo_writer_done(struct tevent_req *req)
2354 struct smbd_echo_state *state = tevent_req_callback_data(
2355 req, struct smbd_echo_state);
2356 ssize_t written;
2357 int err;
2359 written = writev_recv(req, &err);
2360 TALLOC_FREE(req);
2361 state->write_req = NULL;
2362 if (written == -1) {
2363 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2364 exit(1);
2366 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2367 smbd_echo_activate_writer(state);
2370 static bool smbd_echo_reply(struct smbd_echo_state *state,
2371 uint8_t *inbuf, size_t inbuf_len,
2372 uint32_t seqnum)
2374 struct smb_request req;
2375 uint16_t num_replies;
2376 char *outbuf;
2377 bool ok;
2379 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2380 DEBUG(10, ("Got netbios keepalive\n"));
2382 * Just swallow it
2384 return true;
2387 if (inbuf_len < smb_size) {
2388 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2389 return false;
2391 if (!valid_smb1_header(inbuf)) {
2392 DEBUG(10, ("Got invalid SMB header\n"));
2393 return false;
2396 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2397 seqnum)) {
2398 return false;
2400 req.inbuf = inbuf;
2402 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2403 smb_messages[req.cmd].name
2404 ? smb_messages[req.cmd].name : "unknown"));
2406 if (req.cmd != SMBecho) {
2407 return false;
2409 if (req.wct < 1) {
2410 return false;
2413 num_replies = SVAL(req.vwv+0, 0);
2414 if (num_replies != 1) {
2415 /* Not a Windows "Hey, you're still there?" request */
2416 return false;
2419 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2420 1, req.buflen)) {
2421 DEBUG(10, ("create_smb1_outbuf failed\n"));
2422 return false;
2424 req.outbuf = (uint8_t *)outbuf;
2426 SSVAL(req.outbuf, smb_vwv0, num_replies);
2428 if (req.buflen > 0) {
2429 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2432 ok = smb1_srv_send(req.xconn,
2433 (char *)outbuf,
2434 true, seqnum+1,
2435 false, &req.pcd);
2436 TALLOC_FREE(outbuf);
2437 if (!ok) {
2438 exit(1);
2441 return true;
2444 static void smbd_echo_exit(struct tevent_context *ev,
2445 struct tevent_fd *fde, uint16_t flags,
2446 void *private_data)
2448 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2449 exit(0);
2452 static void smbd_echo_got_packet(struct tevent_req *req);
2454 static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2455 int parent_pipe)
2457 struct smbd_echo_state *state;
2458 struct tevent_req *read_req;
2460 state = talloc_zero(xconn, struct smbd_echo_state);
2461 if (state == NULL) {
2462 DEBUG(1, ("talloc failed\n"));
2463 return;
2465 state->xconn = xconn;
2466 state->parent_pipe = parent_pipe;
2467 state->ev = samba_tevent_context_init(state);
2468 if (state->ev == NULL) {
2469 DEBUG(1, ("samba_tevent_context_init failed\n"));
2470 TALLOC_FREE(state);
2471 return;
2473 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2474 TEVENT_FD_READ, smbd_echo_exit,
2475 state);
2476 if (state->parent_fde == NULL) {
2477 DEBUG(1, ("tevent_add_fd failed\n"));
2478 TALLOC_FREE(state);
2479 return;
2482 read_req = smbd_echo_read_send(state, state->ev, xconn);
2483 if (read_req == NULL) {
2484 DEBUG(1, ("smbd_echo_read_send failed\n"));
2485 TALLOC_FREE(state);
2486 return;
2488 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2490 while (true) {
2491 if (tevent_loop_once(state->ev) == -1) {
2492 DEBUG(1, ("tevent_loop_once failed: %s\n",
2493 strerror(errno)));
2494 break;
2497 TALLOC_FREE(state);
2500 static void smbd_echo_got_packet(struct tevent_req *req)
2502 struct smbd_echo_state *state = tevent_req_callback_data(
2503 req, struct smbd_echo_state);
2504 NTSTATUS status;
2505 char *buf = NULL;
2506 size_t buflen = 0;
2507 uint32_t seqnum = 0;
2508 bool reply;
2510 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2511 TALLOC_FREE(req);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2514 nt_errstr(status)));
2515 exit(1);
2518 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2519 if (!reply) {
2520 size_t num_pending;
2521 struct iovec *tmp;
2522 struct iovec *iov;
2524 num_pending = talloc_array_length(state->pending);
2525 tmp = talloc_realloc(state, state->pending, struct iovec,
2526 num_pending+1);
2527 if (tmp == NULL) {
2528 DEBUG(1, ("talloc_realloc failed\n"));
2529 exit(1);
2531 state->pending = tmp;
2533 if (buflen >= smb_size) {
2535 * place the seqnum in the packet so that the main process
2536 * can reply with signing
2538 SIVAL(buf, smb_ss_field, seqnum);
2539 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2542 iov = &state->pending[num_pending];
2543 iov->iov_base = talloc_move(state->pending, &buf);
2544 iov->iov_len = buflen;
2546 DEBUG(10,("echo_handler[%d]: forward to main\n",
2547 (int)getpid()));
2548 smbd_echo_activate_writer(state);
2551 req = smbd_echo_read_send(state, state->ev, state->xconn);
2552 if (req == NULL) {
2553 DEBUG(1, ("smbd_echo_read_send failed\n"));
2554 exit(1);
2556 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2561 * Handle SMBecho requests in a forked child process
2563 bool fork_echo_handler(struct smbXsrv_connection *xconn)
2565 int listener_pipe[2];
2566 int res;
2567 pid_t child;
2568 bool use_mutex = false;
2570 res = pipe(listener_pipe);
2571 if (res == -1) {
2572 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2573 return false;
2576 #ifdef HAVE_ROBUST_MUTEXES
2577 use_mutex = tdb_runtime_check_for_robust_mutexes();
2579 if (use_mutex) {
2580 pthread_mutexattr_t a;
2582 xconn->smb1.echo_handler.socket_mutex =
2583 anonymous_shared_allocate(sizeof(pthread_mutex_t));
2584 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2585 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2586 strerror(errno)));
2587 goto fail;
2590 res = pthread_mutexattr_init(&a);
2591 if (res != 0) {
2592 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2593 strerror(res)));
2594 goto fail;
2596 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2597 if (res != 0) {
2598 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2599 strerror(res)));
2600 pthread_mutexattr_destroy(&a);
2601 goto fail;
2603 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2604 if (res != 0) {
2605 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2606 strerror(res)));
2607 pthread_mutexattr_destroy(&a);
2608 goto fail;
2610 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2611 if (res != 0) {
2612 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2613 "%s\n", strerror(res)));
2614 pthread_mutexattr_destroy(&a);
2615 goto fail;
2617 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2618 &a);
2619 pthread_mutexattr_destroy(&a);
2620 if (res != 0) {
2621 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2622 strerror(res)));
2623 goto fail;
2626 #endif
2628 if (!use_mutex) {
2629 xconn->smb1.echo_handler.socket_lock_fd =
2630 create_unlink_tmp(lp_lock_directory());
2631 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2632 DEBUG(1, ("Could not create lock fd: %s\n",
2633 strerror(errno)));
2634 goto fail;
2638 child = fork();
2639 if (child == 0) {
2640 NTSTATUS status;
2642 close(listener_pipe[0]);
2643 set_blocking(listener_pipe[1], false);
2645 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2646 xconn->client->raw_ev_ctx,
2647 true);
2648 if (!NT_STATUS_IS_OK(status)) {
2649 DEBUG(1, ("reinit_after_fork failed: %s\n",
2650 nt_errstr(status)));
2651 exit(1);
2653 process_set_title("smbd-echo", "echo handler");
2654 initialize_password_db(true, xconn->client->raw_ev_ctx);
2655 smbd_echo_loop(xconn, listener_pipe[1]);
2656 exit(0);
2658 close(listener_pipe[1]);
2659 listener_pipe[1] = -1;
2660 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2662 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
2665 * Without smb signing this is the same as the normal smbd
2666 * listener. This needs to change once signing comes in.
2668 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2669 xconn->client->raw_ev_ctx,
2670 xconn,
2671 xconn->smb1.echo_handler.trusted_fd,
2672 TEVENT_FD_READ,
2673 smbd_server_echo_handler,
2674 xconn);
2675 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2676 DEBUG(1, ("event_add_fd failed\n"));
2677 goto fail;
2680 return true;
2682 fail:
2683 if (listener_pipe[0] != -1) {
2684 close(listener_pipe[0]);
2686 if (listener_pipe[1] != -1) {
2687 close(listener_pipe[1]);
2689 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2690 close(xconn->smb1.echo_handler.socket_lock_fd);
2692 #ifdef HAVE_ROBUST_MUTEXES
2693 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2694 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2695 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2697 #endif
2698 smbd_echo_init(xconn);
2700 return false;
2703 bool req_is_in_chain(const struct smb_request *req)
2705 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2707 * We're right now handling a subsequent request, so we must
2708 * be in a chain
2710 return true;
2713 if (!smb1cli_is_andx_req(req->cmd)) {
2714 return false;
2717 if (req->wct < 2) {
2719 * Okay, an illegal request, but definitely not chained :-)
2721 return false;
2724 return (CVAL(req->vwv+0, 0) != 0xFF);