r4231: commiting changes to 3.0.10
[Samba.git] / source / smbd / process.c
blob8adc5c2e665ecb1dc0e1b6539d8c57ed8ed68c9f
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 struct timeval smb_last_time;
25 static char *InBuffer = NULL;
26 char *OutBuffer = NULL;
27 char *last_inbuf = NULL;
29 /*
30 * Size of data we can send to client. Set
31 * by the client for all protocols above CORE.
32 * Set by us for CORE protocol.
34 int max_send = BUFFER_SIZE;
36 * Size of the data we can receive. Set by us.
37 * Can be modified by the max xmit parameter.
39 int max_recv = BUFFER_SIZE;
41 extern int last_message;
42 extern int global_oplock_break;
43 extern userdom_struct current_user_info;
44 extern int smb_read_error;
45 SIG_ATOMIC_T reload_after_sighup = 0;
46 SIG_ATOMIC_T got_sig_term = 0;
47 BOOL global_machine_password_needs_changing = False;
48 extern int max_send;
50 /****************************************************************************
51 Function to return the current request mid from Inbuffer.
52 ****************************************************************************/
54 uint16 get_current_mid(void)
56 return SVAL(InBuffer,smb_mid);
59 /****************************************************************************
60 structure to hold a linked list of queued messages.
61 for processing.
62 ****************************************************************************/
64 static struct pending_message_list *smb_oplock_queue;
65 static struct pending_message_list *smb_sharing_violation_queue;
67 enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE };
69 /****************************************************************************
70 Free up a message.
71 ****************************************************************************/
73 static void free_queued_message(struct pending_message_list *msg)
75 data_blob_free(&msg->buf);
76 data_blob_free(&msg->private_data);
77 SAFE_FREE(msg);
80 /****************************************************************************
81 Function to push a message onto the tail of a linked list of smb messages ready
82 for processing.
83 ****************************************************************************/
85 static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len)
87 struct pending_message_list *tmp_msg;
88 struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list);
90 if(msg == NULL) {
91 DEBUG(0,("push_message: malloc fail (1)\n"));
92 return False;
95 memset(msg,'\0',sizeof(*msg));
97 msg->buf = data_blob(buf, msg_len);
98 if(msg->buf.data == NULL) {
99 DEBUG(0,("push_message: malloc fail (2)\n"));
100 SAFE_FREE(msg);
101 return False;
104 if (ptv) {
105 msg->msg_time = *ptv;
108 if (private) {
109 msg->private_data = data_blob(private, private_len);
110 if (msg->private_data.data == NULL) {
111 DEBUG(0,("push_message: malloc fail (3)\n"));
112 data_blob_free(&msg->buf);
113 SAFE_FREE(msg);
117 if (qt == OPLOCK_QUEUE) {
118 DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
119 } else {
120 DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
123 DEBUG(10,("push_message: pushed message length %u on queue %s\n",
124 (unsigned int)msg_len,
125 qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" ));
127 return True;
130 /****************************************************************************
131 Function to push an oplock smb message onto a linked list of local smb messages ready
132 for processing.
133 ****************************************************************************/
135 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
137 BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
138 if (ret) {
139 /* Push the MID of this packet on the signing queue. */
140 srv_defer_sign_response(SVAL(buf,smb_mid));
142 return ret;
145 /****************************************************************************
146 Function to delete a sharing violation open message by mid.
147 ****************************************************************************/
149 void remove_sharing_violation_open_smb_message(uint16 mid)
151 struct pending_message_list *pml;
153 if (!lp_defer_sharing_violations()) {
154 return;
157 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
158 if (mid == SVAL(pml->buf.data,smb_mid)) {
159 DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
160 (unsigned int)mid, (unsigned int)pml->buf.length ));
161 DLIST_REMOVE(smb_sharing_violation_queue, pml);
162 free_queued_message(pml);
163 return;
168 /****************************************************************************
169 Move a sharing violation open retry message to the front of the list and
170 schedule it for immediate processing.
171 ****************************************************************************/
173 void schedule_sharing_violation_open_smb_message(uint16 mid)
175 struct pending_message_list *pml;
176 int i = 0;
178 if (!lp_defer_sharing_violations()) {
179 return;
182 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
183 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
184 DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
185 (unsigned int)msg_mid ));
186 if (mid == msg_mid) {
187 DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
188 mid ));
189 pml->msg_time.tv_sec = 0;
190 pml->msg_time.tv_usec = 0;
191 DLIST_PROMOTE(smb_sharing_violation_queue, pml);
192 return;
196 DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
197 mid ));
200 /****************************************************************************
201 Return true if this mid is on the deferred queue.
202 ****************************************************************************/
204 BOOL open_was_deferred(uint16 mid)
206 struct pending_message_list *pml;
208 if (!lp_defer_sharing_violations()) {
209 return False;
212 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
213 if (SVAL(pml->buf.data,smb_mid) == mid) {
214 return True;
217 return False;
220 /****************************************************************************
221 Return the message queued by this mid.
222 ****************************************************************************/
224 struct pending_message_list *get_open_deferred_message(uint16 mid)
226 struct pending_message_list *pml;
228 if (!lp_defer_sharing_violations()) {
229 return NULL;
232 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
233 if (SVAL(pml->buf.data,smb_mid) == mid) {
234 return pml;
237 return NULL;
240 /****************************************************************************
241 Function to push a sharing violation open smb message onto a linked list of local smb messages ready
242 for processing.
243 ****************************************************************************/
245 BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len)
247 uint16 mid = SVAL(InBuffer,smb_mid);
248 struct timeval tv;
249 SMB_BIG_INT tdif;
251 if (!lp_defer_sharing_violations()) {
252 return True;
255 tv = *ptv;
256 tdif = tv.tv_sec;
257 tdif *= 1000000;
258 tdif += tv.tv_usec;
260 /* Add on the timeout. */
261 tdif += SHARING_VIOLATION_USEC_WAIT;
263 tv.tv_sec = tdif / 1000000;
264 tv.tv_usec = tdif % 1000000;
266 DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\
267 timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid,
268 (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec));
270 return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer,
271 smb_len(InBuffer)+4, &tv, private, priv_len);
274 /****************************************************************************
275 Do all async processing in here. This includes UDB oplock messages, kernel
276 oplock messages, change notify events etc.
277 ****************************************************************************/
279 static void async_processing(char *buffer, int buffer_len)
281 DEBUG(10,("async_processing: Doing async processing.\n"));
283 /* check for oplock messages (both UDP and kernel) */
284 if (receive_local_message(buffer, buffer_len, 1)) {
285 process_local_message(buffer, buffer_len);
288 if (got_sig_term) {
289 exit_server("Caught TERM signal");
292 /* check for async change notify events */
293 process_pending_change_notify_queue(0);
295 /* check for sighup processing */
296 if (reload_after_sighup) {
297 change_to_root_user();
298 DEBUG(1,("Reloading services after SIGHUP\n"));
299 reload_services(False);
300 reload_after_sighup = 0;
304 /****************************************************************************
305 Do a select on an two fd's - with timeout.
307 If a local udp message has been pushed onto the
308 queue (this can only happen during oplock break
309 processing) call async_processing()
311 If a pending smb message has been pushed onto the
312 queue (this can only happen during oplock break
313 processing) return this next.
315 If the first smbfd is ready then read an smb from it.
316 if the second (loopback UDP) fd is ready then read a message
317 from it and setup the buffer header to identify the length
318 and from address.
319 Returns False on timeout or error.
320 Else returns True.
322 The timeout is in milliseconds
323 ****************************************************************************/
325 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
327 fd_set fds;
328 int selrtn;
329 struct timeval to;
330 struct timeval *pto;
331 int maxfd;
333 smb_read_error = 0;
335 again:
337 to.tv_sec = timeout / 1000;
338 to.tv_usec = (timeout % 1000) * 1000;
339 pto = timeout > 0 ? &to : NULL;
342 * Note that this call must be before processing any SMB
343 * messages as we need to synchronously process any messages
344 * we may have sent to ourselves from the previous SMB.
346 message_dispatch();
349 * Check to see if we already have a message on the smb queue.
350 * If so - copy and return it.
352 if(smb_oplock_queue != NULL) {
353 struct pending_message_list *msg = smb_oplock_queue;
354 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
356 /* Free the message we just copied. */
357 DLIST_REMOVE(smb_oplock_queue, msg);
358 free_queued_message(msg);
360 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
361 return True;
365 * Check to see if we already have a message on the deferred open queue
366 * and it's time to schedule.
368 if(smb_sharing_violation_queue != NULL) {
369 BOOL pop_message = False;
370 struct pending_message_list *msg = smb_sharing_violation_queue;
372 if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
373 pop_message = True;
374 } else {
375 struct timeval tv;
376 SMB_BIG_INT tdif;
378 GetTimeOfDay(&tv);
379 tdif = usec_time_diff(&msg->msg_time, &tv);
380 if (tdif <= 0) {
381 /* Timed out. Schedule...*/
382 pop_message = True;
383 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
384 } else {
385 /* Make a more accurate select timeout. */
386 to.tv_sec = tdif / 1000000;
387 to.tv_usec = tdif % 1000000;
388 pto = &to;
389 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
390 (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
394 if (pop_message) {
395 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
397 /* We leave this message on the queue so the open code can
398 know this is a retry. */
399 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
400 return True;
405 * Setup the select read fd set.
408 FD_ZERO(&fds);
411 * Ensure we process oplock break messages by preference.
412 * We have to do this before the select, after the select
413 * and if the select returns EINTR. This is due to the fact
414 * that the selects called from async_processing can eat an EINTR
415 * caused by a signal (we can't take the break message there).
416 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
419 if (oplock_message_waiting(&fds)) {
420 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
421 async_processing(buffer, buffer_len);
423 * After async processing we must go and do the select again, as
424 * the state of the flag in fds for the server file descriptor is
425 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
427 goto again;
430 FD_SET(smbd_server_fd(),&fds);
431 maxfd = setup_oplock_select_set(&fds);
433 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
435 /* if we get EINTR then maybe we have received an oplock
436 signal - treat this as select returning 1. This is ugly, but
437 is the best we can do until the oplock code knows more about
438 signals */
439 if (selrtn == -1 && errno == EINTR) {
440 async_processing(buffer, buffer_len);
442 * After async processing we must go and do the select again, as
443 * the state of the flag in fds for the server file descriptor is
444 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
446 goto again;
449 /* Check if error */
450 if (selrtn == -1) {
451 /* something is wrong. Maybe the socket is dead? */
452 smb_read_error = READ_ERROR;
453 return False;
456 /* Did we timeout ? */
457 if (selrtn == 0) {
458 smb_read_error = READ_TIMEOUT;
459 return False;
463 * Ensure we process oplock break messages by preference.
464 * This is IMPORTANT ! Otherwise we can starve other processes
465 * sending us an oplock break message. JRA.
468 if (oplock_message_waiting(&fds)) {
469 async_processing(buffer, buffer_len);
471 * After async processing we must go and do the select again, as
472 * the state of the flag in fds for the server file descriptor is
473 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
475 goto again;
478 return receive_smb(smbd_server_fd(), buffer, 0);
481 /****************************************************************************
482 Get the next SMB packet, doing the local message processing automatically.
483 ****************************************************************************/
485 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
487 BOOL got_keepalive;
488 BOOL ret;
490 do {
491 ret = receive_message_or_smb(inbuf,bufsize,timeout);
493 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
494 } while (ret && got_keepalive);
496 return ret;
499 /****************************************************************************
500 We're terminating and have closed all our files/connections etc.
501 If there are any pending local messages we need to respond to them
502 before termination so that other smbds don't think we just died whilst
503 holding oplocks.
504 ****************************************************************************/
506 void respond_to_all_remaining_local_messages(void)
508 char buffer[1024];
511 * Assert we have no exclusive open oplocks.
514 if(get_number_of_exclusive_open_oplocks()) {
515 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
516 get_number_of_exclusive_open_oplocks() ));
517 return;
521 * Keep doing receive_local_message with a 1 ms timeout until
522 * we have no more messages.
525 while(receive_local_message(buffer, sizeof(buffer), 1)) {
526 /* Deal with oplock break requests from other smbd's. */
527 process_local_message(buffer, sizeof(buffer));
530 return;
535 These flags determine some of the permissions required to do an operation
537 Note that I don't set NEED_WRITE on some write operations because they
538 are used by some brain-dead clients when printing, and I don't want to
539 force write permissions on print services.
541 #define AS_USER (1<<0)
542 #define NEED_WRITE (1<<1)
543 #define TIME_INIT (1<<2)
544 #define CAN_IPC (1<<3)
545 #define AS_GUEST (1<<5)
546 #define QUEUE_IN_OPLOCK (1<<6)
547 #define DO_CHDIR (1<<7)
550 define a list of possible SMB messages and their corresponding
551 functions. Any message that has a NULL function is unimplemented -
552 please feel free to contribute implementations!
554 static const struct smb_message_struct {
555 const char *name;
556 int (*fn)(connection_struct *conn, char *, char *, int, int);
557 int flags;
558 } smb_messages[256] = {
560 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
561 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
562 /* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
563 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
564 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
565 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
566 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
567 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
568 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
569 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
570 /* 0x0a */ { "SMBread",reply_read,AS_USER},
571 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
572 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
573 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
574 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
575 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
576 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
577 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
578 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
579 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
580 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
581 /* 0x15 */ { NULL, NULL, 0 },
582 /* 0x16 */ { NULL, NULL, 0 },
583 /* 0x17 */ { NULL, NULL, 0 },
584 /* 0x18 */ { NULL, NULL, 0 },
585 /* 0x19 */ { NULL, NULL, 0 },
586 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
587 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
588 /* 0x1c */ { "SMBreadBs",NULL,0 },
589 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
590 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
591 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
592 /* 0x20 */ { "SMBwritec",NULL,0},
593 /* 0x21 */ { NULL, NULL, 0 },
594 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
595 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
596 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
597 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
598 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
599 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
600 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
601 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
602 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
603 /* 0x2b */ { "SMBecho",reply_echo,0},
604 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
605 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
606 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
607 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
608 /* 0x30 */ { NULL, NULL, 0 },
609 /* 0x31 */ { NULL, NULL, 0 },
610 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
611 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
612 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
613 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
614 /* 0x36 */ { NULL, NULL, 0 },
615 /* 0x37 */ { NULL, NULL, 0 },
616 /* 0x38 */ { NULL, NULL, 0 },
617 /* 0x39 */ { NULL, NULL, 0 },
618 /* 0x3a */ { NULL, NULL, 0 },
619 /* 0x3b */ { NULL, NULL, 0 },
620 /* 0x3c */ { NULL, NULL, 0 },
621 /* 0x3d */ { NULL, NULL, 0 },
622 /* 0x3e */ { NULL, NULL, 0 },
623 /* 0x3f */ { NULL, NULL, 0 },
624 /* 0x40 */ { NULL, NULL, 0 },
625 /* 0x41 */ { NULL, NULL, 0 },
626 /* 0x42 */ { NULL, NULL, 0 },
627 /* 0x43 */ { NULL, NULL, 0 },
628 /* 0x44 */ { NULL, NULL, 0 },
629 /* 0x45 */ { NULL, NULL, 0 },
630 /* 0x46 */ { NULL, NULL, 0 },
631 /* 0x47 */ { NULL, NULL, 0 },
632 /* 0x48 */ { NULL, NULL, 0 },
633 /* 0x49 */ { NULL, NULL, 0 },
634 /* 0x4a */ { NULL, NULL, 0 },
635 /* 0x4b */ { NULL, NULL, 0 },
636 /* 0x4c */ { NULL, NULL, 0 },
637 /* 0x4d */ { NULL, NULL, 0 },
638 /* 0x4e */ { NULL, NULL, 0 },
639 /* 0x4f */ { NULL, NULL, 0 },
640 /* 0x50 */ { NULL, NULL, 0 },
641 /* 0x51 */ { NULL, NULL, 0 },
642 /* 0x52 */ { NULL, NULL, 0 },
643 /* 0x53 */ { NULL, NULL, 0 },
644 /* 0x54 */ { NULL, NULL, 0 },
645 /* 0x55 */ { NULL, NULL, 0 },
646 /* 0x56 */ { NULL, NULL, 0 },
647 /* 0x57 */ { NULL, NULL, 0 },
648 /* 0x58 */ { NULL, NULL, 0 },
649 /* 0x59 */ { NULL, NULL, 0 },
650 /* 0x5a */ { NULL, NULL, 0 },
651 /* 0x5b */ { NULL, NULL, 0 },
652 /* 0x5c */ { NULL, NULL, 0 },
653 /* 0x5d */ { NULL, NULL, 0 },
654 /* 0x5e */ { NULL, NULL, 0 },
655 /* 0x5f */ { NULL, NULL, 0 },
656 /* 0x60 */ { NULL, NULL, 0 },
657 /* 0x61 */ { NULL, NULL, 0 },
658 /* 0x62 */ { NULL, NULL, 0 },
659 /* 0x63 */ { NULL, NULL, 0 },
660 /* 0x64 */ { NULL, NULL, 0 },
661 /* 0x65 */ { NULL, NULL, 0 },
662 /* 0x66 */ { NULL, NULL, 0 },
663 /* 0x67 */ { NULL, NULL, 0 },
664 /* 0x68 */ { NULL, NULL, 0 },
665 /* 0x69 */ { NULL, NULL, 0 },
666 /* 0x6a */ { NULL, NULL, 0 },
667 /* 0x6b */ { NULL, NULL, 0 },
668 /* 0x6c */ { NULL, NULL, 0 },
669 /* 0x6d */ { NULL, NULL, 0 },
670 /* 0x6e */ { NULL, NULL, 0 },
671 /* 0x6f */ { NULL, NULL, 0 },
672 /* 0x70 */ { "SMBtcon",reply_tcon,0},
673 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
674 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
675 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
676 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
677 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
678 /* 0x76 */ { NULL, NULL, 0 },
679 /* 0x77 */ { NULL, NULL, 0 },
680 /* 0x78 */ { NULL, NULL, 0 },
681 /* 0x79 */ { NULL, NULL, 0 },
682 /* 0x7a */ { NULL, NULL, 0 },
683 /* 0x7b */ { NULL, NULL, 0 },
684 /* 0x7c */ { NULL, NULL, 0 },
685 /* 0x7d */ { NULL, NULL, 0 },
686 /* 0x7e */ { NULL, NULL, 0 },
687 /* 0x7f */ { NULL, NULL, 0 },
688 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
689 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
690 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
691 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
692 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
693 /* 0x85 */ { NULL, NULL, 0 },
694 /* 0x86 */ { NULL, NULL, 0 },
695 /* 0x87 */ { NULL, NULL, 0 },
696 /* 0x88 */ { NULL, NULL, 0 },
697 /* 0x89 */ { NULL, NULL, 0 },
698 /* 0x8a */ { NULL, NULL, 0 },
699 /* 0x8b */ { NULL, NULL, 0 },
700 /* 0x8c */ { NULL, NULL, 0 },
701 /* 0x8d */ { NULL, NULL, 0 },
702 /* 0x8e */ { NULL, NULL, 0 },
703 /* 0x8f */ { NULL, NULL, 0 },
704 /* 0x90 */ { NULL, NULL, 0 },
705 /* 0x91 */ { NULL, NULL, 0 },
706 /* 0x92 */ { NULL, NULL, 0 },
707 /* 0x93 */ { NULL, NULL, 0 },
708 /* 0x94 */ { NULL, NULL, 0 },
709 /* 0x95 */ { NULL, NULL, 0 },
710 /* 0x96 */ { NULL, NULL, 0 },
711 /* 0x97 */ { NULL, NULL, 0 },
712 /* 0x98 */ { NULL, NULL, 0 },
713 /* 0x99 */ { NULL, NULL, 0 },
714 /* 0x9a */ { NULL, NULL, 0 },
715 /* 0x9b */ { NULL, NULL, 0 },
716 /* 0x9c */ { NULL, NULL, 0 },
717 /* 0x9d */ { NULL, NULL, 0 },
718 /* 0x9e */ { NULL, NULL, 0 },
719 /* 0x9f */ { NULL, NULL, 0 },
720 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
721 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
722 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
723 /* 0xa3 */ { NULL, NULL, 0 },
724 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
725 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
726 /* 0xa6 */ { NULL, NULL, 0 },
727 /* 0xa7 */ { NULL, NULL, 0 },
728 /* 0xa8 */ { NULL, NULL, 0 },
729 /* 0xa9 */ { NULL, NULL, 0 },
730 /* 0xaa */ { NULL, NULL, 0 },
731 /* 0xab */ { NULL, NULL, 0 },
732 /* 0xac */ { NULL, NULL, 0 },
733 /* 0xad */ { NULL, NULL, 0 },
734 /* 0xae */ { NULL, NULL, 0 },
735 /* 0xaf */ { NULL, NULL, 0 },
736 /* 0xb0 */ { NULL, NULL, 0 },
737 /* 0xb1 */ { NULL, NULL, 0 },
738 /* 0xb2 */ { NULL, NULL, 0 },
739 /* 0xb3 */ { NULL, NULL, 0 },
740 /* 0xb4 */ { NULL, NULL, 0 },
741 /* 0xb5 */ { NULL, NULL, 0 },
742 /* 0xb6 */ { NULL, NULL, 0 },
743 /* 0xb7 */ { NULL, NULL, 0 },
744 /* 0xb8 */ { NULL, NULL, 0 },
745 /* 0xb9 */ { NULL, NULL, 0 },
746 /* 0xba */ { NULL, NULL, 0 },
747 /* 0xbb */ { NULL, NULL, 0 },
748 /* 0xbc */ { NULL, NULL, 0 },
749 /* 0xbd */ { NULL, NULL, 0 },
750 /* 0xbe */ { NULL, NULL, 0 },
751 /* 0xbf */ { NULL, NULL, 0 },
752 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
753 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
754 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
755 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
756 /* 0xc4 */ { NULL, NULL, 0 },
757 /* 0xc5 */ { NULL, NULL, 0 },
758 /* 0xc6 */ { NULL, NULL, 0 },
759 /* 0xc7 */ { NULL, NULL, 0 },
760 /* 0xc8 */ { NULL, NULL, 0 },
761 /* 0xc9 */ { NULL, NULL, 0 },
762 /* 0xca */ { NULL, NULL, 0 },
763 /* 0xcb */ { NULL, NULL, 0 },
764 /* 0xcc */ { NULL, NULL, 0 },
765 /* 0xcd */ { NULL, NULL, 0 },
766 /* 0xce */ { NULL, NULL, 0 },
767 /* 0xcf */ { NULL, NULL, 0 },
768 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
769 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
770 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
771 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
772 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
773 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
774 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
775 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
776 /* 0xd8 */ { NULL, NULL, 0 },
777 /* 0xd9 */ { NULL, NULL, 0 },
778 /* 0xda */ { NULL, NULL, 0 },
779 /* 0xdb */ { NULL, NULL, 0 },
780 /* 0xdc */ { NULL, NULL, 0 },
781 /* 0xdd */ { NULL, NULL, 0 },
782 /* 0xde */ { NULL, NULL, 0 },
783 /* 0xdf */ { NULL, NULL, 0 },
784 /* 0xe0 */ { NULL, NULL, 0 },
785 /* 0xe1 */ { NULL, NULL, 0 },
786 /* 0xe2 */ { NULL, NULL, 0 },
787 /* 0xe3 */ { NULL, NULL, 0 },
788 /* 0xe4 */ { NULL, NULL, 0 },
789 /* 0xe5 */ { NULL, NULL, 0 },
790 /* 0xe6 */ { NULL, NULL, 0 },
791 /* 0xe7 */ { NULL, NULL, 0 },
792 /* 0xe8 */ { NULL, NULL, 0 },
793 /* 0xe9 */ { NULL, NULL, 0 },
794 /* 0xea */ { NULL, NULL, 0 },
795 /* 0xeb */ { NULL, NULL, 0 },
796 /* 0xec */ { NULL, NULL, 0 },
797 /* 0xed */ { NULL, NULL, 0 },
798 /* 0xee */ { NULL, NULL, 0 },
799 /* 0xef */ { NULL, NULL, 0 },
800 /* 0xf0 */ { NULL, NULL, 0 },
801 /* 0xf1 */ { NULL, NULL, 0 },
802 /* 0xf2 */ { NULL, NULL, 0 },
803 /* 0xf3 */ { NULL, NULL, 0 },
804 /* 0xf4 */ { NULL, NULL, 0 },
805 /* 0xf5 */ { NULL, NULL, 0 },
806 /* 0xf6 */ { NULL, NULL, 0 },
807 /* 0xf7 */ { NULL, NULL, 0 },
808 /* 0xf8 */ { NULL, NULL, 0 },
809 /* 0xf9 */ { NULL, NULL, 0 },
810 /* 0xfa */ { NULL, NULL, 0 },
811 /* 0xfb */ { NULL, NULL, 0 },
812 /* 0xfc */ { NULL, NULL, 0 },
813 /* 0xfd */ { NULL, NULL, 0 },
814 /* 0xfe */ { NULL, NULL, 0 },
815 /* 0xff */ { NULL, NULL, 0 }
819 /*******************************************************************
820 Dump a packet to a file.
821 ********************************************************************/
823 static void smb_dump(const char *name, int type, char *data, ssize_t len)
825 int fd, i;
826 pstring fname;
827 if (DEBUGLEVEL < 50) return;
829 if (len < 4) len = smb_len(data)+4;
830 for (i=1;i<100;i++) {
831 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
832 type ? "req" : "resp");
833 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
834 if (fd != -1 || errno != EEXIST) break;
836 if (fd != -1) {
837 ssize_t ret = write(fd, data, len);
838 if (ret != len)
839 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
840 close(fd);
841 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
846 /****************************************************************************
847 Do a switch on the message type, and return the response size
848 ****************************************************************************/
850 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
852 static pid_t pid= (pid_t)-1;
853 int outsize = 0;
854 extern uint16 global_smbpid;
856 type &= 0xff;
858 if (pid == (pid_t)-1)
859 pid = sys_getpid();
861 errno = 0;
862 last_message = type;
864 /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
865 if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
866 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
867 exit_server("Non-SMB packet");
868 return(-1);
871 /* yuck! this is an interim measure before we get rid of our
872 current inbuf/outbuf system */
873 global_smbpid = SVAL(inbuf,smb_pid);
875 if (smb_messages[type].fn == NULL) {
876 DEBUG(0,("Unknown message type %d!\n",type));
877 smb_dump("Unknown", 1, inbuf, size);
878 outsize = reply_unknown(inbuf,outbuf);
879 } else {
880 int flags = smb_messages[type].flags;
881 static uint16 last_session_tag = UID_FIELD_INVALID;
882 /* In share mode security we must ignore the vuid. */
883 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
884 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
886 DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn));
888 smb_dump(smb_fn_name(type), 1, inbuf, size);
889 if(global_oplock_break) {
890 if(flags & QUEUE_IN_OPLOCK) {
892 * Queue this message as we are the process of an oplock break.
895 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
896 DEBUGADD( 2, ( "oplock break state.\n" ) );
898 push_oplock_pending_smb_message( inbuf, size );
899 return -1;
903 /* Ensure this value is replaced in the incoming packet. */
904 SSVAL(inbuf,smb_uid,session_tag);
907 * Ensure the correct username is in current_user_info.
908 * This is a really ugly bugfix for problems with
909 * multiple session_setup_and_X's being done and
910 * allowing %U and %G substitutions to work correctly.
911 * There is a reason this code is done here, don't
912 * move it unless you know what you're doing... :-).
913 * JRA.
916 if (session_tag != last_session_tag) {
917 user_struct *vuser = NULL;
919 last_session_tag = session_tag;
920 if(session_tag != UID_FIELD_INVALID)
921 vuser = get_valid_user_struct(session_tag);
922 if(vuser != NULL)
923 set_current_user_info(&vuser->user);
926 /* does this protocol need to be run as root? */
927 if (!(flags & AS_USER))
928 change_to_root_user();
930 /* does this protocol need a valid tree connection? */
931 if ((flags & AS_USER) && !conn)
932 return ERROR_DOS(ERRSRV, ERRinvnid);
935 /* does this protocol need to be run as the connected user? */
936 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
937 if (flags & AS_GUEST)
938 flags &= ~AS_USER;
939 else
940 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
943 /* this code is to work around a bug is MS client 3 without
944 introducing a security hole - it needs to be able to do
945 print queue checks as guest if it isn't logged in properly */
946 if (flags & AS_USER)
947 flags &= ~AS_GUEST;
949 /* does it need write permission? */
950 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
951 return(ERROR_DOS(ERRSRV,ERRaccess));
953 /* ipc services are limited */
954 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
955 return(ERROR_DOS(ERRSRV,ERRaccess));
957 /* load service specific parameters */
958 if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False)))
959 return(ERROR_DOS(ERRSRV,ERRaccess));
961 /* does this protocol need to be run as guest? */
962 if ((flags & AS_GUEST) && (!change_to_guest() ||
963 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
964 return(ERROR_DOS(ERRSRV,ERRaccess));
966 last_inbuf = inbuf;
968 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
971 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
973 return(outsize);
977 /****************************************************************************
978 Construct a reply to the incoming packet.
979 ****************************************************************************/
981 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
983 int type = CVAL(inbuf,smb_com);
984 int outsize = 0;
985 int msg_type = CVAL(inbuf,0);
987 GetTimeOfDay(&smb_last_time);
989 chain_size = 0;
990 file_chain_reset();
991 reset_chain_p();
993 if (msg_type != 0)
994 return(reply_special(inbuf,outbuf));
996 construct_reply_common(inbuf, outbuf);
998 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
1000 outsize += chain_size;
1002 if(outsize > 4)
1003 smb_setlen(outbuf,outsize - 4);
1004 return(outsize);
1007 /****************************************************************************
1008 Keep track of the number of running smbd's. This functionality is used to
1009 'hard' limit Samba overhead on resource constrained systems.
1010 ****************************************************************************/
1012 static BOOL process_count_update_successful = False;
1014 static int32 increment_smbd_process_count(void)
1016 int32 total_smbds;
1018 if (lp_max_smbd_processes()) {
1019 total_smbds = 0;
1020 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1021 return 1;
1022 process_count_update_successful = True;
1023 return total_smbds + 1;
1025 return 1;
1028 void decrement_smbd_process_count(void)
1030 int32 total_smbds;
1032 if (lp_max_smbd_processes() && process_count_update_successful) {
1033 total_smbds = 1;
1034 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1038 static BOOL smbd_process_limit(void)
1040 int32 total_smbds;
1042 if (lp_max_smbd_processes()) {
1044 /* Always add one to the smbd process count, as exit_server() always
1045 * subtracts one.
1048 if (!conn_tdb_ctx()) {
1049 DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1050 set. Ignoring max smbd restriction.\n"));
1051 return False;
1054 total_smbds = increment_smbd_process_count();
1055 return total_smbds > lp_max_smbd_processes();
1057 else
1058 return False;
1061 /****************************************************************************
1062 Process an smb from the client - split out from the smbd_process() code so
1063 it can be used by the oplock break code.
1064 ****************************************************************************/
1066 void process_smb(char *inbuf, char *outbuf)
1068 static int trans_num;
1069 int msg_type = CVAL(inbuf,0);
1070 int32 len = smb_len(inbuf);
1071 int nread = len + 4;
1073 DO_PROFILE_INC(smb_count);
1075 if (trans_num == 0) {
1076 /* on the first packet, check the global hosts allow/ hosts
1077 deny parameters before doing any parsing of the packet
1078 passed to us by the client. This prevents attacks on our
1079 parsing code from hosts not in the hosts allow list */
1080 if (smbd_process_limit() ||
1081 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1082 /* send a negative session response "not listening on calling name" */
1083 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1084 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1085 (void)send_smb(smbd_server_fd(),(char *)buf);
1086 exit_server("connection denied");
1090 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1091 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1093 if (msg_type == 0)
1094 show_msg(inbuf);
1095 else if(msg_type == SMBkeepalive)
1096 return; /* Keepalive packet. */
1098 nread = construct_reply(inbuf,outbuf,nread,max_send);
1100 if(nread > 0) {
1101 if (CVAL(outbuf,0) == 0)
1102 show_msg(outbuf);
1104 if (nread != smb_len(outbuf) + 4) {
1105 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1106 nread, smb_len(outbuf)));
1107 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1108 exit_server("process_smb: send_smb failed.");
1111 trans_num++;
1114 /****************************************************************************
1115 Return a string containing the function name of a SMB command.
1116 ****************************************************************************/
1118 const char *smb_fn_name(int type)
1120 const char *unknown_name = "SMBunknown";
1122 if (smb_messages[type].name == NULL)
1123 return(unknown_name);
1125 return(smb_messages[type].name);
1128 /****************************************************************************
1129 Helper functions for contruct_reply.
1130 ****************************************************************************/
1132 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1134 void add_to_common_flags2(uint32 v)
1136 common_flags2 |= v;
1139 void remove_from_common_flags2(uint32 v)
1141 common_flags2 &= ~v;
1144 void construct_reply_common(char *inbuf,char *outbuf)
1146 memset(outbuf,'\0',smb_size);
1148 set_message(outbuf,0,0,True);
1149 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1151 memcpy(outbuf+4,inbuf+4,4);
1152 SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1153 SCVAL(outbuf,smb_reh,0);
1154 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1155 SSVAL(outbuf,smb_flg2,
1156 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1157 common_flags2);
1159 SSVAL(outbuf,smb_err,SMB_SUCCESS);
1160 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1161 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1162 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1163 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1166 /****************************************************************************
1167 Construct a chained reply and add it to the already made reply
1168 ****************************************************************************/
1170 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1172 static char *orig_inbuf;
1173 static char *orig_outbuf;
1174 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1175 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1176 char *inbuf2, *outbuf2;
1177 int outsize2;
1178 char inbuf_saved[smb_wct];
1179 char outbuf_saved[smb_wct];
1180 int wct = CVAL(outbuf,smb_wct);
1181 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
1183 /* maybe its not chained */
1184 if (smb_com2 == 0xFF) {
1185 SCVAL(outbuf,smb_vwv0,0xFF);
1186 return outsize;
1189 if (chain_size == 0) {
1190 /* this is the first part of the chain */
1191 orig_inbuf = inbuf;
1192 orig_outbuf = outbuf;
1196 * The original Win95 redirector dies on a reply to
1197 * a lockingX and read chain unless the chain reply is
1198 * 4 byte aligned. JRA.
1201 outsize = (outsize + 3) & ~3;
1203 /* we need to tell the client where the next part of the reply will be */
1204 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1205 SCVAL(outbuf,smb_vwv0,smb_com2);
1207 /* remember how much the caller added to the chain, only counting stuff
1208 after the parameter words */
1209 chain_size += outsize - smb_wct;
1211 /* work out pointers into the original packets. The
1212 headers on these need to be filled in */
1213 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1214 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1216 /* remember the original command type */
1217 smb_com1 = CVAL(orig_inbuf,smb_com);
1219 /* save the data which will be overwritten by the new headers */
1220 memcpy(inbuf_saved,inbuf2,smb_wct);
1221 memcpy(outbuf_saved,outbuf2,smb_wct);
1223 /* give the new packet the same header as the last part of the SMB */
1224 memmove(inbuf2,inbuf,smb_wct);
1226 /* create the in buffer */
1227 SCVAL(inbuf2,smb_com,smb_com2);
1229 /* create the out buffer */
1230 construct_reply_common(inbuf2, outbuf2);
1232 DEBUG(3,("Chained message\n"));
1233 show_msg(inbuf2);
1235 /* process the request */
1236 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1237 bufsize-chain_size);
1239 /* copy the new reply and request headers over the old ones, but
1240 preserve the smb_com field */
1241 memmove(orig_outbuf,outbuf2,smb_wct);
1242 SCVAL(orig_outbuf,smb_com,smb_com1);
1244 /* restore the saved data, being careful not to overwrite any
1245 data from the reply header */
1246 memcpy(inbuf2,inbuf_saved,smb_wct);
1249 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1250 if (ofs < 0) ofs = 0;
1251 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1254 return outsize2;
1257 /****************************************************************************
1258 Setup the needed select timeout.
1259 ****************************************************************************/
1261 static int setup_select_timeout(void)
1263 int select_timeout;
1264 int t;
1266 select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1267 select_timeout *= 1000;
1269 t = change_notify_timeout();
1270 if (t != -1)
1271 select_timeout = MIN(select_timeout, t*1000);
1273 if (print_notify_messages_pending())
1274 select_timeout = MIN(select_timeout, 1000);
1276 return select_timeout;
1279 /****************************************************************************
1280 Check if services need reloading.
1281 ****************************************************************************/
1283 void check_reload(int t)
1285 static time_t last_smb_conf_reload_time = 0;
1286 static time_t last_load_printers_reload_time = 0;
1287 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1289 if(last_smb_conf_reload_time == 0) {
1290 last_smb_conf_reload_time = t;
1291 /* Our printing subsystem might not be ready at smbd start up.
1292 Then no printer is available till the first printers check
1293 is performed. A lower initial interval circumvents this. */
1294 if ( printcap_cache_time > 60 )
1295 last_load_printers_reload_time = t - printcap_cache_time + 60;
1296 else
1297 last_load_printers_reload_time = t;
1300 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1301 reload_services(True);
1302 reload_after_sighup = False;
1303 last_smb_conf_reload_time = t;
1306 /* 'printcap cache time = 0' disable the feature */
1308 if ( printcap_cache_time != 0 )
1310 /* see if it's time to reload or if the clock has been set back */
1312 if ( (t >= last_load_printers_reload_time+printcap_cache_time)
1313 || (t-last_load_printers_reload_time < 0) )
1315 DEBUG( 3,( "Printcap cache time expired.\n"));
1316 remove_stale_printers();
1317 load_printers();
1318 last_load_printers_reload_time = t;
1323 /****************************************************************************
1324 Process any timeout housekeeping. Return False if the caller should exit.
1325 ****************************************************************************/
1327 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1329 static time_t last_keepalive_sent_time = 0;
1330 static time_t last_idle_closed_check = 0;
1331 time_t t;
1332 BOOL allidle = True;
1333 extern int keepalive;
1335 if (smb_read_error == READ_EOF) {
1336 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1337 return False;
1340 if (smb_read_error == READ_ERROR) {
1341 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1342 strerror(errno)));
1343 return False;
1346 if (smb_read_error == READ_BAD_SIG) {
1347 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1348 return False;
1351 *last_timeout_processing_time = t = time(NULL);
1353 if(last_keepalive_sent_time == 0)
1354 last_keepalive_sent_time = t;
1356 if(last_idle_closed_check == 0)
1357 last_idle_closed_check = t;
1359 /* become root again if waiting */
1360 change_to_root_user();
1362 /* run all registered idle events */
1363 smb_run_idle_events(t);
1365 /* check if we need to reload services */
1366 check_reload(t);
1368 /* automatic timeout if all connections are closed */
1369 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1370 DEBUG( 2, ( "Closing idle connection\n" ) );
1371 return False;
1372 } else {
1373 last_idle_closed_check = t;
1376 if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1377 extern struct auth_context *negprot_global_auth_context;
1378 if (!send_keepalive(smbd_server_fd())) {
1379 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1380 return False;
1383 /* send a keepalive for a password server or the like.
1384 This is attached to the auth_info created in the
1385 negprot */
1386 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
1387 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1389 negprot_global_auth_context->challenge_set_method->send_keepalive
1390 (&negprot_global_auth_context->challenge_set_method->private_data);
1393 last_keepalive_sent_time = t;
1396 /* check for connection timeouts */
1397 allidle = conn_idle_all(t, deadtime);
1399 if (allidle && conn_num_open()>0) {
1400 DEBUG(2,("Closing idle connection 2.\n"));
1401 return False;
1404 if(global_machine_password_needs_changing &&
1405 /* for ADS we need to do a regular ADS password change, not a domain
1406 password change */
1407 lp_security() == SEC_DOMAIN) {
1409 unsigned char trust_passwd_hash[16];
1410 time_t lct;
1413 * We're in domain level security, and the code that
1414 * read the machine password flagged that the machine
1415 * password needs changing.
1419 * First, open the machine password file with an exclusive lock.
1422 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1423 DEBUG(0,("process: unable to lock the machine account password for \
1424 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1425 return True;
1428 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1429 DEBUG(0,("process: unable to read the machine account password for \
1430 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1431 secrets_lock_trust_account_password(lp_workgroup(), False);
1432 return True;
1436 * Make sure someone else hasn't already done this.
1439 if(t < lct + lp_machine_password_timeout()) {
1440 global_machine_password_needs_changing = False;
1441 secrets_lock_trust_account_password(lp_workgroup(), False);
1442 return True;
1445 /* always just contact the PDC here */
1447 change_trust_account_password( lp_workgroup(), NULL);
1448 global_machine_password_needs_changing = False;
1449 secrets_lock_trust_account_password(lp_workgroup(), False);
1453 * Check to see if we have any blocking locks
1454 * outstanding on the queue.
1456 process_blocking_lock_queue(t);
1458 /* update printer queue caches if necessary */
1460 update_monitored_printq_cache();
1463 * Check to see if we have any change notifies
1464 * outstanding on the queue.
1466 process_pending_change_notify_queue(t);
1469 * Now we are root, check if the log files need pruning.
1470 * Force a log file check.
1472 force_check_log_size();
1473 check_log_size();
1475 /* Send any queued printer notify message to interested smbd's. */
1477 print_notify_send_messages(0);
1480 * Modify the select timeout depending upon
1481 * what we have remaining in our queues.
1484 *select_timeout = setup_select_timeout();
1486 return True;
1489 /****************************************************************************
1490 process commands from the client
1491 ****************************************************************************/
1493 void smbd_process(void)
1495 extern int smb_echo_count;
1496 time_t last_timeout_processing_time = time(NULL);
1497 unsigned int num_smbs = 0;
1498 const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN;
1500 InBuffer = (char *)SMB_MALLOC(total_buffer_size);
1501 OutBuffer = (char *)SMB_MALLOC(total_buffer_size);
1502 if ((InBuffer == NULL) || (OutBuffer == NULL))
1503 return;
1505 #if defined(DEVELOPER)
1506 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1507 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1508 #endif
1510 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1512 while (True) {
1513 int deadtime = lp_deadtime()*60;
1514 int select_timeout = setup_select_timeout();
1515 int num_echos;
1517 if (deadtime <= 0)
1518 deadtime = DEFAULT_SMBD_TIMEOUT;
1520 errno = 0;
1522 /* free up temporary memory */
1523 lp_talloc_free();
1524 main_loop_talloc_free();
1526 /* run all registered idle events */
1527 smb_run_idle_events(time(NULL));
1530 /* Did someone ask for immediate checks on things like blocking locks ? */
1531 if (select_timeout == 0) {
1532 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1533 return;
1534 num_smbs = 0; /* Reset smb counter. */
1537 #if defined(DEVELOPER)
1538 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1539 #endif
1541 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1542 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1543 return;
1544 num_smbs = 0; /* Reset smb counter. */
1548 * Ensure we do timeout processing if the SMB we just got was
1549 * only an echo request. This allows us to set the select
1550 * timeout in 'receive_message_or_smb()' to any value we like
1551 * without worrying that the client will send echo requests
1552 * faster than the select timeout, thus starving out the
1553 * essential processing (change notify, blocking locks) that
1554 * the timeout code does. JRA.
1556 num_echos = smb_echo_count;
1558 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1560 process_smb(InBuffer, OutBuffer);
1562 if (smb_echo_count != num_echos) {
1563 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1564 return;
1565 num_smbs = 0; /* Reset smb counter. */
1568 num_smbs++;
1571 * If we are getting smb requests in a constant stream
1572 * with no echos, make sure we attempt timeout processing
1573 * every select_timeout milliseconds - but only check for this
1574 * every 200 smb requests.
1577 if ((num_smbs % 200) == 0) {
1578 time_t new_check_time = time(NULL);
1579 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1580 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1581 return;
1582 num_smbs = 0; /* Reset smb counter. */
1583 last_timeout_processing_time = new_check_time; /* Reset time. */
1587 /* The timeout_processing function isn't run nearly
1588 often enough to implement 'max log size' without
1589 overrunning the size of the file by many megabytes.
1590 This is especially true if we are running at debug
1591 level 10. Checking every 50 SMBs is a nice
1592 tradeoff of performance vs log file size overrun. */
1594 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1595 change_to_root_user();
1596 check_log_size();