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/>.
23 extern struct auth_context *negprot_global_auth_context;
24 extern int smb_echo_count;
26 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
28 static char *InBuffer = NULL;
29 static char *OutBuffer = NULL;
30 static const char *current_inbuf = NULL;
32 static char *NewInBuffer(char **old_inbuf);
33 static char *NewOutBuffer(char **old_outbuf);
36 * Size of data we can send to client. Set
37 * by the client for all protocols above CORE.
38 * Set by us for CORE protocol.
40 int max_send = BUFFER_SIZE;
42 * Size of the data we can receive. Set by us.
43 * Can be modified by the max xmit parameter.
45 int max_recv = BUFFER_SIZE;
47 extern int last_message;
48 extern int smb_read_error;
49 SIG_ATOMIC_T reload_after_sighup = 0;
50 SIG_ATOMIC_T got_sig_term = 0;
51 extern BOOL global_machine_password_needs_changing;
55 * Initialize a struct smb_request from an inbuf
58 void init_smb_request(struct smb_request *req, const uint8 *inbuf)
60 req->flags2 = SVAL(inbuf, smb_flg2);
61 req->smbpid = SVAL(inbuf, smb_pid);
62 req->mid = SVAL(inbuf, smb_mid);
63 req->vuid = SVAL(inbuf, smb_uid);
64 req->tid = SVAL(inbuf, smb_tid);
65 req->wct = CVAL(inbuf, smb_wct);
71 * From within a converted call you might have to call non-converted
72 * subroutines that still take the old inbuf/outbuf/lenght/bufsize
73 * parameters. This takes a struct smb_request and prepares the legacy
77 BOOL reply_prep_legacy(struct smb_request *req,
78 char **pinbuf, char **poutbuf,
79 int *psize, int *pbufsize)
81 const int bufsize = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE
85 if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) {
86 DEBUG(0, ("Could not allocate legacy inbuf\n"));
89 memcpy(inbuf, req->inbuf, MIN(smb_len(req->inbuf)+4, bufsize));
90 req->inbuf = (uint8 *)inbuf;
92 if (!(outbuf = TALLOC_ARRAY(req, char, bufsize))) {
93 DEBUG(0, ("Could not allocate legacy outbuf\n"));
96 req->outbuf = (uint8 *)outbuf;
98 construct_reply_common(inbuf, outbuf);
102 *psize = smb_len(inbuf)+4;
109 * Post-process the output of the legacy routine so that the result fits into
110 * the new reply_xxx API
113 void reply_post_legacy(struct smb_request *req, int outsize)
116 smb_setlen((char *)req->inbuf, (char *)req->outbuf,
120 TALLOC_FREE(req->outbuf);
124 /****************************************************************************
125 structure to hold a linked list of queued messages.
127 ****************************************************************************/
129 static struct pending_message_list *deferred_open_queue;
131 /****************************************************************************
132 Function to push a message onto the tail of a linked list of smb messages
133 ready for processing.
134 ****************************************************************************/
136 static BOOL push_queued_message(const char *buf, int msg_len,
137 struct timeval request_time,
138 struct timeval end_time,
139 char *private_data, size_t private_len)
141 struct pending_message_list *msg;
143 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
146 DEBUG(0,("push_message: malloc fail (1)\n"));
150 msg->buf = data_blob_talloc(msg, buf, msg_len);
151 if(msg->buf.data == NULL) {
152 DEBUG(0,("push_message: malloc fail (2)\n"));
157 msg->request_time = request_time;
158 msg->end_time = end_time;
161 msg->private_data = data_blob_talloc(msg, private_data,
163 if (msg->private_data.data == NULL) {
164 DEBUG(0,("push_message: malloc fail (3)\n"));
170 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
172 DEBUG(10,("push_message: pushed message length %u on "
173 "deferred_open_queue\n", (unsigned int)msg_len));
178 /****************************************************************************
179 Function to delete a sharing violation open message by mid.
180 ****************************************************************************/
182 void remove_deferred_open_smb_message(uint16 mid)
184 struct pending_message_list *pml;
186 for (pml = deferred_open_queue; pml; pml = pml->next) {
187 if (mid == SVAL(pml->buf.data,smb_mid)) {
188 DEBUG(10,("remove_deferred_open_smb_message: "
189 "deleting mid %u len %u\n",
191 (unsigned int)pml->buf.length ));
192 DLIST_REMOVE(deferred_open_queue, pml);
199 /****************************************************************************
200 Move a sharing violation open retry message to the front of the list and
201 schedule it for immediate processing.
202 ****************************************************************************/
204 void schedule_deferred_open_smb_message(uint16 mid)
206 struct pending_message_list *pml;
209 for (pml = deferred_open_queue; pml; pml = pml->next) {
210 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
211 DEBUG(10, ("schedule_deferred_open_smb_message: [%d] "
212 "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
213 if (mid == msg_mid) {
214 DEBUG(10, ("schedule_deferred_open_smb_message: "
215 "scheduling mid %u\n", mid));
216 pml->end_time.tv_sec = 0;
217 pml->end_time.tv_usec = 0;
218 DLIST_PROMOTE(deferred_open_queue, pml);
223 DEBUG(10, ("schedule_deferred_open_smb_message: failed to find "
224 "message mid %u\n", mid ));
227 /****************************************************************************
228 Return true if this mid is on the deferred queue.
229 ****************************************************************************/
231 BOOL open_was_deferred(uint16 mid)
233 struct pending_message_list *pml;
235 for (pml = deferred_open_queue; pml; pml = pml->next) {
236 if (SVAL(pml->buf.data,smb_mid) == mid) {
243 /****************************************************************************
244 Return the message queued by this mid.
245 ****************************************************************************/
247 struct pending_message_list *get_open_deferred_message(uint16 mid)
249 struct pending_message_list *pml;
251 for (pml = deferred_open_queue; pml; pml = pml->next) {
252 if (SVAL(pml->buf.data,smb_mid) == mid) {
259 /****************************************************************************
260 Function to push a deferred open smb message onto a linked list of local smb
261 messages ready for processing.
262 ****************************************************************************/
264 BOOL push_deferred_smb_message(uint16 mid,
265 struct timeval request_time,
266 struct timeval timeout,
267 char *private_data, size_t priv_len)
269 struct timeval end_time;
271 end_time = timeval_sum(&request_time, &timeout);
273 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
274 "timeout time [%u.%06u]\n",
275 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
276 (unsigned int)end_time.tv_sec,
277 (unsigned int)end_time.tv_usec));
279 return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
280 request_time, end_time,
281 private_data, priv_len);
285 struct timed_event *te;
286 struct timeval interval;
288 BOOL (*handler)(const struct timeval *now, void *private_data);
292 static void idle_event_handler(struct event_context *ctx,
293 struct timed_event *te,
294 const struct timeval *now,
297 struct idle_event *event =
298 talloc_get_type_abort(private_data, struct idle_event);
300 TALLOC_FREE(event->te);
302 if (!event->handler(now, event->private_data)) {
303 /* Don't repeat, delete ourselves */
308 event->te = event_add_timed(ctx, event,
309 timeval_sum(now, &event->interval),
311 idle_event_handler, event);
313 /* We can't do much but fail here. */
314 SMB_ASSERT(event->te != NULL);
317 struct idle_event *event_add_idle(struct event_context *event_ctx,
319 struct timeval interval,
321 BOOL (*handler)(const struct timeval *now,
325 struct idle_event *result;
326 struct timeval now = timeval_current();
328 result = TALLOC_P(mem_ctx, struct idle_event);
329 if (result == NULL) {
330 DEBUG(0, ("talloc failed\n"));
334 result->interval = interval;
335 result->handler = handler;
336 result->private_data = private_data;
338 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
339 DEBUG(0, ("talloc failed\n"));
344 result->te = event_add_timed(event_ctx, result,
345 timeval_sum(&now, &interval),
347 idle_event_handler, result);
348 if (result->te == NULL) {
349 DEBUG(0, ("event_add_timed failed\n"));
357 /****************************************************************************
358 Do all async processing in here. This includes kernel oplock messages, change
360 ****************************************************************************/
362 static void async_processing(fd_set *pfds)
364 DEBUG(10,("async_processing: Doing async processing.\n"));
368 process_kernel_oplocks(smbd_messaging_context(), pfds);
370 /* Do the aio check again after receive_local_message as it does a
371 select and may have eaten our signal. */
372 /* Is this till true? -- vl */
376 exit_server_cleanly("termination signal");
379 /* check for sighup processing */
380 if (reload_after_sighup) {
381 change_to_root_user();
382 DEBUG(1,("Reloading services after SIGHUP\n"));
383 reload_services(False);
384 reload_after_sighup = 0;
388 /****************************************************************************
389 Add a fd to the set we will be select(2)ing on.
390 ****************************************************************************/
392 static int select_on_fd(int fd, int maxfd, fd_set *fds)
396 maxfd = MAX(maxfd, fd);
402 /****************************************************************************
403 Do a select on an two fd's - with timeout.
405 If a local udp message has been pushed onto the
406 queue (this can only happen during oplock break
407 processing) call async_processing()
409 If a pending smb message has been pushed onto the
410 queue (this can only happen during oplock break
411 processing) return this next.
413 If the first smbfd is ready then read an smb from it.
414 if the second (loopback UDP) fd is ready then read a message
415 from it and setup the buffer header to identify the length
417 Returns False on timeout or error.
420 The timeout is in milliseconds
421 ****************************************************************************/
423 static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
424 size_t *buffer_len, int timeout)
437 to.tv_sec = timeout / 1000;
438 to.tv_usec = (timeout % 1000) * 1000;
440 to.tv_sec = SMBD_SELECT_TIMEOUT;
445 * Note that this call must be before processing any SMB
446 * messages as we need to synchronously process any messages
447 * we may have sent to ourselves from the previous SMB.
449 message_dispatch(smbd_messaging_context());
452 * Check to see if we already have a message on the deferred open queue
453 * and it's time to schedule.
455 if(deferred_open_queue != NULL) {
456 BOOL pop_message = False;
457 struct pending_message_list *msg = deferred_open_queue;
459 if (timeval_is_zero(&msg->end_time)) {
466 tdif = usec_time_diff(&msg->end_time, &tv);
468 /* Timed out. Schedule...*/
470 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
472 /* Make a more accurate select timeout. */
473 to.tv_sec = tdif / 1000000;
474 to.tv_usec = tdif % 1000000;
475 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
476 (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
482 *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
484 if (*buffer == NULL) {
485 DEBUG(0, ("talloc failed\n"));
486 smb_read_error = READ_ERROR;
489 *buffer_len = msg->buf.length;
491 /* We leave this message on the queue so the open code can
492 know this is a retry. */
493 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
499 * Setup the select fd sets.
506 * Ensure we process oplock break messages by preference.
507 * We have to do this before the select, after the select
508 * and if the select returns EINTR. This is due to the fact
509 * that the selects called from async_processing can eat an EINTR
510 * caused by a signal (we can't take the break message there).
511 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
514 if (oplock_message_waiting(&r_fds)) {
515 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
516 async_processing(&r_fds);
518 * After async processing we must go and do the select again, as
519 * the state of the flag in fds for the server file descriptor is
520 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
526 * Are there any timed events waiting ? If so, ensure we don't
527 * select for longer than it would take to wait for them.
534 event_add_to_select_args(smbd_event_context(), &now,
535 &r_fds, &w_fds, &to, &maxfd);
538 if (timeval_is_zero(&to)) {
539 /* Process a timed event now... */
540 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
547 START_PROFILE(smbd_idle);
549 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
550 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
552 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
555 END_PROFILE(smbd_idle);
559 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
563 /* if we get EINTR then maybe we have received an oplock
564 signal - treat this as select returning 1. This is ugly, but
565 is the best we can do until the oplock code knows more about
567 if (selrtn == -1 && errno == EINTR) {
568 async_processing(&r_fds);
570 * After async processing we must go and do the select again, as
571 * the state of the flag in fds for the server file descriptor is
572 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
579 /* something is wrong. Maybe the socket is dead? */
580 smb_read_error = READ_ERROR;
584 /* Did we timeout ? */
586 smb_read_error = READ_TIMEOUT;
591 * Ensure we process oplock break messages by preference.
592 * This is IMPORTANT ! Otherwise we can starve other processes
593 * sending us an oplock break message. JRA.
596 if (oplock_message_waiting(&r_fds)) {
597 async_processing(&r_fds);
599 * After async processing we must go and do the select again, as
600 * the state of the flag in fds for the server file descriptor is
601 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
606 len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0);
612 *buffer_len = (size_t)len;
618 * Only allow 5 outstanding trans requests. We're allocating memory, so
622 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
625 for (; list != NULL; list = list->next) {
627 if (list->mid == mid) {
628 return NT_STATUS_INVALID_PARAMETER;
634 return NT_STATUS_INSUFFICIENT_RESOURCES;
640 /****************************************************************************
641 We're terminating and have closed all our files/connections etc.
642 If there are any pending local messages we need to respond to them
643 before termination so that other smbds don't think we just died whilst
645 ****************************************************************************/
647 void respond_to_all_remaining_local_messages(void)
650 * Assert we have no exclusive open oplocks.
653 if(get_number_of_exclusive_open_oplocks()) {
654 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
655 get_number_of_exclusive_open_oplocks() ));
659 process_kernel_oplocks(smbd_messaging_context(), NULL);
666 These flags determine some of the permissions required to do an operation
668 Note that I don't set NEED_WRITE on some write operations because they
669 are used by some brain-dead clients when printing, and I don't want to
670 force write permissions on print services.
672 #define AS_USER (1<<0)
673 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
674 #define TIME_INIT (1<<2)
675 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
676 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
677 #define DO_CHDIR (1<<6)
680 define a list of possible SMB messages and their corresponding
681 functions. Any message that has a NULL function is unimplemented -
682 please feel free to contribute implementations!
684 static const struct smb_message_struct {
686 int (*fn)(connection_struct *conn, char *, char *, int, int);
687 void (*fn_new)(connection_struct *conn, struct smb_request *req);
689 } smb_messages[256] = {
691 /* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE},
692 /* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE},
693 /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER },
694 /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER},
695 /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC },
696 /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER},
697 /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE },
698 /* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE },
699 /* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER},
700 /* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE},
701 /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER},
702 /* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC },
703 /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER},
704 /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER},
705 /* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER },
706 /* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER},
707 /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER},
708 /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR},
709 /* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER},
710 /* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER},
711 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER},
712 /* 0x15 */ { NULL, NULL, NULL, 0 },
713 /* 0x16 */ { NULL, NULL, NULL, 0 },
714 /* 0x17 */ { NULL, NULL, NULL, 0 },
715 /* 0x18 */ { NULL, NULL, NULL, 0 },
716 /* 0x19 */ { NULL, NULL, NULL, 0 },
717 /* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER},
718 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER},
719 /* 0x1c */ { "SMBreadBs",NULL, NULL,0 },
720 /* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER},
721 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER},
722 /* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER},
723 /* 0x20 */ { "SMBwritec",NULL, NULL,0},
724 /* 0x21 */ { NULL, NULL, NULL, 0 },
725 /* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE },
726 /* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER },
727 /* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER },
728 /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC },
729 /* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC},
730 /* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0},
731 /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER},
732 /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE },
733 /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE },
734 /* 0x2b */ { "SMBecho",NULL,reply_echo,0},
735 /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER},
736 /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC },
737 /* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC },
738 /* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC },
739 /* 0x30 */ { NULL, NULL, NULL, 0 },
740 /* 0x31 */ { NULL, NULL, NULL, 0 },
741 /* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC },
742 /* 0x33 */ { "SMBtranss2", NULL,reply_transs2, AS_USER},
743 /* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER},
744 /* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER},
745 /* 0x36 */ { NULL, NULL, NULL, 0 },
746 /* 0x37 */ { NULL, NULL, NULL, 0 },
747 /* 0x38 */ { NULL, NULL, NULL, 0 },
748 /* 0x39 */ { NULL, NULL, NULL, 0 },
749 /* 0x3a */ { NULL, NULL, NULL, 0 },
750 /* 0x3b */ { NULL, NULL, NULL, 0 },
751 /* 0x3c */ { NULL, NULL, NULL, 0 },
752 /* 0x3d */ { NULL, NULL, NULL, 0 },
753 /* 0x3e */ { NULL, NULL, NULL, 0 },
754 /* 0x3f */ { NULL, NULL, NULL, 0 },
755 /* 0x40 */ { NULL, NULL, NULL, 0 },
756 /* 0x41 */ { NULL, NULL, NULL, 0 },
757 /* 0x42 */ { NULL, NULL, NULL, 0 },
758 /* 0x43 */ { NULL, NULL, NULL, 0 },
759 /* 0x44 */ { NULL, NULL, NULL, 0 },
760 /* 0x45 */ { NULL, NULL, NULL, 0 },
761 /* 0x46 */ { NULL, NULL, NULL, 0 },
762 /* 0x47 */ { NULL, NULL, NULL, 0 },
763 /* 0x48 */ { NULL, NULL, NULL, 0 },
764 /* 0x49 */ { NULL, NULL, NULL, 0 },
765 /* 0x4a */ { NULL, NULL, NULL, 0 },
766 /* 0x4b */ { NULL, NULL, NULL, 0 },
767 /* 0x4c */ { NULL, NULL, NULL, 0 },
768 /* 0x4d */ { NULL, NULL, NULL, 0 },
769 /* 0x4e */ { NULL, NULL, NULL, 0 },
770 /* 0x4f */ { NULL, NULL, NULL, 0 },
771 /* 0x50 */ { NULL, NULL, NULL, 0 },
772 /* 0x51 */ { NULL, NULL, NULL, 0 },
773 /* 0x52 */ { NULL, NULL, NULL, 0 },
774 /* 0x53 */ { NULL, NULL, NULL, 0 },
775 /* 0x54 */ { NULL, NULL, NULL, 0 },
776 /* 0x55 */ { NULL, NULL, NULL, 0 },
777 /* 0x56 */ { NULL, NULL, NULL, 0 },
778 /* 0x57 */ { NULL, NULL, NULL, 0 },
779 /* 0x58 */ { NULL, NULL, NULL, 0 },
780 /* 0x59 */ { NULL, NULL, NULL, 0 },
781 /* 0x5a */ { NULL, NULL, NULL, 0 },
782 /* 0x5b */ { NULL, NULL, NULL, 0 },
783 /* 0x5c */ { NULL, NULL, NULL, 0 },
784 /* 0x5d */ { NULL, NULL, NULL, 0 },
785 /* 0x5e */ { NULL, NULL, NULL, 0 },
786 /* 0x5f */ { NULL, NULL, NULL, 0 },
787 /* 0x60 */ { NULL, NULL, NULL, 0 },
788 /* 0x61 */ { NULL, NULL, NULL, 0 },
789 /* 0x62 */ { NULL, NULL, NULL, 0 },
790 /* 0x63 */ { NULL, NULL, NULL, 0 },
791 /* 0x64 */ { NULL, NULL, NULL, 0 },
792 /* 0x65 */ { NULL, NULL, NULL, 0 },
793 /* 0x66 */ { NULL, NULL, NULL, 0 },
794 /* 0x67 */ { NULL, NULL, NULL, 0 },
795 /* 0x68 */ { NULL, NULL, NULL, 0 },
796 /* 0x69 */ { NULL, NULL, NULL, 0 },
797 /* 0x6a */ { NULL, NULL, NULL, 0 },
798 /* 0x6b */ { NULL, NULL, NULL, 0 },
799 /* 0x6c */ { NULL, NULL, NULL, 0 },
800 /* 0x6d */ { NULL, NULL, NULL, 0 },
801 /* 0x6e */ { NULL, NULL, NULL, 0 },
802 /* 0x6f */ { NULL, NULL, NULL, 0 },
803 /* 0x70 */ { "SMBtcon",reply_tcon,NULL,0},
804 /* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR},
805 /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0},
806 /* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0},
807 /* 0x74 */ { "SMBulogoffX", NULL,reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
808 /* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0},
809 /* 0x76 */ { NULL, NULL, NULL, 0 },
810 /* 0x77 */ { NULL, NULL, NULL, 0 },
811 /* 0x78 */ { NULL, NULL, NULL, 0 },
812 /* 0x79 */ { NULL, NULL, NULL, 0 },
813 /* 0x7a */ { NULL, NULL, NULL, 0 },
814 /* 0x7b */ { NULL, NULL, NULL, 0 },
815 /* 0x7c */ { NULL, NULL, NULL, 0 },
816 /* 0x7d */ { NULL, NULL, NULL, 0 },
817 /* 0x7e */ { NULL, NULL, NULL, 0 },
818 /* 0x7f */ { NULL, NULL, NULL, 0 },
819 /* 0x80 */ { "SMBdskattr",NULL,reply_dskattr,AS_USER},
820 /* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER},
821 /* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER},
822 /* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER},
823 /* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER},
824 /* 0x85 */ { NULL, NULL, NULL, 0 },
825 /* 0x86 */ { NULL, NULL, NULL, 0 },
826 /* 0x87 */ { NULL, NULL, NULL, 0 },
827 /* 0x88 */ { NULL, NULL, NULL, 0 },
828 /* 0x89 */ { NULL, NULL, NULL, 0 },
829 /* 0x8a */ { NULL, NULL, NULL, 0 },
830 /* 0x8b */ { NULL, NULL, NULL, 0 },
831 /* 0x8c */ { NULL, NULL, NULL, 0 },
832 /* 0x8d */ { NULL, NULL, NULL, 0 },
833 /* 0x8e */ { NULL, NULL, NULL, 0 },
834 /* 0x8f */ { NULL, NULL, NULL, 0 },
835 /* 0x90 */ { NULL, NULL, NULL, 0 },
836 /* 0x91 */ { NULL, NULL, NULL, 0 },
837 /* 0x92 */ { NULL, NULL, NULL, 0 },
838 /* 0x93 */ { NULL, NULL, NULL, 0 },
839 /* 0x94 */ { NULL, NULL, NULL, 0 },
840 /* 0x95 */ { NULL, NULL, NULL, 0 },
841 /* 0x96 */ { NULL, NULL, NULL, 0 },
842 /* 0x97 */ { NULL, NULL, NULL, 0 },
843 /* 0x98 */ { NULL, NULL, NULL, 0 },
844 /* 0x99 */ { NULL, NULL, NULL, 0 },
845 /* 0x9a */ { NULL, NULL, NULL, 0 },
846 /* 0x9b */ { NULL, NULL, NULL, 0 },
847 /* 0x9c */ { NULL, NULL, NULL, 0 },
848 /* 0x9d */ { NULL, NULL, NULL, 0 },
849 /* 0x9e */ { NULL, NULL, NULL, 0 },
850 /* 0x9f */ { NULL, NULL, NULL, 0 },
851 /* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC },
852 /* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC },
853 /* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC },
854 /* 0xa3 */ { NULL, NULL, NULL, 0 },
855 /* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 },
856 /* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE },
857 /* 0xa6 */ { NULL, NULL, NULL, 0 },
858 /* 0xa7 */ { NULL, NULL, NULL, 0 },
859 /* 0xa8 */ { NULL, NULL, NULL, 0 },
860 /* 0xa9 */ { NULL, NULL, NULL, 0 },
861 /* 0xaa */ { NULL, NULL, NULL, 0 },
862 /* 0xab */ { NULL, NULL, NULL, 0 },
863 /* 0xac */ { NULL, NULL, NULL, 0 },
864 /* 0xad */ { NULL, NULL, NULL, 0 },
865 /* 0xae */ { NULL, NULL, NULL, 0 },
866 /* 0xaf */ { NULL, NULL, NULL, 0 },
867 /* 0xb0 */ { NULL, NULL, NULL, 0 },
868 /* 0xb1 */ { NULL, NULL, NULL, 0 },
869 /* 0xb2 */ { NULL, NULL, NULL, 0 },
870 /* 0xb3 */ { NULL, NULL, NULL, 0 },
871 /* 0xb4 */ { NULL, NULL, NULL, 0 },
872 /* 0xb5 */ { NULL, NULL, NULL, 0 },
873 /* 0xb6 */ { NULL, NULL, NULL, 0 },
874 /* 0xb7 */ { NULL, NULL, NULL, 0 },
875 /* 0xb8 */ { NULL, NULL, NULL, 0 },
876 /* 0xb9 */ { NULL, NULL, NULL, 0 },
877 /* 0xba */ { NULL, NULL, NULL, 0 },
878 /* 0xbb */ { NULL, NULL, NULL, 0 },
879 /* 0xbc */ { NULL, NULL, NULL, 0 },
880 /* 0xbd */ { NULL, NULL, NULL, 0 },
881 /* 0xbe */ { NULL, NULL, NULL, 0 },
882 /* 0xbf */ { NULL, NULL, NULL, 0 },
883 /* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER},
884 /* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER},
885 /* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER},
886 /* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER},
887 /* 0xc4 */ { NULL, NULL, NULL, 0 },
888 /* 0xc5 */ { NULL, NULL, NULL, 0 },
889 /* 0xc6 */ { NULL, NULL, NULL, 0 },
890 /* 0xc7 */ { NULL, NULL, NULL, 0 },
891 /* 0xc8 */ { NULL, NULL, NULL, 0 },
892 /* 0xc9 */ { NULL, NULL, NULL, 0 },
893 /* 0xca */ { NULL, NULL, NULL, 0 },
894 /* 0xcb */ { NULL, NULL, NULL, 0 },
895 /* 0xcc */ { NULL, NULL, NULL, 0 },
896 /* 0xcd */ { NULL, NULL, NULL, 0 },
897 /* 0xce */ { NULL, NULL, NULL, 0 },
898 /* 0xcf */ { NULL, NULL, NULL, 0 },
899 /* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST},
900 /* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST},
901 /* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST},
902 /* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST},
903 /* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST},
904 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST},
905 /* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST},
906 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST},
907 /* 0xd8 */ { NULL, NULL, NULL, 0 },
908 /* 0xd9 */ { NULL, NULL, NULL, 0 },
909 /* 0xda */ { NULL, NULL, NULL, 0 },
910 /* 0xdb */ { NULL, NULL, NULL, 0 },
911 /* 0xdc */ { NULL, NULL, NULL, 0 },
912 /* 0xdd */ { NULL, NULL, NULL, 0 },
913 /* 0xde */ { NULL, NULL, NULL, 0 },
914 /* 0xdf */ { NULL, NULL, NULL, 0 },
915 /* 0xe0 */ { NULL, NULL, NULL, 0 },
916 /* 0xe1 */ { NULL, NULL, NULL, 0 },
917 /* 0xe2 */ { NULL, NULL, NULL, 0 },
918 /* 0xe3 */ { NULL, NULL, NULL, 0 },
919 /* 0xe4 */ { NULL, NULL, NULL, 0 },
920 /* 0xe5 */ { NULL, NULL, NULL, 0 },
921 /* 0xe6 */ { NULL, NULL, NULL, 0 },
922 /* 0xe7 */ { NULL, NULL, NULL, 0 },
923 /* 0xe8 */ { NULL, NULL, NULL, 0 },
924 /* 0xe9 */ { NULL, NULL, NULL, 0 },
925 /* 0xea */ { NULL, NULL, NULL, 0 },
926 /* 0xeb */ { NULL, NULL, NULL, 0 },
927 /* 0xec */ { NULL, NULL, NULL, 0 },
928 /* 0xed */ { NULL, NULL, NULL, 0 },
929 /* 0xee */ { NULL, NULL, NULL, 0 },
930 /* 0xef */ { NULL, NULL, NULL, 0 },
931 /* 0xf0 */ { NULL, NULL, NULL, 0 },
932 /* 0xf1 */ { NULL, NULL, NULL, 0 },
933 /* 0xf2 */ { NULL, NULL, NULL, 0 },
934 /* 0xf3 */ { NULL, NULL, NULL, 0 },
935 /* 0xf4 */ { NULL, NULL, NULL, 0 },
936 /* 0xf5 */ { NULL, NULL, NULL, 0 },
937 /* 0xf6 */ { NULL, NULL, NULL, 0 },
938 /* 0xf7 */ { NULL, NULL, NULL, 0 },
939 /* 0xf8 */ { NULL, NULL, NULL, 0 },
940 /* 0xf9 */ { NULL, NULL, NULL, 0 },
941 /* 0xfa */ { NULL, NULL, NULL, 0 },
942 /* 0xfb */ { NULL, NULL, NULL, 0 },
943 /* 0xfc */ { NULL, NULL, NULL, 0 },
944 /* 0xfd */ { NULL, NULL, NULL, 0 },
945 /* 0xfe */ { NULL, NULL, NULL, 0 },
946 /* 0xff */ { NULL, NULL, NULL, 0 }
950 /*******************************************************************
951 allocate and initialize a reply packet
952 ********************************************************************/
954 void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes)
956 if (!(req->outbuf = TALLOC_ARRAY(
958 smb_size + num_words*2 + num_bytes))) {
959 smb_panic("could not allocate output buffer\n");
962 construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
963 set_message((char *)req->inbuf, (char *)req->outbuf,
964 num_words, num_bytes, False);
966 * Zero out the word area, the caller has to take care of the bcc area
969 if (num_words != 0) {
970 memset(req->outbuf + smb_vwv0, 0, num_words*2);
977 /*******************************************************************
978 Dump a packet to a file.
979 ********************************************************************/
981 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
985 if (DEBUGLEVEL < 50) return;
987 if (len < 4) len = smb_len(data)+4;
988 for (i=1;i<100;i++) {
989 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
990 type ? "req" : "resp");
991 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
992 if (fd != -1 || errno != EEXIST) break;
995 ssize_t ret = write(fd, data, len);
997 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
999 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1003 /****************************************************************************
1004 Prepare everything for calling the actual request function, and potentially
1005 call the request function via the "new" interface.
1007 Return False if the "legacy" function needs to be called, everything is
1010 Return True if we're done.
1012 I know this API sucks, but it is the one with the least code change I could
1014 ****************************************************************************/
1016 static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
1017 connection_struct **pconn)
1021 connection_struct *conn;
1023 static uint16 last_session_tag = UID_FIELD_INVALID;
1027 last_message = type;
1029 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1030 * so subtract 4 from it. */
1031 if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0)
1032 || (size < (smb_size - 4))) {
1033 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1034 smb_len(req->inbuf)));
1035 exit_server_cleanly("Non-SMB packet");
1039 if ((smb_messages[type].fn == NULL)
1040 && (smb_messages[type].fn_new == NULL)) {
1041 DEBUG(0,("Unknown message type %d!\n",type));
1042 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1043 reply_unknown_new(req, type);
1047 flags = smb_messages[type].flags;
1049 /* In share mode security we must ignore the vuid. */
1050 session_tag = (lp_security() == SEC_SHARE)
1051 ? UID_FIELD_INVALID : req->vuid;
1052 conn = conn_find(req->tid);
1054 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1055 (int)sys_getpid(), (unsigned long)conn));
1057 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1059 /* Ensure this value is replaced in the incoming packet. */
1060 SSVAL(req->inbuf,smb_uid,session_tag);
1063 * Ensure the correct username is in current_user_info. This is a
1064 * really ugly bugfix for problems with multiple session_setup_and_X's
1065 * being done and allowing %U and %G substitutions to work correctly.
1066 * There is a reason this code is done here, don't move it unless you
1067 * know what you're doing... :-).
1071 if (session_tag != last_session_tag) {
1072 user_struct *vuser = NULL;
1074 last_session_tag = session_tag;
1075 if(session_tag != UID_FIELD_INVALID) {
1076 vuser = get_valid_user_struct(session_tag);
1078 set_current_user_info(&vuser->user);
1083 /* Does this call need to be run as the connected user? */
1084 if (flags & AS_USER) {
1086 /* Does this call need a valid tree connection? */
1089 * Amazingly, the error code depends on the command
1092 if (type == SMBntcreateX) {
1093 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1095 reply_doserror(req, ERRSRV, ERRinvnid);
1100 if (!change_to_user(conn,session_tag)) {
1101 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1105 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1107 /* Does it need write permission? */
1108 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1109 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1113 /* IPC services are limited */
1114 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1115 reply_doserror(req, ERRSRV,ERRaccess);
1119 /* This call needs to be run as root */
1120 change_to_root_user();
1123 /* load service specific parameters */
1125 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1126 (flags & (AS_USER|DO_CHDIR)
1128 reply_doserror(req, ERRSRV, ERRaccess);
1131 conn->num_smb_operations++;
1134 /* does this protocol need to be run as guest? */
1135 if ((flags & AS_GUEST)
1136 && (!change_to_guest() ||
1137 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1138 lp_hostsdeny(-1)))) {
1139 reply_doserror(req, ERRSRV, ERRaccess);
1143 current_inbuf = (char *)req->inbuf; /* In case we need to defer this
1144 * message in open... */
1146 if (smb_messages[type].fn_new != NULL) {
1147 smb_messages[type].fn_new(conn, req);
1152 * Indicate the upper layer that there's still work.
1162 /****************************************************************************
1163 Do a switch on the message type, and return the response size
1164 ****************************************************************************/
1166 static int switch_message(uint8 type, struct smb_request *req, char **outbuf,
1167 int size, int bufsize)
1170 connection_struct *conn = NULL;
1172 if (switch_message_new(type, req, size, &conn)) {
1173 if (req->outbuf != NULL) {
1174 *outbuf = (char *)req->outbuf;
1175 return smb_len(req->outbuf)+4;
1180 if (InBuffer == NULL) {
1181 DEBUG(1, ("have to alloc InBuffer for %s\n",
1182 smb_fn_name(type)));
1183 if (NewInBuffer(NULL) == NULL) {
1184 smb_panic("Could not allocate InBuffer");
1188 if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) {
1189 smb_panic("Could not allocate OutBuffer");
1192 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer,
1195 memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size));
1197 construct_reply_common(InBuffer, OutBuffer);
1199 outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size,
1202 smb_dump(smb_fn_name(type), 0, OutBuffer, outsize);
1204 *outbuf = OutBuffer;
1209 /****************************************************************************
1210 Construct a reply to the incoming packet.
1211 ****************************************************************************/
1213 static void construct_reply(char *inbuf, int size)
1215 uint8 type = CVAL(inbuf,smb_com);
1217 struct smb_request *req;
1224 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
1225 smb_panic("could not allocate smb_request");
1227 init_smb_request(req, (uint8 *)inbuf);
1229 outsize = switch_message(type, req, &outbuf, size, max_send);
1232 smb_setlen(inbuf,outbuf,outsize - 4);
1236 if (CVAL(outbuf,0) == 0)
1239 if (outsize != smb_len(outbuf) + 4) {
1240 DEBUG(0,("ERROR: Invalid message response size! "
1241 "%d %d\n", outsize, smb_len(outbuf)));
1242 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1243 exit_server_cleanly("construct_reply: send_smb "
1253 /****************************************************************************
1254 Process an smb from the client
1255 ****************************************************************************/
1257 static void process_smb(char *inbuf, size_t nread)
1259 static int trans_num;
1260 int msg_type = CVAL(inbuf,0);
1262 DO_PROFILE_INC(smb_count);
1264 if (trans_num == 0) {
1265 /* on the first packet, check the global hosts allow/ hosts
1266 deny parameters before doing any parsing of the packet
1267 passed to us by the client. This prevents attacks on our
1268 parsing code from hosts not in the hosts allow list */
1269 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1270 lp_hostsdeny(-1))) {
1271 /* send a negative session response "not listening on calling name" */
1272 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1273 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1274 (void)send_smb(smbd_server_fd(),(char *)buf);
1275 exit_server_cleanly("connection denied");
1279 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1281 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) );
1283 if (msg_type != 0) {
1285 * NetBIOS session request, keepalive, etc.
1287 reply_special(inbuf);
1293 construct_reply(inbuf,nread);
1298 /****************************************************************************
1299 Return a string containing the function name of a SMB command.
1300 ****************************************************************************/
1302 const char *smb_fn_name(int type)
1304 const char *unknown_name = "SMBunknown";
1306 if (smb_messages[type].name == NULL)
1307 return(unknown_name);
1309 return(smb_messages[type].name);
1312 /****************************************************************************
1313 Helper functions for contruct_reply.
1314 ****************************************************************************/
1316 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1318 void add_to_common_flags2(uint32 v)
1323 void remove_from_common_flags2(uint32 v)
1325 common_flags2 &= ~v;
1328 void construct_reply_common(const char *inbuf, char *outbuf)
1330 set_message(inbuf,outbuf,0,0,False);
1332 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1333 SIVAL(outbuf,smb_rcls,0);
1334 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1335 SSVAL(outbuf,smb_flg2,
1336 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1338 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1340 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1341 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1342 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1343 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1346 /****************************************************************************
1347 Construct a chained reply and add it to the already made reply
1348 ****************************************************************************/
1350 int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
1352 static char *orig_inbuf;
1353 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1354 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1358 char inbuf_saved[smb_wct];
1359 char *outbuf = *poutbuf;
1360 size_t outsize = smb_len(outbuf) + 4;
1361 size_t outsize_padded;
1362 size_t ofs, to_move;
1364 struct smb_request *req;
1365 size_t caller_outputlen;
1366 char *caller_output;
1368 /* Maybe its not chained, or it's an error packet. */
1369 if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1370 SCVAL(outbuf,smb_vwv0,0xFF);
1374 if (chain_size == 0) {
1375 /* this is the first part of the chain */
1380 * We need to save the output the caller added to the chain so that we
1381 * can splice it into the final output buffer later.
1384 caller_outputlen = outsize - smb_wct;
1386 caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
1388 if (caller_output == NULL) {
1389 /* TODO: NT_STATUS_NO_MEMORY */
1390 smb_panic("could not dup outbuf");
1394 * The original Win95 redirector dies on a reply to
1395 * a lockingX and read chain unless the chain reply is
1396 * 4 byte aligned. JRA.
1399 outsize_padded = (outsize + 3) & ~3;
1402 * remember how much the caller added to the chain, only counting
1403 * stuff after the parameter words
1405 chain_size += outsize_padded - smb_wct;
1408 * work out pointers into the original packets. The
1409 * headers on these need to be filled in
1411 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1413 /* remember the original command type */
1414 smb_com1 = CVAL(orig_inbuf,smb_com);
1416 /* save the data which will be overwritten by the new headers */
1417 memcpy(inbuf_saved,inbuf2,smb_wct);
1419 /* give the new packet the same header as the last part of the SMB */
1420 memmove(inbuf2,inbuf,smb_wct);
1422 /* create the in buffer */
1423 SCVAL(inbuf2,smb_com,smb_com2);
1425 /* work out the new size for the in buffer. */
1426 new_size = size - (inbuf2 - inbuf);
1428 DEBUG(0,("chain_reply: chain packet size incorrect "
1429 "(orig size = %d, offset = %d)\n",
1430 size, (int)(inbuf2 - inbuf) ));
1431 exit_server_cleanly("Bad chained packet");
1435 /* And set it in the header. */
1436 smb_setlen(inbuf, inbuf2, new_size);
1438 DEBUG(3,("Chained message\n"));
1441 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
1442 smb_panic("could not allocate smb_request");
1444 init_smb_request(req, (uint8 *)inbuf2);
1446 /* process the request */
1447 outsize2 = switch_message(smb_com2, req, &outbuf, new_size,
1448 bufsize-chain_size);
1451 * We don't accept deferred operations in chained requests.
1453 SMB_ASSERT(outsize2 >= smb_wct);
1456 * Move away the new command output so that caller_output fits in,
1457 * copy in the caller_output saved above.
1460 SMB_ASSERT(outsize_padded >= smb_wct);
1463 * "ofs" is the space we need for caller_output. Equal to
1464 * caller_outputlen plus the padding.
1467 ofs = outsize_padded - smb_wct;
1470 * "to_move" is the amount of bytes the secondary routine gave us
1473 to_move = outsize2 - smb_wct;
1475 if (to_move + ofs + smb_wct + chain_size > max_send) {
1476 smb_panic("replies too large -- would have to cut");
1480 * In the "new" API "outbuf" is allocated via reply_outbuf, just for
1481 * the first request in the chain. So we have to re-allocate it. In
1482 * the "old" API the only outbuf ever used is the global OutBuffer
1483 * which is always large enough.
1486 if (outbuf != OutBuffer) {
1487 outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
1488 to_move + ofs + smb_wct);
1489 if (outbuf == NULL) {
1490 smb_panic("could not realloc outbuf");
1496 memmove(outbuf + smb_wct + ofs, outbuf + smb_wct, to_move);
1497 memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
1500 * The secondary function has overwritten smb_com
1503 SCVAL(outbuf, smb_com, smb_com1);
1506 * We've just copied in the whole "wct" area from the secondary
1507 * function. Fix up the chaining: com2 and the offset need to be
1511 SCVAL(outbuf, smb_vwv0, smb_com2);
1512 SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
1514 if (outsize_padded > outsize) {
1517 * Due to padding we have some uninitialized bytes after the
1521 memset(outbuf + outsize, 0, outsize_padded - outsize);
1524 smb_setlen(NULL, outbuf, outsize2 + chain_size - 4);
1527 * restore the saved data, being careful not to overwrite any data
1528 * from the reply header
1530 memcpy(inbuf2,inbuf_saved,smb_wct);
1532 SAFE_FREE(caller_output);
1535 return outsize2 + chain_size;
1538 void chain_reply_new(struct smb_request *req)
1540 chain_reply(CONST_DISCARD(char *, req->inbuf),
1541 (char **)(void *)&req->outbuf,
1542 smb_len(req->inbuf)+4,
1543 smb_len(req->outbuf)+4);
1546 /****************************************************************************
1547 Setup the needed select timeout in milliseconds.
1548 ****************************************************************************/
1550 static int setup_select_timeout(void)
1554 select_timeout = SMBD_SELECT_TIMEOUT*1000;
1556 if (print_notify_messages_pending()) {
1557 select_timeout = MIN(select_timeout, 1000);
1560 return select_timeout;
1563 /****************************************************************************
1564 Check if services need reloading.
1565 ****************************************************************************/
1567 void check_reload(time_t t)
1569 static pid_t mypid = 0;
1570 static time_t last_smb_conf_reload_time = 0;
1571 static time_t last_printer_reload_time = 0;
1572 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1574 if(last_smb_conf_reload_time == 0) {
1575 last_smb_conf_reload_time = t;
1576 /* Our printing subsystem might not be ready at smbd start up.
1577 Then no printer is available till the first printers check
1578 is performed. A lower initial interval circumvents this. */
1579 if ( printcap_cache_time > 60 )
1580 last_printer_reload_time = t - printcap_cache_time + 60;
1582 last_printer_reload_time = t;
1585 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1586 /* randomize over 60 second the printcap reload to avoid all
1587 * process hitting cupsd at the same time */
1588 int time_range = 60;
1590 last_printer_reload_time += random() % time_range;
1594 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1595 reload_services(True);
1596 reload_after_sighup = False;
1597 last_smb_conf_reload_time = t;
1600 /* 'printcap cache time = 0' disable the feature */
1602 if ( printcap_cache_time != 0 )
1604 /* see if it's time to reload or if the clock has been set back */
1606 if ( (t >= last_printer_reload_time+printcap_cache_time)
1607 || (t-last_printer_reload_time < 0) )
1609 DEBUG( 3,( "Printcap cache time expired.\n"));
1611 last_printer_reload_time = t;
1616 /****************************************************************************
1617 Process any timeout housekeeping. Return False if the caller should exit.
1618 ****************************************************************************/
1620 static BOOL timeout_processing(int *select_timeout,
1621 time_t *last_timeout_processing_time)
1625 if (smb_read_error == READ_EOF) {
1626 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1630 if (smb_read_error == READ_ERROR) {
1631 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1636 if (smb_read_error == READ_BAD_SIG) {
1637 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1641 *last_timeout_processing_time = t = time(NULL);
1643 /* become root again if waiting */
1644 change_to_root_user();
1646 /* check if we need to reload services */
1649 if(global_machine_password_needs_changing &&
1650 /* for ADS we need to do a regular ADS password change, not a domain
1652 lp_security() == SEC_DOMAIN) {
1654 unsigned char trust_passwd_hash[16];
1658 * We're in domain level security, and the code that
1659 * read the machine password flagged that the machine
1660 * password needs changing.
1664 * First, open the machine password file with an exclusive lock.
1667 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1668 DEBUG(0,("process: unable to lock the machine account password for \
1669 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1673 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1674 DEBUG(0,("process: unable to read the machine account password for \
1675 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1676 secrets_lock_trust_account_password(lp_workgroup(), False);
1681 * Make sure someone else hasn't already done this.
1684 if(t < lct + lp_machine_password_timeout()) {
1685 global_machine_password_needs_changing = False;
1686 secrets_lock_trust_account_password(lp_workgroup(), False);
1690 /* always just contact the PDC here */
1692 change_trust_account_password( lp_workgroup(), NULL);
1693 global_machine_password_needs_changing = False;
1694 secrets_lock_trust_account_password(lp_workgroup(), False);
1697 /* update printer queue caches if necessary */
1699 update_monitored_printq_cache();
1702 * Now we are root, check if the log files need pruning.
1703 * Force a log file check.
1705 force_check_log_size();
1708 /* Send any queued printer notify message to interested smbd's. */
1710 print_notify_send_messages(smbd_messaging_context(), 0);
1713 * Modify the select timeout depending upon
1714 * what we have remaining in our queues.
1717 *select_timeout = setup_select_timeout();
1722 /****************************************************************************
1723 Accessor functions for InBuffer, OutBuffer.
1724 ****************************************************************************/
1726 char *get_InBuffer(void)
1731 char *get_OutBuffer(void)
1736 /****************************************************************************
1737 Allocate a new InBuffer. Returns the new and old ones.
1738 ****************************************************************************/
1740 static char *NewInBuffer(char **old_inbuf)
1742 char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1747 *old_inbuf = InBuffer;
1749 InBuffer = new_inbuf;
1750 #if defined(DEVELOPER)
1751 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1756 /****************************************************************************
1757 Allocate a new OutBuffer. Returns the new and old ones.
1758 ****************************************************************************/
1760 static char *NewOutBuffer(char **old_outbuf)
1762 char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1767 *old_outbuf = OutBuffer;
1769 OutBuffer = new_outbuf;
1770 #if defined(DEVELOPER)
1771 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1776 /****************************************************************************
1777 Process commands from the client
1778 ****************************************************************************/
1780 void smbd_process(void)
1782 time_t last_timeout_processing_time = time(NULL);
1783 unsigned int num_smbs = 0;
1785 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1788 int select_timeout = setup_select_timeout();
1795 /* free up temporary memory */
1797 main_loop_TALLOC_FREE();
1799 /* Did someone ask for immediate checks on things like blocking locks ? */
1800 if (select_timeout == 0) {
1801 if(!timeout_processing(&select_timeout,
1802 &last_timeout_processing_time))
1804 num_smbs = 0; /* Reset smb counter. */
1807 run_events(smbd_event_context(), 0, NULL, NULL);
1809 while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
1811 if(!timeout_processing(&select_timeout,
1812 &last_timeout_processing_time))
1814 num_smbs = 0; /* Reset smb counter. */
1819 * Ensure we do timeout processing if the SMB we just got was
1820 * only an echo request. This allows us to set the select
1821 * timeout in 'receive_message_or_smb()' to any value we like
1822 * without worrying that the client will send echo requests
1823 * faster than the select timeout, thus starving out the
1824 * essential processing (change notify, blocking locks) that
1825 * the timeout code does. JRA.
1827 num_echos = smb_echo_count;
1829 process_smb(inbuf, inbuf_len);
1833 if (smb_echo_count != num_echos) {
1834 if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
1836 num_smbs = 0; /* Reset smb counter. */
1842 * If we are getting smb requests in a constant stream
1843 * with no echos, make sure we attempt timeout processing
1844 * every select_timeout milliseconds - but only check for this
1845 * every 200 smb requests.
1848 if ((num_smbs % 200) == 0) {
1849 time_t new_check_time = time(NULL);
1850 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1851 if(!timeout_processing(
1853 &last_timeout_processing_time))
1855 num_smbs = 0; /* Reset smb counter. */
1856 last_timeout_processing_time = new_check_time; /* Reset time. */
1860 /* The timeout_processing function isn't run nearly
1861 often enough to implement 'max log size' without
1862 overrunning the size of the file by many megabytes.
1863 This is especially true if we are running at debug
1864 level 10. Checking every 50 SMBs is a nice
1865 tradeoff of performance vs log file size overrun. */
1867 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1868 change_to_root_user();