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;
376 /* Ensure we have at least wct words and 2 bytes of bcc. */
377 if (smb_size + req->wct*2 > req_size) {
378 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
379 (unsigned int)req->wct,
380 (unsigned int)req_size));
381 exit_server_cleanly("Invalid SMB request");
383 /* Ensure bcc is correct. */
384 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
385 DEBUG(0,("init_smb_request: invalid bcc number %u "
386 "(wct = %u, size %u)\n",
387 (unsigned int)req->buflen,
388 (unsigned int)req->wct,
389 (unsigned int)req_size));
390 exit_server_cleanly("Invalid SMB request");
396 /****************************************************************************
397 Function to push a message onto the tail of a linked list of smb messages ready
399 ****************************************************************************/
401 static bool push_queued_message(struct smb_request *req,
402 struct timeval request_time,
403 struct timeval end_time,
404 char *private_data, size_t private_len)
406 int msg_len = smb_len(req->inbuf) + 4;
407 struct pending_message_list *msg;
409 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
412 DEBUG(0,("push_message: malloc fail (1)\n"));
416 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
417 if(msg->buf.data == NULL) {
418 DEBUG(0,("push_message: malloc fail (2)\n"));
423 msg->request_time = request_time;
424 msg->end_time = end_time;
425 msg->encrypted = req->encrypted;
428 msg->private_data = data_blob_talloc(msg, private_data,
430 if (msg->private_data.data == NULL) {
431 DEBUG(0,("push_message: malloc fail (3)\n"));
437 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
439 DEBUG(10,("push_message: pushed message length %u on "
440 "deferred_open_queue\n", (unsigned int)msg_len));
445 /****************************************************************************
446 Function to delete a sharing violation open message by mid.
447 ****************************************************************************/
449 void remove_deferred_open_smb_message(uint16 mid)
451 struct pending_message_list *pml;
453 for (pml = deferred_open_queue; pml; pml = pml->next) {
454 if (mid == SVAL(pml->buf.data,smb_mid)) {
455 DEBUG(10,("remove_sharing_violation_open_smb_message: "
456 "deleting mid %u len %u\n",
458 (unsigned int)pml->buf.length ));
459 DLIST_REMOVE(deferred_open_queue, pml);
466 /****************************************************************************
467 Move a sharing violation open retry message to the front of the list and
468 schedule it for immediate processing.
469 ****************************************************************************/
471 void schedule_deferred_open_smb_message(uint16 mid)
473 struct pending_message_list *pml;
476 for (pml = deferred_open_queue; pml; pml = pml->next) {
477 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
478 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
479 (unsigned int)msg_mid ));
480 if (mid == msg_mid) {
481 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
483 pml->end_time.tv_sec = 0;
484 pml->end_time.tv_usec = 0;
485 DLIST_PROMOTE(deferred_open_queue, pml);
490 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
494 /****************************************************************************
495 Return true if this mid is on the deferred queue.
496 ****************************************************************************/
498 bool open_was_deferred(uint16 mid)
500 struct pending_message_list *pml;
502 for (pml = deferred_open_queue; pml; pml = pml->next) {
503 if (SVAL(pml->buf.data,smb_mid) == mid) {
510 /****************************************************************************
511 Return the message queued by this mid.
512 ****************************************************************************/
514 struct pending_message_list *get_open_deferred_message(uint16 mid)
516 struct pending_message_list *pml;
518 for (pml = deferred_open_queue; pml; pml = pml->next) {
519 if (SVAL(pml->buf.data,smb_mid) == mid) {
526 /****************************************************************************
527 Function to push a deferred open smb message onto a linked list of local smb
528 messages ready for processing.
529 ****************************************************************************/
531 bool push_deferred_smb_message(struct smb_request *req,
532 struct timeval request_time,
533 struct timeval timeout,
534 char *private_data, size_t priv_len)
536 struct timeval end_time;
538 if (req->unread_bytes) {
539 DEBUG(0,("push_deferred_smb_message: logic error ! "
540 "unread_bytes = %u\n",
541 (unsigned int)req->unread_bytes ));
542 smb_panic("push_deferred_smb_message: "
543 "logic error unread_bytes != 0" );
546 end_time = timeval_sum(&request_time, &timeout);
548 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
549 "timeout time [%u.%06u]\n",
550 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
551 (unsigned int)end_time.tv_sec,
552 (unsigned int)end_time.tv_usec));
554 return push_queued_message(req, request_time, end_time,
555 private_data, priv_len);
559 struct timed_event *te;
560 struct timeval interval;
562 bool (*handler)(const struct timeval *now, void *private_data);
566 static void smbd_idle_event_handler(struct event_context *ctx,
567 struct timed_event *te,
571 struct idle_event *event =
572 talloc_get_type_abort(private_data, struct idle_event);
574 TALLOC_FREE(event->te);
576 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
577 event->name, event->te));
579 if (!event->handler(&now, event->private_data)) {
580 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
581 event->name, event->te));
582 /* Don't repeat, delete ourselves */
587 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
588 event->name, event->te));
590 event->te = event_add_timed(ctx, event,
591 timeval_sum(&now, &event->interval),
592 smbd_idle_event_handler, event);
594 /* We can't do much but fail here. */
595 SMB_ASSERT(event->te != NULL);
598 struct idle_event *event_add_idle(struct event_context *event_ctx,
600 struct timeval interval,
602 bool (*handler)(const struct timeval *now,
606 struct idle_event *result;
607 struct timeval now = timeval_current();
609 result = TALLOC_P(mem_ctx, struct idle_event);
610 if (result == NULL) {
611 DEBUG(0, ("talloc failed\n"));
615 result->interval = interval;
616 result->handler = handler;
617 result->private_data = private_data;
619 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
620 DEBUG(0, ("talloc failed\n"));
625 result->te = event_add_timed(event_ctx, result,
626 timeval_sum(&now, &interval),
627 smbd_idle_event_handler, result);
628 if (result->te == NULL) {
629 DEBUG(0, ("event_add_timed failed\n"));
634 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
638 /****************************************************************************
639 Do all async processing in here. This includes kernel oplock messages, change
641 ****************************************************************************/
643 static void async_processing(fd_set *pfds)
645 DEBUG(10,("async_processing: Doing async processing.\n"));
649 process_kernel_oplocks(smbd_messaging_context(), pfds);
651 /* Do the aio check again after receive_local_message as it does a
652 select and may have eaten our signal. */
653 /* Is this till true? -- vl */
657 exit_server_cleanly("termination signal");
660 /* check for sighup processing */
661 if (reload_after_sighup) {
662 change_to_root_user();
663 DEBUG(1,("Reloading services after SIGHUP\n"));
664 reload_services(False);
665 reload_after_sighup = 0;
669 /****************************************************************************
670 Add a fd to the set we will be select(2)ing on.
671 ****************************************************************************/
673 static int select_on_fd(int fd, int maxfd, fd_set *fds)
677 maxfd = MAX(maxfd, fd);
683 /****************************************************************************
684 Do a select on an two fd's - with timeout.
686 If a local udp message has been pushed onto the
687 queue (this can only happen during oplock break
688 processing) call async_processing()
690 If a pending smb message has been pushed onto the
691 queue (this can only happen during oplock break
692 processing) return this next.
694 If the first smbfd is ready then read an smb from it.
695 if the second (loopback UDP) fd is ready then read a message
696 from it and setup the buffer header to identify the length
698 Returns False on timeout or error.
701 The timeout is in milliseconds
702 ****************************************************************************/
704 static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
706 size_t *p_unread, bool *p_encrypted)
717 to.tv_sec = SMBD_SELECT_TIMEOUT;
721 * Note that this call must be before processing any SMB
722 * messages as we need to synchronously process any messages
723 * we may have sent to ourselves from the previous SMB.
725 message_dispatch(smbd_messaging_context());
728 * Check to see if we already have a message on the deferred open queue
729 * and it's time to schedule.
731 if(deferred_open_queue != NULL) {
732 bool pop_message = False;
733 struct pending_message_list *msg = deferred_open_queue;
735 if (timeval_is_zero(&msg->end_time)) {
742 tdif = usec_time_diff(&msg->end_time, &tv);
744 /* Timed out. Schedule...*/
746 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
748 /* Make a more accurate select timeout. */
749 to.tv_sec = tdif / 1000000;
750 to.tv_usec = tdif % 1000000;
751 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
752 (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
758 *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
760 if (*buffer == NULL) {
761 DEBUG(0, ("talloc failed\n"));
762 return NT_STATUS_NO_MEMORY;
764 *buffer_len = msg->buf.length;
765 *p_encrypted = msg->encrypted;
767 /* We leave this message on the queue so the open code can
768 know this is a retry. */
769 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
775 * Setup the select fd sets.
782 * Ensure we process oplock break messages by preference.
783 * We have to do this before the select, after the select
784 * and if the select returns EINTR. This is due to the fact
785 * that the selects called from async_processing can eat an EINTR
786 * caused by a signal (we can't take the break message there).
787 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
790 if (oplock_message_waiting(&r_fds)) {
791 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
792 async_processing(&r_fds);
794 * After async processing we must go and do the select again, as
795 * the state of the flag in fds for the server file descriptor is
796 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
798 return NT_STATUS_RETRY;
802 * Are there any timed events waiting ? If so, ensure we don't
803 * select for longer than it would take to wait for them.
810 event_add_to_select_args(smbd_event_context(), &now,
811 &r_fds, &w_fds, &to, &maxfd);
814 if (timeval_is_zero(&to)) {
815 /* Process a timed event now... */
816 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
817 return NT_STATUS_RETRY;
823 START_PROFILE(smbd_idle);
825 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
826 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
828 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
831 END_PROFILE(smbd_idle);
835 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
836 return NT_STATUS_RETRY;
839 /* if we get EINTR then maybe we have received an oplock
840 signal - treat this as select returning 1. This is ugly, but
841 is the best we can do until the oplock code knows more about
843 if (selrtn == -1 && errno == EINTR) {
844 async_processing(&r_fds);
846 * After async processing we must go and do the select again, as
847 * the state of the flag in fds for the server file descriptor is
848 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
850 return NT_STATUS_RETRY;
855 /* something is wrong. Maybe the socket is dead? */
856 return map_nt_error_from_unix(errno);
859 /* Did we timeout ? */
861 return NT_STATUS_RETRY;
865 * Ensure we process oplock break messages by preference.
866 * This is IMPORTANT ! Otherwise we can starve other processes
867 * sending us an oplock break message. JRA.
870 if (oplock_message_waiting(&r_fds)) {
871 async_processing(&r_fds);
873 * After async processing we must go and do the select again, as
874 * the state of the flag in fds for the server file descriptor is
875 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
877 return NT_STATUS_RETRY;
881 * We've just woken up from a protentially long select sleep.
882 * Ensure we process local messages as we need to synchronously
883 * process any messages from other smbd's to avoid file rename race
884 * conditions. This call is cheap if there are no messages waiting.
887 message_dispatch(smbd_messaging_context());
889 status = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0,
890 p_unread, p_encrypted, &len);
892 if (!NT_STATUS_IS_OK(status)) {
902 * Only allow 5 outstanding trans requests. We're allocating memory, so
906 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
909 for (; list != NULL; list = list->next) {
911 if (list->mid == mid) {
912 return NT_STATUS_INVALID_PARAMETER;
918 return NT_STATUS_INSUFFICIENT_RESOURCES;
924 /****************************************************************************
925 We're terminating and have closed all our files/connections etc.
926 If there are any pending local messages we need to respond to them
927 before termination so that other smbds don't think we just died whilst
929 ****************************************************************************/
931 void respond_to_all_remaining_local_messages(void)
934 * Assert we have no exclusive open oplocks.
937 if(get_number_of_exclusive_open_oplocks()) {
938 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
939 get_number_of_exclusive_open_oplocks() ));
943 process_kernel_oplocks(smbd_messaging_context(), NULL);
950 These flags determine some of the permissions required to do an operation
952 Note that I don't set NEED_WRITE on some write operations because they
953 are used by some brain-dead clients when printing, and I don't want to
954 force write permissions on print services.
956 #define AS_USER (1<<0)
957 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
958 #define TIME_INIT (1<<2)
959 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
960 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
961 #define DO_CHDIR (1<<6)
964 define a list of possible SMB messages and their corresponding
965 functions. Any message that has a NULL function is unimplemented -
966 please feel free to contribute implementations!
968 static const struct smb_message_struct {
970 void (*fn)(struct smb_request *req);
972 } smb_messages[256] = {
974 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
975 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
976 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
977 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
978 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
979 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
980 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
981 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
982 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
983 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
984 /* 0x0a */ { "SMBread",reply_read,AS_USER},
985 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
986 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
987 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
988 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
989 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
990 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
991 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
992 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
993 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
994 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
995 /* 0x15 */ { NULL, NULL, 0 },
996 /* 0x16 */ { NULL, NULL, 0 },
997 /* 0x17 */ { NULL, NULL, 0 },
998 /* 0x18 */ { NULL, NULL, 0 },
999 /* 0x19 */ { NULL, NULL, 0 },
1000 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
1001 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
1002 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
1003 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
1004 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1005 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1006 /* 0x20 */ { "SMBwritec", NULL,0},
1007 /* 0x21 */ { NULL, NULL, 0 },
1008 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1009 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1010 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1011 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1012 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1013 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
1014 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
1015 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1016 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1017 /* 0x2b */ { "SMBecho",reply_echo,0},
1018 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1019 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1020 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1021 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1022 /* 0x30 */ { NULL, NULL, 0 },
1023 /* 0x31 */ { NULL, NULL, 0 },
1024 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1025 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
1026 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1027 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1028 /* 0x36 */ { NULL, NULL, 0 },
1029 /* 0x37 */ { NULL, NULL, 0 },
1030 /* 0x38 */ { NULL, NULL, 0 },
1031 /* 0x39 */ { NULL, NULL, 0 },
1032 /* 0x3a */ { NULL, NULL, 0 },
1033 /* 0x3b */ { NULL, NULL, 0 },
1034 /* 0x3c */ { NULL, NULL, 0 },
1035 /* 0x3d */ { NULL, NULL, 0 },
1036 /* 0x3e */ { NULL, NULL, 0 },
1037 /* 0x3f */ { NULL, NULL, 0 },
1038 /* 0x40 */ { NULL, NULL, 0 },
1039 /* 0x41 */ { NULL, NULL, 0 },
1040 /* 0x42 */ { NULL, NULL, 0 },
1041 /* 0x43 */ { NULL, NULL, 0 },
1042 /* 0x44 */ { NULL, NULL, 0 },
1043 /* 0x45 */ { NULL, NULL, 0 },
1044 /* 0x46 */ { NULL, NULL, 0 },
1045 /* 0x47 */ { NULL, NULL, 0 },
1046 /* 0x48 */ { NULL, NULL, 0 },
1047 /* 0x49 */ { NULL, NULL, 0 },
1048 /* 0x4a */ { NULL, NULL, 0 },
1049 /* 0x4b */ { NULL, NULL, 0 },
1050 /* 0x4c */ { NULL, NULL, 0 },
1051 /* 0x4d */ { NULL, NULL, 0 },
1052 /* 0x4e */ { NULL, NULL, 0 },
1053 /* 0x4f */ { NULL, NULL, 0 },
1054 /* 0x50 */ { NULL, NULL, 0 },
1055 /* 0x51 */ { NULL, NULL, 0 },
1056 /* 0x52 */ { NULL, NULL, 0 },
1057 /* 0x53 */ { NULL, NULL, 0 },
1058 /* 0x54 */ { NULL, NULL, 0 },
1059 /* 0x55 */ { NULL, NULL, 0 },
1060 /* 0x56 */ { NULL, NULL, 0 },
1061 /* 0x57 */ { NULL, NULL, 0 },
1062 /* 0x58 */ { NULL, NULL, 0 },
1063 /* 0x59 */ { NULL, NULL, 0 },
1064 /* 0x5a */ { NULL, NULL, 0 },
1065 /* 0x5b */ { NULL, NULL, 0 },
1066 /* 0x5c */ { NULL, NULL, 0 },
1067 /* 0x5d */ { NULL, NULL, 0 },
1068 /* 0x5e */ { NULL, NULL, 0 },
1069 /* 0x5f */ { NULL, NULL, 0 },
1070 /* 0x60 */ { NULL, NULL, 0 },
1071 /* 0x61 */ { NULL, NULL, 0 },
1072 /* 0x62 */ { NULL, NULL, 0 },
1073 /* 0x63 */ { NULL, NULL, 0 },
1074 /* 0x64 */ { NULL, NULL, 0 },
1075 /* 0x65 */ { NULL, NULL, 0 },
1076 /* 0x66 */ { NULL, NULL, 0 },
1077 /* 0x67 */ { NULL, NULL, 0 },
1078 /* 0x68 */ { NULL, NULL, 0 },
1079 /* 0x69 */ { NULL, NULL, 0 },
1080 /* 0x6a */ { NULL, NULL, 0 },
1081 /* 0x6b */ { NULL, NULL, 0 },
1082 /* 0x6c */ { NULL, NULL, 0 },
1083 /* 0x6d */ { NULL, NULL, 0 },
1084 /* 0x6e */ { NULL, NULL, 0 },
1085 /* 0x6f */ { NULL, NULL, 0 },
1086 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1087 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1088 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1089 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1090 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1091 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1092 /* 0x76 */ { NULL, NULL, 0 },
1093 /* 0x77 */ { NULL, NULL, 0 },
1094 /* 0x78 */ { NULL, NULL, 0 },
1095 /* 0x79 */ { NULL, NULL, 0 },
1096 /* 0x7a */ { NULL, NULL, 0 },
1097 /* 0x7b */ { NULL, NULL, 0 },
1098 /* 0x7c */ { NULL, NULL, 0 },
1099 /* 0x7d */ { NULL, NULL, 0 },
1100 /* 0x7e */ { NULL, NULL, 0 },
1101 /* 0x7f */ { NULL, NULL, 0 },
1102 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1103 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1104 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1105 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1106 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1107 /* 0x85 */ { NULL, NULL, 0 },
1108 /* 0x86 */ { NULL, NULL, 0 },
1109 /* 0x87 */ { NULL, NULL, 0 },
1110 /* 0x88 */ { NULL, NULL, 0 },
1111 /* 0x89 */ { NULL, NULL, 0 },
1112 /* 0x8a */ { NULL, NULL, 0 },
1113 /* 0x8b */ { NULL, NULL, 0 },
1114 /* 0x8c */ { NULL, NULL, 0 },
1115 /* 0x8d */ { NULL, NULL, 0 },
1116 /* 0x8e */ { NULL, NULL, 0 },
1117 /* 0x8f */ { NULL, NULL, 0 },
1118 /* 0x90 */ { NULL, NULL, 0 },
1119 /* 0x91 */ { NULL, NULL, 0 },
1120 /* 0x92 */ { NULL, NULL, 0 },
1121 /* 0x93 */ { NULL, NULL, 0 },
1122 /* 0x94 */ { NULL, NULL, 0 },
1123 /* 0x95 */ { NULL, NULL, 0 },
1124 /* 0x96 */ { NULL, NULL, 0 },
1125 /* 0x97 */ { NULL, NULL, 0 },
1126 /* 0x98 */ { NULL, NULL, 0 },
1127 /* 0x99 */ { NULL, NULL, 0 },
1128 /* 0x9a */ { NULL, NULL, 0 },
1129 /* 0x9b */ { NULL, NULL, 0 },
1130 /* 0x9c */ { NULL, NULL, 0 },
1131 /* 0x9d */ { NULL, NULL, 0 },
1132 /* 0x9e */ { NULL, NULL, 0 },
1133 /* 0x9f */ { NULL, NULL, 0 },
1134 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1135 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1136 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1137 /* 0xa3 */ { NULL, NULL, 0 },
1138 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1139 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1140 /* 0xa6 */ { NULL, NULL, 0 },
1141 /* 0xa7 */ { NULL, NULL, 0 },
1142 /* 0xa8 */ { NULL, NULL, 0 },
1143 /* 0xa9 */ { NULL, NULL, 0 },
1144 /* 0xaa */ { NULL, NULL, 0 },
1145 /* 0xab */ { NULL, NULL, 0 },
1146 /* 0xac */ { NULL, NULL, 0 },
1147 /* 0xad */ { NULL, NULL, 0 },
1148 /* 0xae */ { NULL, NULL, 0 },
1149 /* 0xaf */ { NULL, NULL, 0 },
1150 /* 0xb0 */ { NULL, NULL, 0 },
1151 /* 0xb1 */ { NULL, NULL, 0 },
1152 /* 0xb2 */ { NULL, NULL, 0 },
1153 /* 0xb3 */ { NULL, NULL, 0 },
1154 /* 0xb4 */ { NULL, NULL, 0 },
1155 /* 0xb5 */ { NULL, NULL, 0 },
1156 /* 0xb6 */ { NULL, NULL, 0 },
1157 /* 0xb7 */ { NULL, NULL, 0 },
1158 /* 0xb8 */ { NULL, NULL, 0 },
1159 /* 0xb9 */ { NULL, NULL, 0 },
1160 /* 0xba */ { NULL, NULL, 0 },
1161 /* 0xbb */ { NULL, NULL, 0 },
1162 /* 0xbc */ { NULL, NULL, 0 },
1163 /* 0xbd */ { NULL, NULL, 0 },
1164 /* 0xbe */ { NULL, NULL, 0 },
1165 /* 0xbf */ { NULL, NULL, 0 },
1166 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1167 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1168 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1169 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1170 /* 0xc4 */ { NULL, NULL, 0 },
1171 /* 0xc5 */ { NULL, NULL, 0 },
1172 /* 0xc6 */ { NULL, NULL, 0 },
1173 /* 0xc7 */ { NULL, NULL, 0 },
1174 /* 0xc8 */ { NULL, NULL, 0 },
1175 /* 0xc9 */ { NULL, NULL, 0 },
1176 /* 0xca */ { NULL, NULL, 0 },
1177 /* 0xcb */ { NULL, NULL, 0 },
1178 /* 0xcc */ { NULL, NULL, 0 },
1179 /* 0xcd */ { NULL, NULL, 0 },
1180 /* 0xce */ { NULL, NULL, 0 },
1181 /* 0xcf */ { NULL, NULL, 0 },
1182 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1183 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1184 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1185 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1186 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1187 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1188 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1189 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1190 /* 0xd8 */ { NULL, NULL, 0 },
1191 /* 0xd9 */ { NULL, NULL, 0 },
1192 /* 0xda */ { NULL, NULL, 0 },
1193 /* 0xdb */ { NULL, NULL, 0 },
1194 /* 0xdc */ { NULL, NULL, 0 },
1195 /* 0xdd */ { NULL, NULL, 0 },
1196 /* 0xde */ { NULL, NULL, 0 },
1197 /* 0xdf */ { NULL, NULL, 0 },
1198 /* 0xe0 */ { NULL, NULL, 0 },
1199 /* 0xe1 */ { NULL, NULL, 0 },
1200 /* 0xe2 */ { NULL, NULL, 0 },
1201 /* 0xe3 */ { NULL, NULL, 0 },
1202 /* 0xe4 */ { NULL, NULL, 0 },
1203 /* 0xe5 */ { NULL, NULL, 0 },
1204 /* 0xe6 */ { NULL, NULL, 0 },
1205 /* 0xe7 */ { NULL, NULL, 0 },
1206 /* 0xe8 */ { NULL, NULL, 0 },
1207 /* 0xe9 */ { NULL, NULL, 0 },
1208 /* 0xea */ { NULL, NULL, 0 },
1209 /* 0xeb */ { NULL, NULL, 0 },
1210 /* 0xec */ { NULL, NULL, 0 },
1211 /* 0xed */ { NULL, NULL, 0 },
1212 /* 0xee */ { NULL, NULL, 0 },
1213 /* 0xef */ { NULL, NULL, 0 },
1214 /* 0xf0 */ { NULL, NULL, 0 },
1215 /* 0xf1 */ { NULL, NULL, 0 },
1216 /* 0xf2 */ { NULL, NULL, 0 },
1217 /* 0xf3 */ { NULL, NULL, 0 },
1218 /* 0xf4 */ { NULL, NULL, 0 },
1219 /* 0xf5 */ { NULL, NULL, 0 },
1220 /* 0xf6 */ { NULL, NULL, 0 },
1221 /* 0xf7 */ { NULL, NULL, 0 },
1222 /* 0xf8 */ { NULL, NULL, 0 },
1223 /* 0xf9 */ { NULL, NULL, 0 },
1224 /* 0xfa */ { NULL, NULL, 0 },
1225 /* 0xfb */ { NULL, NULL, 0 },
1226 /* 0xfc */ { NULL, NULL, 0 },
1227 /* 0xfd */ { NULL, NULL, 0 },
1228 /* 0xfe */ { NULL, NULL, 0 },
1229 /* 0xff */ { NULL, NULL, 0 }
1233 /*******************************************************************
1234 allocate and initialize a reply packet
1235 ********************************************************************/
1237 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1238 const char *inbuf, char **outbuf, uint8_t num_words,
1242 * Protect against integer wrap
1244 if ((num_bytes > 0xffffff)
1245 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1247 if (asprintf(&msg, "num_bytes too large: %u",
1248 (unsigned)num_bytes) == -1) {
1249 msg = CONST_DISCARD(char *, "num_bytes too large");
1254 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1255 smb_size + num_words*2 + num_bytes);
1256 if (*outbuf == NULL) {
1260 construct_reply_common(req, inbuf, *outbuf);
1261 srv_set_message(*outbuf, num_words, num_bytes, false);
1263 * Zero out the word area, the caller has to take care of the bcc area
1266 if (num_words != 0) {
1267 memset(*outbuf + smb_vwv0, 0, num_words*2);
1273 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1276 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1278 smb_panic("could not allocate output buffer\n");
1280 req->outbuf = (uint8_t *)outbuf;
1284 /*******************************************************************
1285 Dump a packet to a file.
1286 ********************************************************************/
1288 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1292 if (DEBUGLEVEL < 50) {
1296 if (len < 4) len = smb_len(data)+4;
1297 for (i=1;i<100;i++) {
1298 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1299 type ? "req" : "resp") == -1) {
1302 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1303 if (fd != -1 || errno != EEXIST) break;
1306 ssize_t ret = write(fd, data, len);
1308 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1310 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1315 /****************************************************************************
1316 Prepare everything for calling the actual request function, and potentially
1317 call the request function via the "new" interface.
1319 Return False if the "legacy" function needs to be called, everything is
1322 Return True if we're done.
1324 I know this API sucks, but it is the one with the least code change I could
1326 ****************************************************************************/
1328 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1332 connection_struct *conn = NULL;
1336 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1337 * so subtract 4 from it. */
1338 if (!valid_smb_header(req->inbuf)
1339 || (size < (smb_size - 4))) {
1340 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1341 smb_len(req->inbuf)));
1342 exit_server_cleanly("Non-SMB packet");
1345 if (smb_messages[type].fn == NULL) {
1346 DEBUG(0,("Unknown message type %d!\n",type));
1347 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1348 reply_unknown_new(req, type);
1352 flags = smb_messages[type].flags;
1354 /* In share mode security we must ignore the vuid. */
1355 session_tag = (lp_security() == SEC_SHARE)
1356 ? UID_FIELD_INVALID : req->vuid;
1359 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1360 (int)sys_getpid(), (unsigned long)conn));
1362 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1364 /* Ensure this value is replaced in the incoming packet. */
1365 SSVAL(req->inbuf,smb_uid,session_tag);
1368 * Ensure the correct username is in current_user_info. This is a
1369 * really ugly bugfix for problems with multiple session_setup_and_X's
1370 * being done and allowing %U and %G substitutions to work correctly.
1371 * There is a reason this code is done here, don't move it unless you
1372 * know what you're doing... :-).
1376 if (session_tag != last_session_tag) {
1377 user_struct *vuser = NULL;
1379 last_session_tag = session_tag;
1380 if(session_tag != UID_FIELD_INVALID) {
1381 vuser = get_valid_user_struct(session_tag);
1383 set_current_user_info(
1384 vuser->server_info->sanitized_username,
1385 vuser->server_info->unix_name,
1386 pdb_get_fullname(vuser->server_info
1388 pdb_get_domain(vuser->server_info
1394 /* Does this call need to be run as the connected user? */
1395 if (flags & AS_USER) {
1397 /* Does this call need a valid tree connection? */
1400 * Amazingly, the error code depends on the command
1403 if (type == SMBntcreateX) {
1404 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1406 reply_doserror(req, ERRSRV, ERRinvnid);
1411 if (!change_to_user(conn,session_tag)) {
1412 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1413 remove_deferred_open_smb_message(req->mid);
1417 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1419 /* Does it need write permission? */
1420 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1421 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1425 /* IPC services are limited */
1426 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1427 reply_doserror(req, ERRSRV,ERRaccess);
1431 /* This call needs to be run as root */
1432 change_to_root_user();
1435 /* load service specific parameters */
1437 if (req->encrypted) {
1438 conn->encrypted_tid = true;
1439 /* encrypted required from now on. */
1440 conn->encrypt_level = Required;
1441 } else if (ENCRYPTION_REQUIRED(conn)) {
1442 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1443 exit_server_cleanly("encryption required "
1449 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1450 (flags & (AS_USER|DO_CHDIR)
1452 reply_doserror(req, ERRSRV, ERRaccess);
1455 conn->num_smb_operations++;
1458 /* does this protocol need to be run as guest? */
1459 if ((flags & AS_GUEST)
1460 && (!change_to_guest() ||
1461 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1462 lp_hostsdeny(-1)))) {
1463 reply_doserror(req, ERRSRV, ERRaccess);
1467 smb_messages[type].fn(req);
1471 /****************************************************************************
1472 Construct a reply to the incoming packet.
1473 ****************************************************************************/
1475 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1477 connection_struct *conn;
1478 struct smb_request *req;
1482 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1483 smb_panic("could not allocate smb_request");
1485 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1486 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1488 conn = switch_message(req->cmd, req, size);
1490 if (req->unread_bytes) {
1491 /* writeX failed. drain socket. */
1492 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1493 req->unread_bytes) {
1494 smb_panic("failed to drain pending bytes");
1496 req->unread_bytes = 0;
1499 if (req->outbuf == NULL) {
1503 if (CVAL(req->outbuf,0) == 0) {
1504 show_msg((char *)req->outbuf);
1507 if (!srv_send_smb(smbd_server_fd(),
1508 (char *)req->outbuf,
1509 IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1510 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1518 /****************************************************************************
1519 Process an smb from the client
1520 ****************************************************************************/
1522 static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted)
1524 int msg_type = CVAL(inbuf,0);
1526 DO_PROFILE_INC(smb_count);
1528 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1530 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1532 (unsigned int)unread_bytes ));
1534 if (msg_type != 0) {
1536 * NetBIOS session request, keepalive, etc.
1538 reply_special(inbuf);
1544 construct_reply(inbuf,nread,unread_bytes,encrypted);
1549 /****************************************************************************
1550 Return a string containing the function name of a SMB command.
1551 ****************************************************************************/
1553 const char *smb_fn_name(int type)
1555 const char *unknown_name = "SMBunknown";
1557 if (smb_messages[type].name == NULL)
1558 return(unknown_name);
1560 return(smb_messages[type].name);
1563 /****************************************************************************
1564 Helper functions for contruct_reply.
1565 ****************************************************************************/
1567 void add_to_common_flags2(uint32 v)
1572 void remove_from_common_flags2(uint32 v)
1574 common_flags2 &= ~v;
1577 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1580 srv_set_message(outbuf,0,0,false);
1582 SCVAL(outbuf, smb_com, req->cmd);
1583 SIVAL(outbuf,smb_rcls,0);
1584 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1585 SSVAL(outbuf,smb_flg2,
1586 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1588 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1590 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1591 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1592 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1593 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1596 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1598 construct_reply_common(req, (char *)req->inbuf, outbuf);
1601 /****************************************************************************
1602 Construct a chained reply and add it to the already made reply
1603 ****************************************************************************/
1605 void chain_reply(struct smb_request *req)
1608 * Dirty little const_discard: We mess with req->inbuf, which is
1609 * declared as const. If maybe at some point this routine gets
1610 * rewritten, this const_discard could go away.
1612 char *inbuf = CONST_DISCARD(char *, req->inbuf);
1613 int size = smb_len(req->inbuf)+4;
1615 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1616 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1620 char inbuf_saved[smb_wct];
1621 char *outbuf = (char *)req->outbuf;
1622 size_t outsize = smb_len(outbuf) + 4;
1623 size_t outsize_padded;
1625 size_t ofs, to_move;
1627 struct smb_request *req2;
1628 size_t caller_outputlen;
1629 char *caller_output;
1631 /* Maybe its not chained, or it's an error packet. */
1632 if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1633 SCVAL(outbuf,smb_vwv0,0xFF);
1637 if (chain_size == 0) {
1638 /* this is the first part of the chain */
1643 * We need to save the output the caller added to the chain so that we
1644 * can splice it into the final output buffer later.
1647 caller_outputlen = outsize - smb_wct;
1649 caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
1651 if (caller_output == NULL) {
1652 /* TODO: NT_STATUS_NO_MEMORY */
1653 smb_panic("could not dup outbuf");
1657 * The original Win95 redirector dies on a reply to
1658 * a lockingX and read chain unless the chain reply is
1659 * 4 byte aligned. JRA.
1662 outsize_padded = (outsize + 3) & ~3;
1663 padding = outsize_padded - outsize;
1666 * remember how much the caller added to the chain, only counting
1667 * stuff after the parameter words
1669 chain_size += (outsize_padded - smb_wct);
1672 * work out pointers into the original packets. The
1673 * headers on these need to be filled in
1675 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1677 /* remember the original command type */
1678 smb_com1 = CVAL(orig_inbuf,smb_com);
1680 /* save the data which will be overwritten by the new headers */
1681 memcpy(inbuf_saved,inbuf2,smb_wct);
1683 /* give the new packet the same header as the last part of the SMB */
1684 memmove(inbuf2,inbuf,smb_wct);
1686 /* create the in buffer */
1687 SCVAL(inbuf2,smb_com,smb_com2);
1689 /* work out the new size for the in buffer. */
1690 new_size = size - (inbuf2 - inbuf);
1692 DEBUG(0,("chain_reply: chain packet size incorrect "
1693 "(orig size = %d, offset = %d)\n",
1694 size, (int)(inbuf2 - inbuf) ));
1695 exit_server_cleanly("Bad chained packet");
1699 /* And set it in the header. */
1700 smb_setlen(inbuf2, new_size - 4);
1702 DEBUG(3,("Chained message\n"));
1705 if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
1706 smb_panic("could not allocate smb_request");
1708 init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted);
1709 req2->inbuf = (uint8_t *)inbuf2;
1710 req2->chain_fsp = req->chain_fsp;
1712 /* process the request */
1713 switch_message(smb_com2, req2, new_size);
1716 * We don't accept deferred operations in chained requests.
1718 SMB_ASSERT(req2->outbuf != NULL);
1719 outsize2 = smb_len(req2->outbuf)+4;
1722 * Move away the new command output so that caller_output fits in,
1723 * copy in the caller_output saved above.
1726 SMB_ASSERT(outsize_padded >= smb_wct);
1729 * "ofs" is the space we need for caller_output. Equal to
1730 * caller_outputlen plus the padding.
1733 ofs = outsize_padded - smb_wct;
1736 * "to_move" is the amount of bytes the secondary routine gave us
1739 to_move = outsize2 - smb_wct;
1741 if (to_move + ofs + smb_wct + chain_size > max_send) {
1742 smb_panic("replies too large -- would have to cut");
1746 * In the "new" API "outbuf" is allocated via reply_outbuf, just for
1747 * the first request in the chain. So we have to re-allocate it. In
1748 * the "old" API the only outbuf ever used is the global OutBuffer
1749 * which is always large enough.
1752 outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
1753 to_move + ofs + smb_wct);
1754 if (outbuf == NULL) {
1755 smb_panic("could not realloc outbuf");
1758 req->outbuf = (uint8 *)outbuf;
1760 memmove(outbuf + smb_wct + ofs, req2->outbuf + smb_wct, to_move);
1761 memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
1764 * copy the new reply header over the old one but preserve the smb_com
1767 memmove(outbuf, req2->outbuf, smb_wct);
1768 SCVAL(outbuf, smb_com, smb_com1);
1771 * We've just copied in the whole "wct" area from the secondary
1772 * function. Fix up the chaining: com2 and the offset need to be
1776 SCVAL(outbuf, smb_vwv0, smb_com2);
1777 SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
1782 * Due to padding we have some uninitialized bytes after the
1786 memset(outbuf + outsize, 0, padding);
1789 smb_setlen(outbuf, outsize2 + caller_outputlen + padding - 4);
1792 * restore the saved data, being careful not to overwrite any data
1793 * from the reply header
1795 memcpy(inbuf2,inbuf_saved,smb_wct);
1797 SAFE_FREE(caller_output);
1801 * Reset the chain_size for our caller's offset calculations
1804 chain_size -= (outsize_padded - smb_wct);
1809 /****************************************************************************
1810 Check if services need reloading.
1811 ****************************************************************************/
1813 void check_reload(time_t t)
1815 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1817 if(last_smb_conf_reload_time == 0) {
1818 last_smb_conf_reload_time = t;
1819 /* Our printing subsystem might not be ready at smbd start up.
1820 Then no printer is available till the first printers check
1821 is performed. A lower initial interval circumvents this. */
1822 if ( printcap_cache_time > 60 )
1823 last_printer_reload_time = t - printcap_cache_time + 60;
1825 last_printer_reload_time = t;
1828 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1829 /* randomize over 60 second the printcap reload to avoid all
1830 * process hitting cupsd at the same time */
1831 int time_range = 60;
1833 last_printer_reload_time += random() % time_range;
1837 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1838 reload_services(True);
1839 reload_after_sighup = False;
1840 last_smb_conf_reload_time = t;
1843 /* 'printcap cache time = 0' disable the feature */
1845 if ( printcap_cache_time != 0 )
1847 /* see if it's time to reload or if the clock has been set back */
1849 if ( (t >= last_printer_reload_time+printcap_cache_time)
1850 || (t-last_printer_reload_time < 0) )
1852 DEBUG( 3,( "Printcap cache time expired.\n"));
1854 last_printer_reload_time = t;
1859 /****************************************************************************
1860 Process commands from the client
1861 ****************************************************************************/
1863 void smbd_process(void)
1865 unsigned int num_smbs = 0;
1866 size_t unread_bytes = 0;
1868 char addr[INET6_ADDRSTRLEN];
1871 * Before the first packet, check the global hosts allow/ hosts deny
1872 * parameters before doing any parsing of packets passed to us by the
1873 * client. This prevents attacks on our parsing code from hosts not in
1874 * the hosts allow list.
1877 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1878 lp_hostsdeny(-1))) {
1880 * send a negative session response "not listening on calling
1883 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1884 DEBUG( 1, ("Connection denied from %s\n",
1885 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1886 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1887 exit_server_cleanly("connection denied");
1890 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1895 size_t inbuf_len = 0;
1896 bool encrypted = false;
1897 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
1901 run_events(smbd_event_context(), 0, NULL, NULL);
1903 status = NT_STATUS_RETRY;
1905 while (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1906 status = receive_message_or_smb(
1907 talloc_tos(), &inbuf, &inbuf_len,
1908 &unread_bytes, &encrypted);
1911 if (!NT_STATUS_IS_OK(status)) {
1912 DEBUG(3, ("receive_message_or_smb failed: %s, "
1913 "exiting\n", nt_errstr(status)));
1917 process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
1921 /* The timeout_processing function isn't run nearly
1922 often enough to implement 'max log size' without
1923 overrunning the size of the file by many megabytes.
1924 This is especially true if we are running at debug
1925 level 10. Checking every 50 SMBs is a nice
1926 tradeoff of performance vs log file size overrun. */
1928 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1929 change_to_root_user();