r1154: Change default setting for case sensitivity to "auto". If set to auto
[Samba/gebeck_regimport.git] / source3 / smbd / process.c
blob72a604811b1edb328fd9365be628cfc23edd6460
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 = (struct pending_message_list *)
89 malloc(sizeof(struct pending_message_list));
91 if(msg == NULL) {
92 DEBUG(0,("push_message: malloc fail (1)\n"));
93 return False;
96 memset(msg,'\0',sizeof(*msg));
98 msg->buf = data_blob(buf, msg_len);
99 if(msg->buf.data == NULL) {
100 DEBUG(0,("push_message: malloc fail (2)\n"));
101 SAFE_FREE(msg);
102 return False;
105 if (ptv) {
106 msg->msg_time = *ptv;
109 if (private) {
110 msg->private_data = data_blob(private, private_len);
111 if (msg->private_data.data == NULL) {
112 DEBUG(0,("push_message: malloc fail (3)\n"));
113 data_blob_free(&msg->buf);
114 SAFE_FREE(msg);
118 if (qt == OPLOCK_QUEUE) {
119 DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
120 } else {
121 DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
124 DEBUG(10,("push_message: pushed message length %u on queue %s\n",
125 (unsigned int)msg_len,
126 qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" ));
128 return True;
131 /****************************************************************************
132 Function to push an oplock smb message onto a linked list of local smb messages ready
133 for processing.
134 ****************************************************************************/
136 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
138 BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
139 if (ret) {
140 /* Push the MID of this packet on the signing queue. */
141 srv_defer_sign_response(SVAL(buf,smb_mid));
143 return ret;
146 /****************************************************************************
147 Function to delete a sharing violation open message by mid.
148 ****************************************************************************/
150 void remove_sharing_violation_open_smb_message(uint16 mid)
152 struct pending_message_list *pml;
154 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
155 if (mid == SVAL(pml->buf.data,smb_mid)) {
156 DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
157 (unsigned int)mid, (unsigned int)pml->buf.length ));
158 DLIST_REMOVE(smb_sharing_violation_queue, pml);
159 free_queued_message(pml);
160 return;
165 /****************************************************************************
166 Move a sharing violation open retry message to the front of the list and
167 schedule it for immediate processing.
168 ****************************************************************************/
170 void schedule_sharing_violation_open_smb_message(uint16 mid)
172 struct pending_message_list *pml;
173 int i = 0;
175 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
176 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
177 DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
178 (unsigned int)msg_mid ));
179 if (mid == msg_mid) {
180 DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
181 mid ));
182 pml->msg_time.tv_sec = 0;
183 pml->msg_time.tv_usec = 0;
184 DLIST_PROMOTE(smb_sharing_violation_queue, pml);
185 return;
189 DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
190 mid ));
193 /****************************************************************************
194 Return true if this mid is on the deferred queue.
195 ****************************************************************************/
197 BOOL open_was_deferred(uint16 mid)
199 struct pending_message_list *pml;
200 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
201 if (SVAL(pml->buf.data,smb_mid) == mid) {
202 return True;
205 return False;
208 /****************************************************************************
209 Return the message queued by this mid.
210 ****************************************************************************/
212 struct pending_message_list *get_open_deferred_message(uint16 mid)
214 struct pending_message_list *pml;
215 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
216 if (SVAL(pml->buf.data,smb_mid) == mid) {
217 return pml;
220 return NULL;
223 /****************************************************************************
224 Function to push a sharing violation open smb message onto a linked list of local smb messages ready
225 for processing.
226 ****************************************************************************/
228 BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len)
230 uint16 mid = SVAL(InBuffer,smb_mid);
231 struct timeval tv;
232 SMB_BIG_INT tdif;
234 tv = *ptv;
235 tdif = tv.tv_sec;
236 tdif *= 1000000;
237 tdif += tv.tv_usec;
239 /* Add on the timeout. */
240 tdif += SHARING_VIOLATION_USEC_WAIT;
242 tv.tv_sec = tdif / 1000000;
243 tv.tv_usec = tdif % 1000000;
245 DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\
246 timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid,
247 (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec));
249 return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer,
250 smb_len(InBuffer)+4, &tv, private, priv_len);
253 /****************************************************************************
254 Do all async processing in here. This includes UDB oplock messages, kernel
255 oplock messages, change notify events etc.
256 ****************************************************************************/
258 static void async_processing(char *buffer, int buffer_len)
260 DEBUG(10,("async_processing: Doing async processing.\n"));
262 /* check for oplock messages (both UDP and kernel) */
263 if (receive_local_message(buffer, buffer_len, 1)) {
264 process_local_message(buffer, buffer_len);
267 if (got_sig_term) {
268 exit_server("Caught TERM signal");
271 /* check for async change notify events */
272 process_pending_change_notify_queue(0);
274 /* check for sighup processing */
275 if (reload_after_sighup) {
276 change_to_root_user();
277 DEBUG(1,("Reloading services after SIGHUP\n"));
278 reload_services(False);
279 reload_after_sighup = 0;
283 /****************************************************************************
284 Do a select on an two fd's - with timeout.
286 If a local udp message has been pushed onto the
287 queue (this can only happen during oplock break
288 processing) call async_processing()
290 If a pending smb message has been pushed onto the
291 queue (this can only happen during oplock break
292 processing) return this next.
294 If the first smbfd is ready then read an smb from it.
295 if the second (loopback UDP) fd is ready then read a message
296 from it and setup the buffer header to identify the length
297 and from address.
298 Returns False on timeout or error.
299 Else returns True.
301 The timeout is in milliseconds
302 ****************************************************************************/
304 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
306 fd_set fds;
307 int selrtn;
308 struct timeval to;
309 struct timeval *pto;
310 int maxfd;
312 smb_read_error = 0;
314 again:
316 to.tv_sec = timeout / 1000;
317 to.tv_usec = (timeout % 1000) * 1000;
318 pto = timeout > 0 ? &to : NULL;
321 * Note that this call must be before processing any SMB
322 * messages as we need to synchronously process any messages
323 * we may have sent to ourselves from the previous SMB.
325 message_dispatch();
328 * Check to see if we already have a message on the smb queue.
329 * If so - copy and return it.
331 if(smb_oplock_queue != NULL) {
332 struct pending_message_list *msg = smb_oplock_queue;
333 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
335 /* Free the message we just copied. */
336 DLIST_REMOVE(smb_oplock_queue, msg);
337 free_queued_message(msg);
339 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
340 return True;
344 * Check to see if we already have a message on the deferred open queue
345 * and it's time to schedule.
347 if(smb_sharing_violation_queue != NULL) {
348 BOOL pop_message = False;
349 struct pending_message_list *msg = smb_sharing_violation_queue;
351 if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
352 pop_message = True;
353 } else {
354 struct timeval tv;
355 SMB_BIG_INT tdif;
357 GetTimeOfDay(&tv);
358 tdif = usec_time_diff(&msg->msg_time, &tv);
359 if (tdif <= 0) {
360 /* Timed out. Schedule...*/
361 pop_message = True;
362 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
363 } else {
364 /* Make a more accurate select timeout. */
365 to.tv_sec = tdif / 1000000;
366 to.tv_usec = tdif % 1000000;
367 pto = &to;
368 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
369 (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
373 if (pop_message) {
374 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
376 /* We leave this message on the queue so the open code can
377 know this is a retry. */
378 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
379 return True;
384 * Setup the select read fd set.
387 FD_ZERO(&fds);
390 * Ensure we process oplock break messages by preference.
391 * We have to do this before the select, after the select
392 * and if the select returns EINTR. This is due to the fact
393 * that the selects called from async_processing can eat an EINTR
394 * caused by a signal (we can't take the break message there).
395 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
398 if (oplock_message_waiting(&fds)) {
399 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
400 async_processing(buffer, buffer_len);
402 * After async processing we must go and do the select again, as
403 * the state of the flag in fds for the server file descriptor is
404 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
406 goto again;
409 FD_SET(smbd_server_fd(),&fds);
410 maxfd = setup_oplock_select_set(&fds);
412 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
414 /* if we get EINTR then maybe we have received an oplock
415 signal - treat this as select returning 1. This is ugly, but
416 is the best we can do until the oplock code knows more about
417 signals */
418 if (selrtn == -1 && errno == EINTR) {
419 async_processing(buffer, buffer_len);
421 * After async processing we must go and do the select again, as
422 * the state of the flag in fds for the server file descriptor is
423 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
425 goto again;
428 /* Check if error */
429 if (selrtn == -1) {
430 /* something is wrong. Maybe the socket is dead? */
431 smb_read_error = READ_ERROR;
432 return False;
435 /* Did we timeout ? */
436 if (selrtn == 0) {
437 smb_read_error = READ_TIMEOUT;
438 return False;
442 * Ensure we process oplock break messages by preference.
443 * This is IMPORTANT ! Otherwise we can starve other processes
444 * sending us an oplock break message. JRA.
447 if (oplock_message_waiting(&fds)) {
448 async_processing(buffer, buffer_len);
450 * After async processing we must go and do the select again, as
451 * the state of the flag in fds for the server file descriptor is
452 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
454 goto again;
457 return receive_smb(smbd_server_fd(), buffer, 0);
460 /****************************************************************************
461 Get the next SMB packet, doing the local message processing automatically.
462 ****************************************************************************/
464 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
466 BOOL got_keepalive;
467 BOOL ret;
469 do {
470 ret = receive_message_or_smb(inbuf,bufsize,timeout);
472 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
473 } while (ret && got_keepalive);
475 return ret;
478 /****************************************************************************
479 We're terminating and have closed all our files/connections etc.
480 If there are any pending local messages we need to respond to them
481 before termination so that other smbds don't think we just died whilst
482 holding oplocks.
483 ****************************************************************************/
485 void respond_to_all_remaining_local_messages(void)
487 char buffer[1024];
490 * Assert we have no exclusive open oplocks.
493 if(get_number_of_exclusive_open_oplocks()) {
494 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
495 get_number_of_exclusive_open_oplocks() ));
496 return;
500 * Keep doing receive_local_message with a 1 ms timeout until
501 * we have no more messages.
504 while(receive_local_message(buffer, sizeof(buffer), 1)) {
505 /* Deal with oplock break requests from other smbd's. */
506 process_local_message(buffer, sizeof(buffer));
509 return;
514 These flags determine some of the permissions required to do an operation
516 Note that I don't set NEED_WRITE on some write operations because they
517 are used by some brain-dead clients when printing, and I don't want to
518 force write permissions on print services.
520 #define AS_USER (1<<0)
521 #define NEED_WRITE (1<<1)
522 #define TIME_INIT (1<<2)
523 #define CAN_IPC (1<<3)
524 #define AS_GUEST (1<<5)
525 #define QUEUE_IN_OPLOCK (1<<6)
526 #define DO_CHDIR (1<<7)
529 define a list of possible SMB messages and their corresponding
530 functions. Any message that has a NULL function is unimplemented -
531 please feel free to contribute implementations!
533 static const struct smb_message_struct {
534 const char *name;
535 int (*fn)(connection_struct *conn, char *, char *, int, int);
536 int flags;
537 } smb_messages[256] = {
539 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
540 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
541 /* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
542 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
543 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
544 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
545 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
546 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
547 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
548 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
549 /* 0x0a */ { "SMBread",reply_read,AS_USER},
550 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
551 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
552 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
553 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
554 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
555 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
556 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
557 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
558 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
559 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
560 /* 0x15 */ { NULL, NULL, 0 },
561 /* 0x16 */ { NULL, NULL, 0 },
562 /* 0x17 */ { NULL, NULL, 0 },
563 /* 0x18 */ { NULL, NULL, 0 },
564 /* 0x19 */ { NULL, NULL, 0 },
565 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
566 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
567 /* 0x1c */ { "SMBreadBs",NULL,0 },
568 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
569 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
570 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
571 /* 0x20 */ { "SMBwritec",NULL,0},
572 /* 0x21 */ { NULL, NULL, 0 },
573 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
574 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
575 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
576 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
577 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
578 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
579 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
580 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
581 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
582 /* 0x2b */ { "SMBecho",reply_echo,0},
583 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
584 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
585 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
586 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
587 /* 0x30 */ { NULL, NULL, 0 },
588 /* 0x31 */ { NULL, NULL, 0 },
589 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
590 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
591 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
592 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
593 /* 0x36 */ { NULL, NULL, 0 },
594 /* 0x37 */ { NULL, NULL, 0 },
595 /* 0x38 */ { NULL, NULL, 0 },
596 /* 0x39 */ { NULL, NULL, 0 },
597 /* 0x3a */ { NULL, NULL, 0 },
598 /* 0x3b */ { NULL, NULL, 0 },
599 /* 0x3c */ { NULL, NULL, 0 },
600 /* 0x3d */ { NULL, NULL, 0 },
601 /* 0x3e */ { NULL, NULL, 0 },
602 /* 0x3f */ { NULL, NULL, 0 },
603 /* 0x40 */ { NULL, NULL, 0 },
604 /* 0x41 */ { NULL, NULL, 0 },
605 /* 0x42 */ { NULL, NULL, 0 },
606 /* 0x43 */ { NULL, NULL, 0 },
607 /* 0x44 */ { NULL, NULL, 0 },
608 /* 0x45 */ { NULL, NULL, 0 },
609 /* 0x46 */ { NULL, NULL, 0 },
610 /* 0x47 */ { NULL, NULL, 0 },
611 /* 0x48 */ { NULL, NULL, 0 },
612 /* 0x49 */ { NULL, NULL, 0 },
613 /* 0x4a */ { NULL, NULL, 0 },
614 /* 0x4b */ { NULL, NULL, 0 },
615 /* 0x4c */ { NULL, NULL, 0 },
616 /* 0x4d */ { NULL, NULL, 0 },
617 /* 0x4e */ { NULL, NULL, 0 },
618 /* 0x4f */ { NULL, NULL, 0 },
619 /* 0x50 */ { NULL, NULL, 0 },
620 /* 0x51 */ { NULL, NULL, 0 },
621 /* 0x52 */ { NULL, NULL, 0 },
622 /* 0x53 */ { NULL, NULL, 0 },
623 /* 0x54 */ { NULL, NULL, 0 },
624 /* 0x55 */ { NULL, NULL, 0 },
625 /* 0x56 */ { NULL, NULL, 0 },
626 /* 0x57 */ { NULL, NULL, 0 },
627 /* 0x58 */ { NULL, NULL, 0 },
628 /* 0x59 */ { NULL, NULL, 0 },
629 /* 0x5a */ { NULL, NULL, 0 },
630 /* 0x5b */ { NULL, NULL, 0 },
631 /* 0x5c */ { NULL, NULL, 0 },
632 /* 0x5d */ { NULL, NULL, 0 },
633 /* 0x5e */ { NULL, NULL, 0 },
634 /* 0x5f */ { NULL, NULL, 0 },
635 /* 0x60 */ { NULL, NULL, 0 },
636 /* 0x61 */ { NULL, NULL, 0 },
637 /* 0x62 */ { NULL, NULL, 0 },
638 /* 0x63 */ { NULL, NULL, 0 },
639 /* 0x64 */ { NULL, NULL, 0 },
640 /* 0x65 */ { NULL, NULL, 0 },
641 /* 0x66 */ { NULL, NULL, 0 },
642 /* 0x67 */ { NULL, NULL, 0 },
643 /* 0x68 */ { NULL, NULL, 0 },
644 /* 0x69 */ { NULL, NULL, 0 },
645 /* 0x6a */ { NULL, NULL, 0 },
646 /* 0x6b */ { NULL, NULL, 0 },
647 /* 0x6c */ { NULL, NULL, 0 },
648 /* 0x6d */ { NULL, NULL, 0 },
649 /* 0x6e */ { NULL, NULL, 0 },
650 /* 0x6f */ { NULL, NULL, 0 },
651 /* 0x70 */ { "SMBtcon",reply_tcon,0},
652 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
653 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
654 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
655 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
656 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
657 /* 0x76 */ { NULL, NULL, 0 },
658 /* 0x77 */ { NULL, NULL, 0 },
659 /* 0x78 */ { NULL, NULL, 0 },
660 /* 0x79 */ { NULL, NULL, 0 },
661 /* 0x7a */ { NULL, NULL, 0 },
662 /* 0x7b */ { NULL, NULL, 0 },
663 /* 0x7c */ { NULL, NULL, 0 },
664 /* 0x7d */ { NULL, NULL, 0 },
665 /* 0x7e */ { NULL, NULL, 0 },
666 /* 0x7f */ { NULL, NULL, 0 },
667 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
668 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
669 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
670 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
671 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
672 /* 0x85 */ { NULL, NULL, 0 },
673 /* 0x86 */ { NULL, NULL, 0 },
674 /* 0x87 */ { NULL, NULL, 0 },
675 /* 0x88 */ { NULL, NULL, 0 },
676 /* 0x89 */ { NULL, NULL, 0 },
677 /* 0x8a */ { NULL, NULL, 0 },
678 /* 0x8b */ { NULL, NULL, 0 },
679 /* 0x8c */ { NULL, NULL, 0 },
680 /* 0x8d */ { NULL, NULL, 0 },
681 /* 0x8e */ { NULL, NULL, 0 },
682 /* 0x8f */ { NULL, NULL, 0 },
683 /* 0x90 */ { NULL, NULL, 0 },
684 /* 0x91 */ { NULL, NULL, 0 },
685 /* 0x92 */ { NULL, NULL, 0 },
686 /* 0x93 */ { NULL, NULL, 0 },
687 /* 0x94 */ { NULL, NULL, 0 },
688 /* 0x95 */ { NULL, NULL, 0 },
689 /* 0x96 */ { NULL, NULL, 0 },
690 /* 0x97 */ { NULL, NULL, 0 },
691 /* 0x98 */ { NULL, NULL, 0 },
692 /* 0x99 */ { NULL, NULL, 0 },
693 /* 0x9a */ { NULL, NULL, 0 },
694 /* 0x9b */ { NULL, NULL, 0 },
695 /* 0x9c */ { NULL, NULL, 0 },
696 /* 0x9d */ { NULL, NULL, 0 },
697 /* 0x9e */ { NULL, NULL, 0 },
698 /* 0x9f */ { NULL, NULL, 0 },
699 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
700 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
701 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
702 /* 0xa3 */ { NULL, NULL, 0 },
703 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
704 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
705 /* 0xa6 */ { NULL, NULL, 0 },
706 /* 0xa7 */ { NULL, NULL, 0 },
707 /* 0xa8 */ { NULL, NULL, 0 },
708 /* 0xa9 */ { NULL, NULL, 0 },
709 /* 0xaa */ { NULL, NULL, 0 },
710 /* 0xab */ { NULL, NULL, 0 },
711 /* 0xac */ { NULL, NULL, 0 },
712 /* 0xad */ { NULL, NULL, 0 },
713 /* 0xae */ { NULL, NULL, 0 },
714 /* 0xaf */ { NULL, NULL, 0 },
715 /* 0xb0 */ { NULL, NULL, 0 },
716 /* 0xb1 */ { NULL, NULL, 0 },
717 /* 0xb2 */ { NULL, NULL, 0 },
718 /* 0xb3 */ { NULL, NULL, 0 },
719 /* 0xb4 */ { NULL, NULL, 0 },
720 /* 0xb5 */ { NULL, NULL, 0 },
721 /* 0xb6 */ { NULL, NULL, 0 },
722 /* 0xb7 */ { NULL, NULL, 0 },
723 /* 0xb8 */ { NULL, NULL, 0 },
724 /* 0xb9 */ { NULL, NULL, 0 },
725 /* 0xba */ { NULL, NULL, 0 },
726 /* 0xbb */ { NULL, NULL, 0 },
727 /* 0xbc */ { NULL, NULL, 0 },
728 /* 0xbd */ { NULL, NULL, 0 },
729 /* 0xbe */ { NULL, NULL, 0 },
730 /* 0xbf */ { NULL, NULL, 0 },
731 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
732 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
733 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
734 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
735 /* 0xc4 */ { NULL, NULL, 0 },
736 /* 0xc5 */ { NULL, NULL, 0 },
737 /* 0xc6 */ { NULL, NULL, 0 },
738 /* 0xc7 */ { NULL, NULL, 0 },
739 /* 0xc8 */ { NULL, NULL, 0 },
740 /* 0xc9 */ { NULL, NULL, 0 },
741 /* 0xca */ { NULL, NULL, 0 },
742 /* 0xcb */ { NULL, NULL, 0 },
743 /* 0xcc */ { NULL, NULL, 0 },
744 /* 0xcd */ { NULL, NULL, 0 },
745 /* 0xce */ { NULL, NULL, 0 },
746 /* 0xcf */ { NULL, NULL, 0 },
747 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
748 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
749 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
750 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
751 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
752 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
753 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
754 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
755 /* 0xd8 */ { NULL, NULL, 0 },
756 /* 0xd9 */ { NULL, NULL, 0 },
757 /* 0xda */ { NULL, NULL, 0 },
758 /* 0xdb */ { NULL, NULL, 0 },
759 /* 0xdc */ { NULL, NULL, 0 },
760 /* 0xdd */ { NULL, NULL, 0 },
761 /* 0xde */ { NULL, NULL, 0 },
762 /* 0xdf */ { NULL, NULL, 0 },
763 /* 0xe0 */ { NULL, NULL, 0 },
764 /* 0xe1 */ { NULL, NULL, 0 },
765 /* 0xe2 */ { NULL, NULL, 0 },
766 /* 0xe3 */ { NULL, NULL, 0 },
767 /* 0xe4 */ { NULL, NULL, 0 },
768 /* 0xe5 */ { NULL, NULL, 0 },
769 /* 0xe6 */ { NULL, NULL, 0 },
770 /* 0xe7 */ { NULL, NULL, 0 },
771 /* 0xe8 */ { NULL, NULL, 0 },
772 /* 0xe9 */ { NULL, NULL, 0 },
773 /* 0xea */ { NULL, NULL, 0 },
774 /* 0xeb */ { NULL, NULL, 0 },
775 /* 0xec */ { NULL, NULL, 0 },
776 /* 0xed */ { NULL, NULL, 0 },
777 /* 0xee */ { NULL, NULL, 0 },
778 /* 0xef */ { NULL, NULL, 0 },
779 /* 0xf0 */ { NULL, NULL, 0 },
780 /* 0xf1 */ { NULL, NULL, 0 },
781 /* 0xf2 */ { NULL, NULL, 0 },
782 /* 0xf3 */ { NULL, NULL, 0 },
783 /* 0xf4 */ { NULL, NULL, 0 },
784 /* 0xf5 */ { NULL, NULL, 0 },
785 /* 0xf6 */ { NULL, NULL, 0 },
786 /* 0xf7 */ { NULL, NULL, 0 },
787 /* 0xf8 */ { NULL, NULL, 0 },
788 /* 0xf9 */ { NULL, NULL, 0 },
789 /* 0xfa */ { NULL, NULL, 0 },
790 /* 0xfb */ { NULL, NULL, 0 },
791 /* 0xfc */ { NULL, NULL, 0 },
792 /* 0xfd */ { NULL, NULL, 0 },
793 /* 0xfe */ { NULL, NULL, 0 },
794 /* 0xff */ { NULL, NULL, 0 }
798 /*******************************************************************
799 Dump a packet to a file.
800 ********************************************************************/
802 static void smb_dump(const char *name, int type, char *data, ssize_t len)
804 int fd, i;
805 pstring fname;
806 if (DEBUGLEVEL < 50) return;
808 if (len < 4) len = smb_len(data)+4;
809 for (i=1;i<100;i++) {
810 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
811 type ? "req" : "resp");
812 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
813 if (fd != -1 || errno != EEXIST) break;
815 if (fd != -1) {
816 ssize_t ret = write(fd, data, len);
817 if (ret != len)
818 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
819 close(fd);
820 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
825 /****************************************************************************
826 Do a switch on the message type, and return the response size
827 ****************************************************************************/
829 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
831 static pid_t pid= (pid_t)-1;
832 int outsize = 0;
833 extern uint16 global_smbpid;
835 type &= 0xff;
837 if (pid == (pid_t)-1)
838 pid = sys_getpid();
840 errno = 0;
841 last_message = type;
843 /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
844 if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
845 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
846 exit_server("Non-SMB packet");
847 return(-1);
850 /* yuck! this is an interim measure before we get rid of our
851 current inbuf/outbuf system */
852 global_smbpid = SVAL(inbuf,smb_pid);
854 if (smb_messages[type].fn == NULL) {
855 DEBUG(0,("Unknown message type %d!\n",type));
856 smb_dump("Unknown", 1, inbuf, size);
857 outsize = reply_unknown(inbuf,outbuf);
858 } else {
859 int flags = smb_messages[type].flags;
860 static uint16 last_session_tag = UID_FIELD_INVALID;
861 /* In share mode security we must ignore the vuid. */
862 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
863 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
865 DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn));
867 smb_dump(smb_fn_name(type), 1, inbuf, size);
868 if(global_oplock_break) {
869 if(flags & QUEUE_IN_OPLOCK) {
871 * Queue this message as we are the process of an oplock break.
874 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
875 DEBUGADD( 2, ( "oplock break state.\n" ) );
877 push_oplock_pending_smb_message( inbuf, size );
878 return -1;
882 /* Ensure this value is replaced in the incoming packet. */
883 SSVAL(inbuf,smb_uid,session_tag);
886 * Ensure the correct username is in current_user_info.
887 * This is a really ugly bugfix for problems with
888 * multiple session_setup_and_X's being done and
889 * allowing %U and %G substitutions to work correctly.
890 * There is a reason this code is done here, don't
891 * move it unless you know what you're doing... :-).
892 * JRA.
895 if (session_tag != last_session_tag) {
896 user_struct *vuser = NULL;
898 last_session_tag = session_tag;
899 if(session_tag != UID_FIELD_INVALID)
900 vuser = get_valid_user_struct(session_tag);
901 if(vuser != NULL)
902 set_current_user_info(&vuser->user);
905 /* does this protocol need to be run as root? */
906 if (!(flags & AS_USER))
907 change_to_root_user();
909 /* does this protocol need a valid tree connection? */
910 if ((flags & AS_USER) && !conn)
911 return ERROR_DOS(ERRSRV, ERRinvnid);
914 /* does this protocol need to be run as the connected user? */
915 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
916 if (flags & AS_GUEST)
917 flags &= ~AS_USER;
918 else
919 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
922 /* this code is to work around a bug is MS client 3 without
923 introducing a security hole - it needs to be able to do
924 print queue checks as guest if it isn't logged in properly */
925 if (flags & AS_USER)
926 flags &= ~AS_GUEST;
928 /* does it need write permission? */
929 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
930 return(ERROR_DOS(ERRSRV,ERRaccess));
932 /* ipc services are limited */
933 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
934 return(ERROR_DOS(ERRSRV,ERRaccess));
936 /* load service specific parameters */
937 if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False)))
938 return(ERROR_DOS(ERRSRV,ERRaccess));
940 /* does this protocol need to be run as guest? */
941 if ((flags & AS_GUEST) && (!change_to_guest() ||
942 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
943 return(ERROR_DOS(ERRSRV,ERRaccess));
945 last_inbuf = inbuf;
947 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
950 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
952 return(outsize);
956 /****************************************************************************
957 Construct a reply to the incoming packet.
958 ****************************************************************************/
960 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
962 int type = CVAL(inbuf,smb_com);
963 int outsize = 0;
964 int msg_type = CVAL(inbuf,0);
966 GetTimeOfDay(&smb_last_time);
968 chain_size = 0;
969 file_chain_reset();
970 reset_chain_p();
972 if (msg_type != 0)
973 return(reply_special(inbuf,outbuf));
975 construct_reply_common(inbuf, outbuf);
977 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
979 outsize += chain_size;
981 if(outsize > 4)
982 smb_setlen(outbuf,outsize - 4);
983 return(outsize);
986 /****************************************************************************
987 Keep track of the number of running smbd's. This functionality is used to
988 'hard' limit Samba overhead on resource constrained systems.
989 ****************************************************************************/
991 static BOOL process_count_update_successful = False;
993 static int32 increment_smbd_process_count(void)
995 int32 total_smbds;
997 if (lp_max_smbd_processes()) {
998 total_smbds = 0;
999 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1000 return 1;
1001 process_count_update_successful = True;
1002 return total_smbds + 1;
1004 return 1;
1007 void decrement_smbd_process_count(void)
1009 int32 total_smbds;
1011 if (lp_max_smbd_processes() && process_count_update_successful) {
1012 total_smbds = 1;
1013 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1017 static BOOL smbd_process_limit(void)
1019 int32 total_smbds;
1021 if (lp_max_smbd_processes()) {
1023 /* Always add one to the smbd process count, as exit_server() always
1024 * subtracts one.
1027 if (!conn_tdb_ctx()) {
1028 DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1029 set. Ignoring max smbd restriction.\n"));
1030 return False;
1033 total_smbds = increment_smbd_process_count();
1034 return total_smbds > lp_max_smbd_processes();
1036 else
1037 return False;
1040 /****************************************************************************
1041 Process an smb from the client - split out from the smbd_process() code so
1042 it can be used by the oplock break code.
1043 ****************************************************************************/
1045 void process_smb(char *inbuf, char *outbuf)
1047 static int trans_num;
1048 int msg_type = CVAL(inbuf,0);
1049 int32 len = smb_len(inbuf);
1050 int nread = len + 4;
1052 DO_PROFILE_INC(smb_count);
1054 if (trans_num == 0) {
1055 /* on the first packet, check the global hosts allow/ hosts
1056 deny parameters before doing any parsing of the packet
1057 passed to us by the client. This prevents attacks on our
1058 parsing code from hosts not in the hosts allow list */
1059 if (smbd_process_limit() ||
1060 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1061 /* send a negative session response "not listening on calling name" */
1062 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1063 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1064 (void)send_smb(smbd_server_fd(),(char *)buf);
1065 exit_server("connection denied");
1069 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1070 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1072 if (msg_type == 0)
1073 show_msg(inbuf);
1074 else if(msg_type == SMBkeepalive)
1075 return; /* Keepalive packet. */
1077 nread = construct_reply(inbuf,outbuf,nread,max_send);
1079 if(nread > 0) {
1080 if (CVAL(outbuf,0) == 0)
1081 show_msg(outbuf);
1083 if (nread != smb_len(outbuf) + 4) {
1084 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1085 nread, smb_len(outbuf)));
1086 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1087 exit_server("process_smb: send_smb failed.");
1090 trans_num++;
1093 /****************************************************************************
1094 Return a string containing the function name of a SMB command.
1095 ****************************************************************************/
1097 const char *smb_fn_name(int type)
1099 const char *unknown_name = "SMBunknown";
1101 if (smb_messages[type].name == NULL)
1102 return(unknown_name);
1104 return(smb_messages[type].name);
1107 /****************************************************************************
1108 Helper functions for contruct_reply.
1109 ****************************************************************************/
1111 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
1113 void remove_from_common_flags2(uint32 v)
1115 common_flags2 &= ~v;
1118 void construct_reply_common(char *inbuf,char *outbuf)
1120 memset(outbuf,'\0',smb_size);
1122 set_message(outbuf,0,0,True);
1123 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1125 memcpy(outbuf+4,inbuf+4,4);
1126 SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1127 SCVAL(outbuf,smb_reh,0);
1128 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1129 SSVAL(outbuf,smb_flg2,
1130 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1131 common_flags2);
1133 SSVAL(outbuf,smb_err,SMB_SUCCESS);
1134 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1135 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1136 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1137 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1140 /****************************************************************************
1141 Construct a chained reply and add it to the already made reply
1142 ****************************************************************************/
1144 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1146 static char *orig_inbuf;
1147 static char *orig_outbuf;
1148 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1149 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1150 char *inbuf2, *outbuf2;
1151 int outsize2;
1152 char inbuf_saved[smb_wct];
1153 char outbuf_saved[smb_wct];
1154 int wct = CVAL(outbuf,smb_wct);
1155 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
1157 /* maybe its not chained */
1158 if (smb_com2 == 0xFF) {
1159 SCVAL(outbuf,smb_vwv0,0xFF);
1160 return outsize;
1163 if (chain_size == 0) {
1164 /* this is the first part of the chain */
1165 orig_inbuf = inbuf;
1166 orig_outbuf = outbuf;
1170 * The original Win95 redirector dies on a reply to
1171 * a lockingX and read chain unless the chain reply is
1172 * 4 byte aligned. JRA.
1175 outsize = (outsize + 3) & ~3;
1177 /* we need to tell the client where the next part of the reply will be */
1178 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1179 SCVAL(outbuf,smb_vwv0,smb_com2);
1181 /* remember how much the caller added to the chain, only counting stuff
1182 after the parameter words */
1183 chain_size += outsize - smb_wct;
1185 /* work out pointers into the original packets. The
1186 headers on these need to be filled in */
1187 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1188 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1190 /* remember the original command type */
1191 smb_com1 = CVAL(orig_inbuf,smb_com);
1193 /* save the data which will be overwritten by the new headers */
1194 memcpy(inbuf_saved,inbuf2,smb_wct);
1195 memcpy(outbuf_saved,outbuf2,smb_wct);
1197 /* give the new packet the same header as the last part of the SMB */
1198 memmove(inbuf2,inbuf,smb_wct);
1200 /* create the in buffer */
1201 SCVAL(inbuf2,smb_com,smb_com2);
1203 /* create the out buffer */
1204 construct_reply_common(inbuf2, outbuf2);
1206 DEBUG(3,("Chained message\n"));
1207 show_msg(inbuf2);
1209 /* process the request */
1210 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1211 bufsize-chain_size);
1213 /* copy the new reply and request headers over the old ones, but
1214 preserve the smb_com field */
1215 memmove(orig_outbuf,outbuf2,smb_wct);
1216 SCVAL(orig_outbuf,smb_com,smb_com1);
1218 /* restore the saved data, being careful not to overwrite any
1219 data from the reply header */
1220 memcpy(inbuf2,inbuf_saved,smb_wct);
1223 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1224 if (ofs < 0) ofs = 0;
1225 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1228 return outsize2;
1231 /****************************************************************************
1232 Setup the needed select timeout.
1233 ****************************************************************************/
1235 static int setup_select_timeout(void)
1237 int select_timeout;
1238 int t;
1240 select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1241 select_timeout *= 1000;
1243 t = change_notify_timeout();
1244 if (t != -1)
1245 select_timeout = MIN(select_timeout, t*1000);
1247 if (print_notify_messages_pending())
1248 select_timeout = MIN(select_timeout, 1000);
1250 return select_timeout;
1253 /****************************************************************************
1254 Check if services need reloading.
1255 ****************************************************************************/
1257 void check_reload(int t)
1259 static time_t last_smb_conf_reload_time = 0;
1260 static time_t last_load_printers_reload_time = 0;
1261 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1263 if(last_smb_conf_reload_time == 0) {
1264 last_smb_conf_reload_time = t;
1265 /* Our printing subsystem might not be ready at smbd start up.
1266 Then no printer is available till the first printers check
1267 is performed. A lower initial interval circumvents this. */
1268 if ( printcap_cache_time > 60 )
1269 last_load_printers_reload_time = t - printcap_cache_time + 60;
1270 else
1271 last_load_printers_reload_time = t;
1274 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1275 reload_services(True);
1276 reload_after_sighup = False;
1277 last_smb_conf_reload_time = t;
1280 /* 'printcap cache time = 0' disable the feature */
1282 if ( printcap_cache_time != 0 )
1284 /* see if it's time to reload or if the clock has been set back */
1286 if ( (t >= last_load_printers_reload_time+printcap_cache_time)
1287 || (t-last_load_printers_reload_time < 0) )
1289 DEBUG( 3,( "Printcap cache time expired.\n"));
1290 remove_stale_printers();
1291 load_printers();
1292 last_load_printers_reload_time = t;
1297 /****************************************************************************
1298 Process any timeout housekeeping. Return False if the caller should exit.
1299 ****************************************************************************/
1301 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1303 static time_t last_keepalive_sent_time = 0;
1304 static time_t last_idle_closed_check = 0;
1305 time_t t;
1306 BOOL allidle = True;
1307 extern int keepalive;
1309 if (smb_read_error == READ_EOF) {
1310 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1311 return False;
1314 if (smb_read_error == READ_ERROR) {
1315 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1316 strerror(errno)));
1317 return False;
1320 if (smb_read_error == READ_BAD_SIG) {
1321 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1322 return False;
1325 *last_timeout_processing_time = t = time(NULL);
1327 if(last_keepalive_sent_time == 0)
1328 last_keepalive_sent_time = t;
1330 if(last_idle_closed_check == 0)
1331 last_idle_closed_check = t;
1333 /* become root again if waiting */
1334 change_to_root_user();
1336 /* run all registered idle events */
1337 smb_run_idle_events(t);
1339 /* check if we need to reload services */
1340 check_reload(t);
1342 /* automatic timeout if all connections are closed */
1343 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1344 DEBUG( 2, ( "Closing idle connection\n" ) );
1345 return False;
1346 } else {
1347 last_idle_closed_check = t;
1350 if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1351 extern struct auth_context *negprot_global_auth_context;
1352 if (!send_keepalive(smbd_server_fd())) {
1353 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1354 return False;
1357 /* send a keepalive for a password server or the like.
1358 This is attached to the auth_info created in the
1359 negprot */
1360 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
1361 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1363 negprot_global_auth_context->challenge_set_method->send_keepalive
1364 (&negprot_global_auth_context->challenge_set_method->private_data);
1367 last_keepalive_sent_time = t;
1370 /* check for connection timeouts */
1371 allidle = conn_idle_all(t, deadtime);
1373 if (allidle && conn_num_open()>0) {
1374 DEBUG(2,("Closing idle connection 2.\n"));
1375 return False;
1378 if(global_machine_password_needs_changing &&
1379 /* for ADS we need to do a regular ADS password change, not a domain
1380 password change */
1381 lp_security() == SEC_DOMAIN) {
1383 unsigned char trust_passwd_hash[16];
1384 time_t lct;
1387 * We're in domain level security, and the code that
1388 * read the machine password flagged that the machine
1389 * password needs changing.
1393 * First, open the machine password file with an exclusive lock.
1396 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1397 DEBUG(0,("process: unable to lock the machine account password for \
1398 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1399 return True;
1402 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1403 DEBUG(0,("process: unable to read the machine account password for \
1404 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1405 secrets_lock_trust_account_password(lp_workgroup(), False);
1406 return True;
1410 * Make sure someone else hasn't already done this.
1413 if(t < lct + lp_machine_password_timeout()) {
1414 global_machine_password_needs_changing = False;
1415 secrets_lock_trust_account_password(lp_workgroup(), False);
1416 return True;
1419 /* always just contact the PDC here */
1421 change_trust_account_password( lp_workgroup(), NULL);
1422 global_machine_password_needs_changing = False;
1423 secrets_lock_trust_account_password(lp_workgroup(), False);
1427 * Check to see if we have any blocking locks
1428 * outstanding on the queue.
1430 process_blocking_lock_queue(t);
1432 /* update printer queue caches if necessary */
1434 update_monitored_printq_cache();
1437 * Check to see if we have any change notifies
1438 * outstanding on the queue.
1440 process_pending_change_notify_queue(t);
1443 * Now we are root, check if the log files need pruning.
1444 * Force a log file check.
1446 force_check_log_size();
1447 check_log_size();
1449 /* Send any queued printer notify message to interested smbd's. */
1451 print_notify_send_messages(0);
1454 * Modify the select timeout depending upon
1455 * what we have remaining in our queues.
1458 *select_timeout = setup_select_timeout();
1460 return True;
1463 /****************************************************************************
1464 process commands from the client
1465 ****************************************************************************/
1467 void smbd_process(void)
1469 extern int smb_echo_count;
1470 time_t last_timeout_processing_time = time(NULL);
1471 unsigned int num_smbs = 0;
1472 const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN;
1474 InBuffer = (char *)malloc(total_buffer_size);
1475 OutBuffer = (char *)malloc(total_buffer_size);
1476 if ((InBuffer == NULL) || (OutBuffer == NULL))
1477 return;
1479 #if defined(DEVELOPER)
1480 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1481 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1482 #endif
1484 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1486 while (True) {
1487 int deadtime = lp_deadtime()*60;
1488 int select_timeout = setup_select_timeout();
1489 int num_echos;
1491 if (deadtime <= 0)
1492 deadtime = DEFAULT_SMBD_TIMEOUT;
1494 errno = 0;
1496 /* free up temporary memory */
1497 lp_talloc_free();
1498 main_loop_talloc_free();
1500 /* run all registered idle events */
1501 smb_run_idle_events(time(NULL));
1504 /* Did someone ask for immediate checks on things like blocking locks ? */
1505 if (select_timeout == 0) {
1506 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1507 return;
1508 num_smbs = 0; /* Reset smb counter. */
1511 #if defined(DEVELOPER)
1512 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1513 #endif
1515 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1516 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1517 return;
1518 num_smbs = 0; /* Reset smb counter. */
1522 * Ensure we do timeout processing if the SMB we just got was
1523 * only an echo request. This allows us to set the select
1524 * timeout in 'receive_message_or_smb()' to any value we like
1525 * without worrying that the client will send echo requests
1526 * faster than the select timeout, thus starving out the
1527 * essential processing (change notify, blocking locks) that
1528 * the timeout code does. JRA.
1530 num_echos = smb_echo_count;
1532 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1534 process_smb(InBuffer, OutBuffer);
1536 if (smb_echo_count != num_echos) {
1537 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1538 return;
1539 num_smbs = 0; /* Reset smb counter. */
1542 num_smbs++;
1545 * If we are getting smb requests in a constant stream
1546 * with no echos, make sure we attempt timeout processing
1547 * every select_timeout milliseconds - but only check for this
1548 * every 200 smb requests.
1551 if ((num_smbs % 200) == 0) {
1552 time_t new_check_time = time(NULL);
1553 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1554 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1555 return;
1556 num_smbs = 0; /* Reset smb counter. */
1557 last_timeout_processing_time = new_check_time; /* Reset time. */
1561 /* The timeout_processing function isn't run nearly
1562 often enough to implement 'max log size' without
1563 overrunning the size of the file by many megabytes.
1564 This is especially true if we are running at debug
1565 level 10. Checking every 50 SMBs is a nice
1566 tradeoff of performance vs log file size overrun. */
1568 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1569 change_to_root_user();
1570 check_log_size();