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/>.
22 #include "smbd/globals.h"
24 extern bool global_machine_password_needs_changing;
26 static void construct_reply_common(struct smb_request *req, const char *inbuf,
29 /* Accessor function for smb_read_error for smbd functions. */
31 /****************************************************************************
33 ****************************************************************************/
35 bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
40 char *buf_out = buffer;
42 /* Sign the outgoing packet if required. */
43 srv_calculate_sign_mac(buf_out);
46 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
47 if (!NT_STATUS_IS_OK(status)) {
48 DEBUG(0, ("send_smb: SMB encryption failed "
49 "on outgoing packet! Error %s\n",
55 len = smb_len(buf_out) + 4;
57 while (nwritten < len) {
58 ret = write_data(fd,buf_out+nwritten,len - nwritten);
60 DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
61 (int)len,(int)ret, strerror(errno) ));
62 srv_free_enc_buffer(buf_out);
68 srv_free_enc_buffer(buf_out);
72 /*******************************************************************
73 Setup the word count and byte count for a smb message.
74 ********************************************************************/
76 int srv_set_message(char *buf,
81 if (zero && (num_words || num_bytes)) {
82 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
84 SCVAL(buf,smb_wct,num_words);
85 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
86 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
87 return (smb_size + num_words*2 + num_bytes);
90 static bool valid_smb_header(const uint8_t *inbuf)
92 if (is_encrypted_packet(inbuf)) {
96 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
97 * but it just looks weird to call strncmp for this one.
99 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
102 /* Socket functions for smbd packet processing. */
104 static bool valid_packet_size(size_t len)
107 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
108 * of header. Don't print the error if this fits.... JRA.
111 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
112 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
113 (unsigned long)len));
119 static NTSTATUS read_packet_remainder(int fd, char *buffer,
120 unsigned int timeout, ssize_t len)
126 return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL);
129 /****************************************************************************
130 Attempt a zerocopy writeX read. We know here that len > smb_size-4
131 ****************************************************************************/
134 * Unfortunately, earlier versions of smbclient/libsmbclient
135 * don't send this "standard" writeX header. I've fixed this
136 * for 3.2 but we'll use the old method with earlier versions.
137 * Windows and CIFSFS at least use this standard size. Not
141 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
142 (2*14) + /* word count (including bcc) */ \
145 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
146 const char lenbuf[4],
147 int fd, char **buffer,
148 unsigned int timeout,
152 /* Size of a WRITEX call (+4 byte len). */
153 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
154 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
158 memcpy(writeX_header, lenbuf, 4);
160 status = read_socket_with_timeout(
161 fd, writeX_header + 4,
162 STANDARD_WRITE_AND_X_HEADER_SIZE,
163 STANDARD_WRITE_AND_X_HEADER_SIZE,
166 if (!NT_STATUS_IS_OK(status)) {
171 * Ok - now try and see if this is a possible
175 if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
177 * If the data offset is beyond what
178 * we've read, drain the extra bytes.
180 uint16_t doff = SVAL(writeX_header,smb_vwv11);
183 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
184 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
185 if (drain_socket(smbd_server_fd(), drain) != drain) {
186 smb_panic("receive_smb_raw_talloc_partial_read:"
187 " failed to drain pending bytes");
190 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
193 /* Spoof down the length and null out the bcc. */
194 set_message_bcc(writeX_header, 0);
195 newlen = smb_len(writeX_header);
197 /* Copy the header we've written. */
199 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
201 sizeof(writeX_header));
203 if (*buffer == NULL) {
204 DEBUG(0, ("Could not allocate inbuf of length %d\n",
205 (int)sizeof(writeX_header)));
206 return NT_STATUS_NO_MEMORY;
209 /* Work out the remaining bytes. */
210 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
211 *len_ret = newlen + 4;
215 if (!valid_packet_size(len)) {
216 return NT_STATUS_INVALID_PARAMETER;
220 * Not a valid writeX call. Just do the standard
224 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
226 if (*buffer == NULL) {
227 DEBUG(0, ("Could not allocate inbuf of length %d\n",
229 return NT_STATUS_NO_MEMORY;
232 /* Copy in what we already read. */
235 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
236 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
239 status = read_packet_remainder(
240 fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
243 if (!NT_STATUS_IS_OK(status)) {
244 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
254 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
255 char **buffer, unsigned int timeout,
256 size_t *p_unread, size_t *plen)
260 int min_recv_size = lp_min_receive_file_size();
265 status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
271 if (CVAL(lenbuf,0) == 0 &&
273 smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */
274 !srv_is_signing_active()) {
276 return receive_smb_raw_talloc_partial_read(
277 mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
280 if (!valid_packet_size(len)) {
281 return NT_STATUS_INVALID_PARAMETER;
285 * The +4 here can't wrap, we've checked the length above already.
288 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
290 if (*buffer == NULL) {
291 DEBUG(0, ("Could not allocate inbuf of length %d\n",
293 return NT_STATUS_NO_MEMORY;
296 memcpy(*buffer, lenbuf, sizeof(lenbuf));
298 status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
299 if (!NT_STATUS_IS_OK(status)) {
307 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
308 char **buffer, unsigned int timeout,
309 size_t *p_unread, bool *p_encrypted,
315 *p_encrypted = false;
317 status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
319 if (!NT_STATUS_IS_OK(status)) {
323 if (is_encrypted_packet((uint8_t *)*buffer)) {
324 status = srv_decrypt_buffer(*buffer);
325 if (!NT_STATUS_IS_OK(status)) {
326 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
327 "incoming packet! Error %s\n",
328 nt_errstr(status) ));
334 /* Check the incoming SMB signature. */
335 if (!srv_check_sign_mac(*buffer, true)) {
336 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
337 "incoming packet!\n"));
338 return NT_STATUS_INVALID_NETWORK_RESPONSE;
346 * Initialize a struct smb_request from an inbuf
349 void init_smb_request(struct smb_request *req,
354 size_t req_size = smb_len(inbuf) + 4;
355 /* Ensure we have at least smb_size bytes. */
356 if (req_size < smb_size) {
357 DEBUG(0,("init_smb_request: invalid request size %u\n",
358 (unsigned int)req_size ));
359 exit_server_cleanly("Invalid SMB request");
361 req->cmd = CVAL(inbuf, smb_com);
362 req->flags2 = SVAL(inbuf, smb_flg2);
363 req->smbpid = SVAL(inbuf, smb_pid);
364 req->mid = SVAL(inbuf, smb_mid);
365 req->vuid = SVAL(inbuf, smb_uid);
366 req->tid = SVAL(inbuf, smb_tid);
367 req->wct = CVAL(inbuf, smb_wct);
368 req->vwv = (uint16_t *)(inbuf+smb_vwv);
369 req->buflen = smb_buflen(inbuf);
370 req->buf = (const uint8_t *)smb_buf(inbuf);
371 req->unread_bytes = unread_bytes;
372 req->encrypted = encrypted;
373 req->conn = conn_find(req->tid);
374 req->chain_fsp = NULL;
375 req->chain_outbuf = NULL;
377 /* Ensure we have at least wct words and 2 bytes of bcc. */
378 if (smb_size + req->wct*2 > req_size) {
379 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
380 (unsigned int)req->wct,
381 (unsigned int)req_size));
382 exit_server_cleanly("Invalid SMB request");
384 /* Ensure bcc is correct. */
385 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
386 DEBUG(0,("init_smb_request: invalid bcc number %u "
387 "(wct = %u, size %u)\n",
388 (unsigned int)req->buflen,
389 (unsigned int)req->wct,
390 (unsigned int)req_size));
391 exit_server_cleanly("Invalid SMB request");
396 static void process_smb(struct smbd_server_connection *conn,
397 uint8_t *inbuf, size_t nread, size_t unread_bytes,
400 static void smbd_deferred_open_timer(struct event_context *ev,
401 struct timed_event *te,
402 struct timeval _tval,
405 struct pending_message_list *msg = talloc_get_type(private_data,
406 struct pending_message_list);
407 TALLOC_CTX *mem_ctx = talloc_tos();
410 /* TODO: remove this hack */
411 message_dispatch(smbd_messaging_context());
413 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
416 exit_server("smbd_deferred_open_timer: talloc failed\n");
420 /* We leave this message on the queue so the open code can
421 know this is a retry. */
422 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
423 (unsigned int)SVAL(msg->buf.data,smb_mid)));
425 process_smb(smbd_server_conn, inbuf,
430 /****************************************************************************
431 Function to push a message onto the tail of a linked list of smb messages ready
433 ****************************************************************************/
435 static bool push_queued_message(struct smb_request *req,
436 struct timeval request_time,
437 struct timeval end_time,
438 char *private_data, size_t private_len)
440 int msg_len = smb_len(req->inbuf) + 4;
441 struct pending_message_list *msg;
443 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
446 DEBUG(0,("push_message: malloc fail (1)\n"));
450 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
451 if(msg->buf.data == NULL) {
452 DEBUG(0,("push_message: malloc fail (2)\n"));
457 msg->request_time = request_time;
458 msg->encrypted = req->encrypted;
461 msg->private_data = data_blob_talloc(msg, private_data,
463 if (msg->private_data.data == NULL) {
464 DEBUG(0,("push_message: malloc fail (3)\n"));
470 msg->te = event_add_timed(smbd_event_context(),
473 smbd_deferred_open_timer,
476 DEBUG(0,("push_message: event_add_timed failed\n"));
481 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
483 DEBUG(10,("push_message: pushed message length %u on "
484 "deferred_open_queue\n", (unsigned int)msg_len));
489 /****************************************************************************
490 Function to delete a sharing violation open message by mid.
491 ****************************************************************************/
493 void remove_deferred_open_smb_message(uint16 mid)
495 struct pending_message_list *pml;
497 for (pml = deferred_open_queue; pml; pml = pml->next) {
498 if (mid == SVAL(pml->buf.data,smb_mid)) {
499 DEBUG(10,("remove_sharing_violation_open_smb_message: "
500 "deleting mid %u len %u\n",
502 (unsigned int)pml->buf.length ));
503 DLIST_REMOVE(deferred_open_queue, pml);
510 /****************************************************************************
511 Move a sharing violation open retry message to the front of the list and
512 schedule it for immediate processing.
513 ****************************************************************************/
515 void schedule_deferred_open_smb_message(uint16 mid)
517 struct pending_message_list *pml;
520 for (pml = deferred_open_queue; pml; pml = pml->next) {
521 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
523 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
524 (unsigned int)msg_mid ));
526 if (mid == msg_mid) {
527 struct timed_event *te;
529 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
532 te = event_add_timed(smbd_event_context(),
535 smbd_deferred_open_timer,
538 DEBUG(10,("schedule_deferred_open_smb_message: "
539 "event_add_timed() failed, skipping mid %u\n",
543 TALLOC_FREE(pml->te);
545 DLIST_PROMOTE(deferred_open_queue, pml);
550 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
554 /****************************************************************************
555 Return true if this mid is on the deferred queue.
556 ****************************************************************************/
558 bool open_was_deferred(uint16 mid)
560 struct pending_message_list *pml;
562 for (pml = deferred_open_queue; pml; pml = pml->next) {
563 if (SVAL(pml->buf.data,smb_mid) == mid) {
570 /****************************************************************************
571 Return the message queued by this mid.
572 ****************************************************************************/
574 struct pending_message_list *get_open_deferred_message(uint16 mid)
576 struct pending_message_list *pml;
578 for (pml = deferred_open_queue; pml; pml = pml->next) {
579 if (SVAL(pml->buf.data,smb_mid) == mid) {
586 /****************************************************************************
587 Function to push a deferred open smb message onto a linked list of local smb
588 messages ready for processing.
589 ****************************************************************************/
591 bool push_deferred_smb_message(struct smb_request *req,
592 struct timeval request_time,
593 struct timeval timeout,
594 char *private_data, size_t priv_len)
596 struct timeval end_time;
598 if (req->unread_bytes) {
599 DEBUG(0,("push_deferred_smb_message: logic error ! "
600 "unread_bytes = %u\n",
601 (unsigned int)req->unread_bytes ));
602 smb_panic("push_deferred_smb_message: "
603 "logic error unread_bytes != 0" );
606 end_time = timeval_sum(&request_time, &timeout);
608 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
609 "timeout time [%u.%06u]\n",
610 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
611 (unsigned int)end_time.tv_sec,
612 (unsigned int)end_time.tv_usec));
614 return push_queued_message(req, request_time, end_time,
615 private_data, priv_len);
619 struct timed_event *te;
620 struct timeval interval;
622 bool (*handler)(const struct timeval *now, void *private_data);
626 static void smbd_idle_event_handler(struct event_context *ctx,
627 struct timed_event *te,
631 struct idle_event *event =
632 talloc_get_type_abort(private_data, struct idle_event);
634 TALLOC_FREE(event->te);
636 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
637 event->name, event->te));
639 if (!event->handler(&now, event->private_data)) {
640 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
641 event->name, event->te));
642 /* Don't repeat, delete ourselves */
647 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
648 event->name, event->te));
650 event->te = event_add_timed(ctx, event,
651 timeval_sum(&now, &event->interval),
652 smbd_idle_event_handler, event);
654 /* We can't do much but fail here. */
655 SMB_ASSERT(event->te != NULL);
658 struct idle_event *event_add_idle(struct event_context *event_ctx,
660 struct timeval interval,
662 bool (*handler)(const struct timeval *now,
666 struct idle_event *result;
667 struct timeval now = timeval_current();
669 result = TALLOC_P(mem_ctx, struct idle_event);
670 if (result == NULL) {
671 DEBUG(0, ("talloc failed\n"));
675 result->interval = interval;
676 result->handler = handler;
677 result->private_data = private_data;
679 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
680 DEBUG(0, ("talloc failed\n"));
685 result->te = event_add_timed(event_ctx, result,
686 timeval_sum(&now, &interval),
687 smbd_idle_event_handler, result);
688 if (result->te == NULL) {
689 DEBUG(0, ("event_add_timed failed\n"));
694 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
698 /****************************************************************************
699 Do all async processing in here. This includes kernel oplock messages, change
701 ****************************************************************************/
703 static void async_processing(void)
705 DEBUG(10,("async_processing: Doing async processing.\n"));
709 process_kernel_oplocks(smbd_messaging_context());
711 /* Do the aio check again after receive_local_message as it does a
712 select and may have eaten our signal. */
713 /* Is this till true? -- vl */
717 exit_server_cleanly("termination signal");
720 /* check for sighup processing */
721 if (reload_after_sighup) {
722 change_to_root_user();
723 DEBUG(1,("Reloading services after SIGHUP\n"));
724 reload_services(False);
725 reload_after_sighup = 0;
729 /****************************************************************************
730 Do a select on an two fd's - with timeout.
732 If a local udp message has been pushed onto the
733 queue (this can only happen during oplock break
734 processing) call async_processing()
736 If a pending smb message has been pushed onto the
737 queue (this can only happen during oplock break
738 processing) return this next.
740 If the first smbfd is ready then read an smb from it.
741 if the second (loopback UDP) fd is ready then read a message
742 from it and setup the buffer header to identify the length
744 Returns False on timeout or error.
747 The timeout is in milliseconds
748 ****************************************************************************/
750 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
757 to.tv_sec = SMBD_SELECT_TIMEOUT;
761 * Note that this call must be before processing any SMB
762 * messages as we need to synchronously process any messages
763 * we may have sent to ourselves from the previous SMB.
765 message_dispatch(smbd_messaging_context());
768 * Setup the select fd sets.
775 * Ensure we process oplock break messages by preference.
776 * We have to do this before the select, after the select
777 * and if the select returns EINTR. This is due to the fact
778 * that the selects called from async_processing can eat an EINTR
779 * caused by a signal (we can't take the break message there).
780 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
783 if (oplock_message_waiting()) {
784 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
787 * After async processing we must go and do the select again, as
788 * the state of the flag in fds for the server file descriptor is
789 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
791 return NT_STATUS_RETRY;
795 * Are there any timed events waiting ? If so, ensure we don't
796 * select for longer than it would take to wait for them.
803 event_add_to_select_args(smbd_event_context(), &now,
804 &r_fds, &w_fds, &to, &maxfd);
807 /* Process a signal and timed events now... */
808 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
809 return NT_STATUS_RETRY;
814 START_PROFILE(smbd_idle);
816 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
819 END_PROFILE(smbd_idle);
823 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
824 return NT_STATUS_RETRY;
827 /* if we get EINTR then maybe we have received an oplock
828 signal - treat this as select returning 1. This is ugly, but
829 is the best we can do until the oplock code knows more about
831 if (selrtn == -1 && errno == EINTR) {
834 * After async processing we must go and do the select again, as
835 * the state of the flag in fds for the server file descriptor is
836 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
838 return NT_STATUS_RETRY;
843 /* something is wrong. Maybe the socket is dead? */
844 return map_nt_error_from_unix(errno);
847 /* Did we timeout ? */
849 return NT_STATUS_RETRY;
853 * We've just woken up from a protentially long select sleep.
854 * Ensure we process local messages as we need to synchronously
855 * process any messages from other smbd's to avoid file rename race
856 * conditions. This call is cheap if there are no messages waiting.
859 message_dispatch(smbd_messaging_context());
865 * Only allow 5 outstanding trans requests. We're allocating memory, so
869 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
872 for (; list != NULL; list = list->next) {
874 if (list->mid == mid) {
875 return NT_STATUS_INVALID_PARAMETER;
881 return NT_STATUS_INSUFFICIENT_RESOURCES;
887 /****************************************************************************
888 We're terminating and have closed all our files/connections etc.
889 If there are any pending local messages we need to respond to them
890 before termination so that other smbds don't think we just died whilst
892 ****************************************************************************/
894 void respond_to_all_remaining_local_messages(void)
897 * Assert we have no exclusive open oplocks.
900 if(get_number_of_exclusive_open_oplocks()) {
901 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
902 get_number_of_exclusive_open_oplocks() ));
906 process_kernel_oplocks(smbd_messaging_context());
913 These flags determine some of the permissions required to do an operation
915 Note that I don't set NEED_WRITE on some write operations because they
916 are used by some brain-dead clients when printing, and I don't want to
917 force write permissions on print services.
919 #define AS_USER (1<<0)
920 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
921 #define TIME_INIT (1<<2)
922 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
923 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
924 #define DO_CHDIR (1<<6)
927 define a list of possible SMB messages and their corresponding
928 functions. Any message that has a NULL function is unimplemented -
929 please feel free to contribute implementations!
931 static const struct smb_message_struct {
933 void (*fn)(struct smb_request *req);
935 } smb_messages[256] = {
937 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
938 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
939 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
940 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
941 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
942 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
943 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
944 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
945 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
946 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
947 /* 0x0a */ { "SMBread",reply_read,AS_USER},
948 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
949 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
950 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
951 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
952 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
953 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
954 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
955 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
956 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
957 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
958 /* 0x15 */ { NULL, NULL, 0 },
959 /* 0x16 */ { NULL, NULL, 0 },
960 /* 0x17 */ { NULL, NULL, 0 },
961 /* 0x18 */ { NULL, NULL, 0 },
962 /* 0x19 */ { NULL, NULL, 0 },
963 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
964 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
965 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
966 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
967 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
968 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
969 /* 0x20 */ { "SMBwritec", NULL,0},
970 /* 0x21 */ { NULL, NULL, 0 },
971 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
972 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
973 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
974 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
975 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
976 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
977 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
978 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
979 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
980 /* 0x2b */ { "SMBecho",reply_echo,0},
981 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
982 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
983 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
984 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
985 /* 0x30 */ { NULL, NULL, 0 },
986 /* 0x31 */ { NULL, NULL, 0 },
987 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
988 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
989 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
990 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
991 /* 0x36 */ { NULL, NULL, 0 },
992 /* 0x37 */ { NULL, NULL, 0 },
993 /* 0x38 */ { NULL, NULL, 0 },
994 /* 0x39 */ { NULL, NULL, 0 },
995 /* 0x3a */ { NULL, NULL, 0 },
996 /* 0x3b */ { NULL, NULL, 0 },
997 /* 0x3c */ { NULL, NULL, 0 },
998 /* 0x3d */ { NULL, NULL, 0 },
999 /* 0x3e */ { NULL, NULL, 0 },
1000 /* 0x3f */ { NULL, NULL, 0 },
1001 /* 0x40 */ { NULL, NULL, 0 },
1002 /* 0x41 */ { NULL, NULL, 0 },
1003 /* 0x42 */ { NULL, NULL, 0 },
1004 /* 0x43 */ { NULL, NULL, 0 },
1005 /* 0x44 */ { NULL, NULL, 0 },
1006 /* 0x45 */ { NULL, NULL, 0 },
1007 /* 0x46 */ { NULL, NULL, 0 },
1008 /* 0x47 */ { NULL, NULL, 0 },
1009 /* 0x48 */ { NULL, NULL, 0 },
1010 /* 0x49 */ { NULL, NULL, 0 },
1011 /* 0x4a */ { NULL, NULL, 0 },
1012 /* 0x4b */ { NULL, NULL, 0 },
1013 /* 0x4c */ { NULL, NULL, 0 },
1014 /* 0x4d */ { NULL, NULL, 0 },
1015 /* 0x4e */ { NULL, NULL, 0 },
1016 /* 0x4f */ { NULL, NULL, 0 },
1017 /* 0x50 */ { NULL, NULL, 0 },
1018 /* 0x51 */ { NULL, NULL, 0 },
1019 /* 0x52 */ { NULL, NULL, 0 },
1020 /* 0x53 */ { NULL, NULL, 0 },
1021 /* 0x54 */ { NULL, NULL, 0 },
1022 /* 0x55 */ { NULL, NULL, 0 },
1023 /* 0x56 */ { NULL, NULL, 0 },
1024 /* 0x57 */ { NULL, NULL, 0 },
1025 /* 0x58 */ { NULL, NULL, 0 },
1026 /* 0x59 */ { NULL, NULL, 0 },
1027 /* 0x5a */ { NULL, NULL, 0 },
1028 /* 0x5b */ { NULL, NULL, 0 },
1029 /* 0x5c */ { NULL, NULL, 0 },
1030 /* 0x5d */ { NULL, NULL, 0 },
1031 /* 0x5e */ { NULL, NULL, 0 },
1032 /* 0x5f */ { NULL, NULL, 0 },
1033 /* 0x60 */ { NULL, NULL, 0 },
1034 /* 0x61 */ { NULL, NULL, 0 },
1035 /* 0x62 */ { NULL, NULL, 0 },
1036 /* 0x63 */ { NULL, NULL, 0 },
1037 /* 0x64 */ { NULL, NULL, 0 },
1038 /* 0x65 */ { NULL, NULL, 0 },
1039 /* 0x66 */ { NULL, NULL, 0 },
1040 /* 0x67 */ { NULL, NULL, 0 },
1041 /* 0x68 */ { NULL, NULL, 0 },
1042 /* 0x69 */ { NULL, NULL, 0 },
1043 /* 0x6a */ { NULL, NULL, 0 },
1044 /* 0x6b */ { NULL, NULL, 0 },
1045 /* 0x6c */ { NULL, NULL, 0 },
1046 /* 0x6d */ { NULL, NULL, 0 },
1047 /* 0x6e */ { NULL, NULL, 0 },
1048 /* 0x6f */ { NULL, NULL, 0 },
1049 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1050 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1051 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1052 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1053 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1054 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1055 /* 0x76 */ { NULL, NULL, 0 },
1056 /* 0x77 */ { NULL, NULL, 0 },
1057 /* 0x78 */ { NULL, NULL, 0 },
1058 /* 0x79 */ { NULL, NULL, 0 },
1059 /* 0x7a */ { NULL, NULL, 0 },
1060 /* 0x7b */ { NULL, NULL, 0 },
1061 /* 0x7c */ { NULL, NULL, 0 },
1062 /* 0x7d */ { NULL, NULL, 0 },
1063 /* 0x7e */ { NULL, NULL, 0 },
1064 /* 0x7f */ { NULL, NULL, 0 },
1065 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1066 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1067 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1068 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1069 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1070 /* 0x85 */ { NULL, NULL, 0 },
1071 /* 0x86 */ { NULL, NULL, 0 },
1072 /* 0x87 */ { NULL, NULL, 0 },
1073 /* 0x88 */ { NULL, NULL, 0 },
1074 /* 0x89 */ { NULL, NULL, 0 },
1075 /* 0x8a */ { NULL, NULL, 0 },
1076 /* 0x8b */ { NULL, NULL, 0 },
1077 /* 0x8c */ { NULL, NULL, 0 },
1078 /* 0x8d */ { NULL, NULL, 0 },
1079 /* 0x8e */ { NULL, NULL, 0 },
1080 /* 0x8f */ { NULL, NULL, 0 },
1081 /* 0x90 */ { NULL, NULL, 0 },
1082 /* 0x91 */ { NULL, NULL, 0 },
1083 /* 0x92 */ { NULL, NULL, 0 },
1084 /* 0x93 */ { NULL, NULL, 0 },
1085 /* 0x94 */ { NULL, NULL, 0 },
1086 /* 0x95 */ { NULL, NULL, 0 },
1087 /* 0x96 */ { NULL, NULL, 0 },
1088 /* 0x97 */ { NULL, NULL, 0 },
1089 /* 0x98 */ { NULL, NULL, 0 },
1090 /* 0x99 */ { NULL, NULL, 0 },
1091 /* 0x9a */ { NULL, NULL, 0 },
1092 /* 0x9b */ { NULL, NULL, 0 },
1093 /* 0x9c */ { NULL, NULL, 0 },
1094 /* 0x9d */ { NULL, NULL, 0 },
1095 /* 0x9e */ { NULL, NULL, 0 },
1096 /* 0x9f */ { NULL, NULL, 0 },
1097 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1098 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1099 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1100 /* 0xa3 */ { NULL, NULL, 0 },
1101 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1102 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1103 /* 0xa6 */ { NULL, NULL, 0 },
1104 /* 0xa7 */ { NULL, NULL, 0 },
1105 /* 0xa8 */ { NULL, NULL, 0 },
1106 /* 0xa9 */ { NULL, NULL, 0 },
1107 /* 0xaa */ { NULL, NULL, 0 },
1108 /* 0xab */ { NULL, NULL, 0 },
1109 /* 0xac */ { NULL, NULL, 0 },
1110 /* 0xad */ { NULL, NULL, 0 },
1111 /* 0xae */ { NULL, NULL, 0 },
1112 /* 0xaf */ { NULL, NULL, 0 },
1113 /* 0xb0 */ { NULL, NULL, 0 },
1114 /* 0xb1 */ { NULL, NULL, 0 },
1115 /* 0xb2 */ { NULL, NULL, 0 },
1116 /* 0xb3 */ { NULL, NULL, 0 },
1117 /* 0xb4 */ { NULL, NULL, 0 },
1118 /* 0xb5 */ { NULL, NULL, 0 },
1119 /* 0xb6 */ { NULL, NULL, 0 },
1120 /* 0xb7 */ { NULL, NULL, 0 },
1121 /* 0xb8 */ { NULL, NULL, 0 },
1122 /* 0xb9 */ { NULL, NULL, 0 },
1123 /* 0xba */ { NULL, NULL, 0 },
1124 /* 0xbb */ { NULL, NULL, 0 },
1125 /* 0xbc */ { NULL, NULL, 0 },
1126 /* 0xbd */ { NULL, NULL, 0 },
1127 /* 0xbe */ { NULL, NULL, 0 },
1128 /* 0xbf */ { NULL, NULL, 0 },
1129 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1130 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1131 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1132 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1133 /* 0xc4 */ { NULL, NULL, 0 },
1134 /* 0xc5 */ { NULL, NULL, 0 },
1135 /* 0xc6 */ { NULL, NULL, 0 },
1136 /* 0xc7 */ { NULL, NULL, 0 },
1137 /* 0xc8 */ { NULL, NULL, 0 },
1138 /* 0xc9 */ { NULL, NULL, 0 },
1139 /* 0xca */ { NULL, NULL, 0 },
1140 /* 0xcb */ { NULL, NULL, 0 },
1141 /* 0xcc */ { NULL, NULL, 0 },
1142 /* 0xcd */ { NULL, NULL, 0 },
1143 /* 0xce */ { NULL, NULL, 0 },
1144 /* 0xcf */ { NULL, NULL, 0 },
1145 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1146 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1147 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1148 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1149 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1150 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1151 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1152 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1153 /* 0xd8 */ { NULL, NULL, 0 },
1154 /* 0xd9 */ { NULL, NULL, 0 },
1155 /* 0xda */ { NULL, NULL, 0 },
1156 /* 0xdb */ { NULL, NULL, 0 },
1157 /* 0xdc */ { NULL, NULL, 0 },
1158 /* 0xdd */ { NULL, NULL, 0 },
1159 /* 0xde */ { NULL, NULL, 0 },
1160 /* 0xdf */ { NULL, NULL, 0 },
1161 /* 0xe0 */ { NULL, NULL, 0 },
1162 /* 0xe1 */ { NULL, NULL, 0 },
1163 /* 0xe2 */ { NULL, NULL, 0 },
1164 /* 0xe3 */ { NULL, NULL, 0 },
1165 /* 0xe4 */ { NULL, NULL, 0 },
1166 /* 0xe5 */ { NULL, NULL, 0 },
1167 /* 0xe6 */ { NULL, NULL, 0 },
1168 /* 0xe7 */ { NULL, NULL, 0 },
1169 /* 0xe8 */ { NULL, NULL, 0 },
1170 /* 0xe9 */ { NULL, NULL, 0 },
1171 /* 0xea */ { NULL, NULL, 0 },
1172 /* 0xeb */ { NULL, NULL, 0 },
1173 /* 0xec */ { NULL, NULL, 0 },
1174 /* 0xed */ { NULL, NULL, 0 },
1175 /* 0xee */ { NULL, NULL, 0 },
1176 /* 0xef */ { NULL, NULL, 0 },
1177 /* 0xf0 */ { NULL, NULL, 0 },
1178 /* 0xf1 */ { NULL, NULL, 0 },
1179 /* 0xf2 */ { NULL, NULL, 0 },
1180 /* 0xf3 */ { NULL, NULL, 0 },
1181 /* 0xf4 */ { NULL, NULL, 0 },
1182 /* 0xf5 */ { NULL, NULL, 0 },
1183 /* 0xf6 */ { NULL, NULL, 0 },
1184 /* 0xf7 */ { NULL, NULL, 0 },
1185 /* 0xf8 */ { NULL, NULL, 0 },
1186 /* 0xf9 */ { NULL, NULL, 0 },
1187 /* 0xfa */ { NULL, NULL, 0 },
1188 /* 0xfb */ { NULL, NULL, 0 },
1189 /* 0xfc */ { NULL, NULL, 0 },
1190 /* 0xfd */ { NULL, NULL, 0 },
1191 /* 0xfe */ { NULL, NULL, 0 },
1192 /* 0xff */ { NULL, NULL, 0 }
1196 /*******************************************************************
1197 allocate and initialize a reply packet
1198 ********************************************************************/
1200 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1201 const char *inbuf, char **outbuf, uint8_t num_words,
1205 * Protect against integer wrap
1207 if ((num_bytes > 0xffffff)
1208 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1210 if (asprintf(&msg, "num_bytes too large: %u",
1211 (unsigned)num_bytes) == -1) {
1212 msg = CONST_DISCARD(char *, "num_bytes too large");
1217 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1218 smb_size + num_words*2 + num_bytes);
1219 if (*outbuf == NULL) {
1223 construct_reply_common(req, inbuf, *outbuf);
1224 srv_set_message(*outbuf, num_words, num_bytes, false);
1226 * Zero out the word area, the caller has to take care of the bcc area
1229 if (num_words != 0) {
1230 memset(*outbuf + smb_vwv0, 0, num_words*2);
1236 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1239 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1241 smb_panic("could not allocate output buffer\n");
1243 req->outbuf = (uint8_t *)outbuf;
1247 /*******************************************************************
1248 Dump a packet to a file.
1249 ********************************************************************/
1251 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1255 if (DEBUGLEVEL < 50) {
1259 if (len < 4) len = smb_len(data)+4;
1260 for (i=1;i<100;i++) {
1261 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1262 type ? "req" : "resp") == -1) {
1265 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1266 if (fd != -1 || errno != EEXIST) break;
1269 ssize_t ret = write(fd, data, len);
1271 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1273 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1278 /****************************************************************************
1279 Prepare everything for calling the actual request function, and potentially
1280 call the request function via the "new" interface.
1282 Return False if the "legacy" function needs to be called, everything is
1285 Return True if we're done.
1287 I know this API sucks, but it is the one with the least code change I could
1289 ****************************************************************************/
1291 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1295 connection_struct *conn = NULL;
1299 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1300 * so subtract 4 from it. */
1301 if (!valid_smb_header(req->inbuf)
1302 || (size < (smb_size - 4))) {
1303 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1304 smb_len(req->inbuf)));
1305 exit_server_cleanly("Non-SMB packet");
1308 if (smb_messages[type].fn == NULL) {
1309 DEBUG(0,("Unknown message type %d!\n",type));
1310 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1311 reply_unknown_new(req, type);
1315 flags = smb_messages[type].flags;
1317 /* In share mode security we must ignore the vuid. */
1318 session_tag = (lp_security() == SEC_SHARE)
1319 ? UID_FIELD_INVALID : req->vuid;
1322 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1323 (int)sys_getpid(), (unsigned long)conn));
1325 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1327 /* Ensure this value is replaced in the incoming packet. */
1328 SSVAL(req->inbuf,smb_uid,session_tag);
1331 * Ensure the correct username is in current_user_info. This is a
1332 * really ugly bugfix for problems with multiple session_setup_and_X's
1333 * being done and allowing %U and %G substitutions to work correctly.
1334 * There is a reason this code is done here, don't move it unless you
1335 * know what you're doing... :-).
1339 if (session_tag != last_session_tag) {
1340 user_struct *vuser = NULL;
1342 last_session_tag = session_tag;
1343 if(session_tag != UID_FIELD_INVALID) {
1344 vuser = get_valid_user_struct(session_tag);
1346 set_current_user_info(
1347 vuser->server_info->sanitized_username,
1348 vuser->server_info->unix_name,
1349 pdb_get_domain(vuser->server_info
1355 /* Does this call need to be run as the connected user? */
1356 if (flags & AS_USER) {
1358 /* Does this call need a valid tree connection? */
1361 * Amazingly, the error code depends on the command
1364 if (type == SMBntcreateX) {
1365 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1367 reply_doserror(req, ERRSRV, ERRinvnid);
1372 if (!change_to_user(conn,session_tag)) {
1373 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1374 remove_deferred_open_smb_message(req->mid);
1378 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1380 /* Does it need write permission? */
1381 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1382 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1386 /* IPC services are limited */
1387 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1388 reply_doserror(req, ERRSRV,ERRaccess);
1392 /* This call needs to be run as root */
1393 change_to_root_user();
1396 /* load service specific parameters */
1398 if (req->encrypted) {
1399 conn->encrypted_tid = true;
1400 /* encrypted required from now on. */
1401 conn->encrypt_level = Required;
1402 } else if (ENCRYPTION_REQUIRED(conn)) {
1403 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1404 exit_server_cleanly("encryption required "
1410 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1411 (flags & (AS_USER|DO_CHDIR)
1413 reply_doserror(req, ERRSRV, ERRaccess);
1416 conn->num_smb_operations++;
1419 /* does this protocol need to be run as guest? */
1420 if ((flags & AS_GUEST)
1421 && (!change_to_guest() ||
1422 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1423 lp_hostsdeny(-1)))) {
1424 reply_doserror(req, ERRSRV, ERRaccess);
1428 smb_messages[type].fn(req);
1432 /****************************************************************************
1433 Construct a reply to the incoming packet.
1434 ****************************************************************************/
1436 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1438 connection_struct *conn;
1439 struct smb_request *req;
1443 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1444 smb_panic("could not allocate smb_request");
1446 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1447 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1449 conn = switch_message(req->cmd, req, size);
1451 if (req->unread_bytes) {
1452 /* writeX failed. drain socket. */
1453 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1454 req->unread_bytes) {
1455 smb_panic("failed to drain pending bytes");
1457 req->unread_bytes = 0;
1460 if (req->outbuf == NULL) {
1464 if (CVAL(req->outbuf,0) == 0) {
1465 show_msg((char *)req->outbuf);
1468 if (!srv_send_smb(smbd_server_fd(),
1469 (char *)req->outbuf,
1470 IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1471 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1479 /****************************************************************************
1480 Process an smb from the client
1481 ****************************************************************************/
1483 static void process_smb(struct smbd_server_connection *conn,
1484 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1487 int msg_type = CVAL(inbuf,0);
1489 DO_PROFILE_INC(smb_count);
1491 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1493 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1495 (unsigned int)unread_bytes ));
1497 if (msg_type != 0) {
1499 * NetBIOS session request, keepalive, etc.
1501 reply_special((char *)inbuf);
1505 show_msg((char *)inbuf);
1507 construct_reply((char *)inbuf,nread,unread_bytes,encrypted);
1512 conn->num_requests++;
1514 /* The timeout_processing function isn't run nearly
1515 often enough to implement 'max log size' without
1516 overrunning the size of the file by many megabytes.
1517 This is especially true if we are running at debug
1518 level 10. Checking every 50 SMBs is a nice
1519 tradeoff of performance vs log file size overrun. */
1521 if ((conn->num_requests % 50) == 0 &&
1522 need_to_check_log_size()) {
1523 change_to_root_user();
1528 /****************************************************************************
1529 Return a string containing the function name of a SMB command.
1530 ****************************************************************************/
1532 const char *smb_fn_name(int type)
1534 const char *unknown_name = "SMBunknown";
1536 if (smb_messages[type].name == NULL)
1537 return(unknown_name);
1539 return(smb_messages[type].name);
1542 /****************************************************************************
1543 Helper functions for contruct_reply.
1544 ****************************************************************************/
1546 void add_to_common_flags2(uint32 v)
1551 void remove_from_common_flags2(uint32 v)
1553 common_flags2 &= ~v;
1556 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1559 srv_set_message(outbuf,0,0,false);
1561 SCVAL(outbuf, smb_com, req->cmd);
1562 SIVAL(outbuf,smb_rcls,0);
1563 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1564 SSVAL(outbuf,smb_flg2,
1565 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1567 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1569 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1570 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1571 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1572 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1575 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1577 construct_reply_common(req, (char *)req->inbuf, outbuf);
1581 * How many bytes have we already accumulated up to the current wct field
1585 size_t req_wct_ofs(struct smb_request *req)
1589 if (req->chain_outbuf == NULL) {
1592 buf_size = talloc_get_size(req->chain_outbuf);
1593 if ((buf_size % 4) != 0) {
1594 buf_size += (4 - (buf_size % 4));
1596 return buf_size - 4;
1600 * Hack around reply_nterror & friends not being aware of chained requests,
1601 * generating illegal (i.e. wct==0) chain replies.
1604 static void fixup_chain_error_packet(struct smb_request *req)
1606 uint8_t *outbuf = req->outbuf;
1608 reply_outbuf(req, 2, 0);
1609 memcpy(req->outbuf, outbuf, smb_wct);
1610 TALLOC_FREE(outbuf);
1611 SCVAL(req->outbuf, smb_vwv0, 0xff);
1614 /****************************************************************************
1615 Construct a chained reply and add it to the already made reply
1616 ****************************************************************************/
1618 void chain_reply(struct smb_request *req)
1620 size_t smblen = smb_len(req->inbuf);
1621 size_t already_used, length_needed;
1623 uint32_t chain_offset; /* uint32_t to avoid overflow */
1630 if (IVAL(req->outbuf, smb_rcls) != 0) {
1631 fixup_chain_error_packet(req);
1635 * Any of the AndX requests and replies have at least a wct of
1636 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1637 * beginning of the SMB header to the next wct field.
1639 * None of the AndX requests put anything valuable in vwv[0] and [1],
1640 * so we can overwrite it here to form the chain.
1643 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1648 * Here we assume that this is the end of the chain. For that we need
1649 * to set "next command" to 0xff and the offset to 0. If we later find
1650 * more commands in the chain, this will be overwritten again.
1653 SCVAL(req->outbuf, smb_vwv0, 0xff);
1654 SCVAL(req->outbuf, smb_vwv0+1, 0);
1655 SSVAL(req->outbuf, smb_vwv1, 0);
1657 if (req->chain_outbuf == NULL) {
1659 * In req->chain_outbuf we collect all the replies. Start the
1660 * chain by copying in the first reply.
1662 req->chain_outbuf = req->outbuf;
1665 if (!smb_splice_chain(&req->chain_outbuf,
1666 CVAL(req->outbuf, smb_com),
1667 CVAL(req->outbuf, smb_wct),
1668 (uint16_t *)(req->outbuf + smb_vwv),
1669 0, smb_buflen(req->outbuf),
1670 (uint8_t *)smb_buf(req->outbuf))) {
1673 TALLOC_FREE(req->outbuf);
1677 * We use the old request's vwv field to grab the next chained command
1678 * and offset into the chained fields.
1681 chain_cmd = CVAL(req->vwv+0, 0);
1682 chain_offset = SVAL(req->vwv+1, 0);
1684 if (chain_cmd == 0xff) {
1686 * End of chain, no more requests from the client. So ship the
1689 smb_setlen((char *)(req->chain_outbuf),
1690 talloc_get_size(req->chain_outbuf) - 4);
1691 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1692 IS_CONN_ENCRYPTED(req->conn)
1693 ||req->encrypted)) {
1694 exit_server_cleanly("chain_reply: srv_send_smb "
1701 * Check if the client tries to fool us. The request so far uses the
1702 * space to the end of the byte buffer in the request just
1703 * processed. The chain_offset can't point into that area. If that was
1704 * the case, we could end up with an endless processing of the chain,
1705 * we would always handle the same request.
1708 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1709 if (chain_offset < already_used) {
1714 * Next check: Make sure the chain offset does not point beyond the
1715 * overall smb request length.
1718 length_needed = chain_offset+1; /* wct */
1719 if (length_needed > smblen) {
1724 * Now comes the pointer magic. Goal here is to set up req->vwv and
1725 * req->buf correctly again to be able to call the subsequent
1726 * switch_message(). The chain offset (the former vwv[1]) points at
1727 * the new wct field.
1730 wct = CVAL(smb_base(req->inbuf), chain_offset);
1733 * Next consistency check: Make the new vwv array fits in the overall
1737 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1738 if (length_needed > smblen) {
1741 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1744 * Now grab the new byte buffer....
1747 buflen = SVAL(vwv+wct, 0);
1750 * .. and check that it fits.
1753 length_needed += buflen;
1754 if (length_needed > smblen) {
1757 buf = (uint8_t *)(vwv+wct+1);
1759 req->cmd = chain_cmd;
1762 req->buflen = buflen;
1765 switch_message(chain_cmd, req, smblen);
1767 if (req->outbuf == NULL) {
1769 * This happens if the chained command has suspended itself or
1770 * if it has called srv_send_smb() itself.
1776 * We end up here if the chained command was not itself chained or
1777 * suspended, but for example a close() command. We now need to splice
1778 * the chained commands' outbuf into the already built up chain_outbuf
1779 * and ship the result.
1785 * We end up here if there's any error in the chain syntax. Report a
1786 * DOS error, just like Windows does.
1788 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1789 fixup_chain_error_packet(req);
1792 if (!smb_splice_chain(&req->chain_outbuf,
1793 CVAL(req->outbuf, smb_com),
1794 CVAL(req->outbuf, smb_wct),
1795 (uint16_t *)(req->outbuf + smb_vwv),
1796 0, smb_buflen(req->outbuf),
1797 (uint8_t *)smb_buf(req->outbuf))) {
1798 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1800 TALLOC_FREE(req->outbuf);
1802 smb_setlen((char *)(req->chain_outbuf),
1803 talloc_get_size(req->chain_outbuf) - 4);
1805 show_msg((char *)(req->chain_outbuf));
1807 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1808 IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
1809 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1813 /****************************************************************************
1814 Check if services need reloading.
1815 ****************************************************************************/
1817 void check_reload(time_t t)
1819 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1821 if(last_smb_conf_reload_time == 0) {
1822 last_smb_conf_reload_time = t;
1823 /* Our printing subsystem might not be ready at smbd start up.
1824 Then no printer is available till the first printers check
1825 is performed. A lower initial interval circumvents this. */
1826 if ( printcap_cache_time > 60 )
1827 last_printer_reload_time = t - printcap_cache_time + 60;
1829 last_printer_reload_time = t;
1832 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1833 /* randomize over 60 second the printcap reload to avoid all
1834 * process hitting cupsd at the same time */
1835 int time_range = 60;
1837 last_printer_reload_time += random() % time_range;
1841 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1842 reload_services(True);
1843 reload_after_sighup = False;
1844 last_smb_conf_reload_time = t;
1847 /* 'printcap cache time = 0' disable the feature */
1849 if ( printcap_cache_time != 0 )
1851 /* see if it's time to reload or if the clock has been set back */
1853 if ( (t >= last_printer_reload_time+printcap_cache_time)
1854 || (t-last_printer_reload_time < 0) )
1856 DEBUG( 3,( "Printcap cache time expired.\n"));
1858 last_printer_reload_time = t;
1863 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1865 /* TODO: make write nonblocking */
1868 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1870 uint8_t *inbuf = NULL;
1871 size_t inbuf_len = 0;
1872 size_t unread_bytes = 0;
1873 bool encrypted = false;
1874 TALLOC_CTX *mem_ctx = talloc_tos();
1877 /* TODO: remove this hack */
1878 message_dispatch(smbd_messaging_context());
1880 /* TODO: make this completely nonblocking */
1882 status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1883 (char **)(void *)&inbuf,
1888 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1891 if (NT_STATUS_IS_ERR(status)) {
1892 exit_server_cleanly("failed to receive smb request");
1894 if (!NT_STATUS_IS_OK(status)) {
1899 process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted);
1902 static void smbd_server_connection_handler(struct event_context *ev,
1903 struct fd_event *fde,
1907 struct smbd_server_connection *conn = talloc_get_type(private_data,
1908 struct smbd_server_connection);
1910 if (flags & EVENT_FD_WRITE) {
1911 smbd_server_connection_write_handler(conn);
1912 } else if (flags & EVENT_FD_READ) {
1913 smbd_server_connection_read_handler(conn);
1917 /****************************************************************************
1918 Process commands from the client
1919 ****************************************************************************/
1921 void smbd_process(void)
1924 * Before the first packet, check the global hosts allow/ hosts deny
1925 * parameters before doing any parsing of packets passed to us by the
1926 * client. This prevents attacks on our parsing code from hosts not in
1927 * the hosts allow list.
1930 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1931 lp_hostsdeny(-1))) {
1932 char addr[INET6_ADDRSTRLEN];
1935 * send a negative session response "not listening on calling
1938 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1939 DEBUG( 1, ("Connection denied from %s\n",
1940 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1941 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1942 exit_server_cleanly("connection denied");
1945 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1947 smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
1948 if (!smbd_server_conn) {
1949 exit_server("failed to create smbd_server_connection");
1951 smbd_server_conn->fde = event_add_fd(smbd_event_context(),
1955 smbd_server_connection_handler,
1957 if (!smbd_server_conn->fde) {
1958 exit_server("failed to create smbd_server_connection fde");
1963 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
1967 status = smbd_server_connection_loop_once(smbd_server_conn);
1968 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
1969 !NT_STATUS_IS_OK(status)) {
1970 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
1971 " exiting\n", nt_errstr(status)));