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.
23 struct timeval smb_last_time
;
25 static char *InBuffer
= NULL
;
26 char *OutBuffer
= NULL
;
27 char *last_inbuf
= NULL
;
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
;
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.
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 /****************************************************************************
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
);
80 /****************************************************************************
81 Function to push a message onto the tail of a linked list of smb messages ready
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
));
92 DEBUG(0,("push_message: malloc fail (1)\n"));
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"));
106 msg
->msg_time
= *ptv
;
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
);
118 if (qt
== OPLOCK_QUEUE
) {
119 DLIST_ADD_END(smb_oplock_queue
, msg
, tmp_msg
);
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" ));
131 /****************************************************************************
132 Function to push an oplock smb message onto a linked list of local smb messages ready
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);
140 /* Push the MID of this packet on the signing queue. */
141 srv_defer_sign_response(SVAL(buf
,smb_mid
));
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
);
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
;
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",
182 pml
->msg_time
.tv_sec
= 0;
183 pml
->msg_time
.tv_usec
= 0;
184 DLIST_PROMOTE(smb_sharing_violation_queue
, pml
);
189 DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
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
) {
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
) {
223 /****************************************************************************
224 Function to push a sharing violation open smb message onto a linked list of local smb messages ready
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
);
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
);
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
298 Returns False on timeout or error.
301 The timeout is in milliseconds
302 ****************************************************************************/
304 static BOOL
receive_message_or_smb(char *buffer
, int buffer_len
, int timeout
)
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.
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"));
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) {
358 tdif
= usec_time_diff(&msg
->msg_time
, &tv
);
360 /* Timed out. Schedule...*/
362 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
364 /* Make a more accurate select timeout. */
365 to
.tv_sec
= tdif
/ 1000000;
366 to
.tv_usec
= tdif
% 1000000;
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
));
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"));
384 * Setup the select read fd set.
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.
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
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.
430 /* something is wrong. Maybe the socket is dead? */
431 smb_read_error
= READ_ERROR
;
435 /* Did we timeout ? */
437 smb_read_error
= READ_TIMEOUT
;
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.
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
)
470 ret
= receive_message_or_smb(inbuf
,bufsize
,timeout
);
472 got_keepalive
= (ret
&& (CVAL(inbuf
,0) == SMBkeepalive
));
473 } while (ret
&& got_keepalive
);
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
483 ****************************************************************************/
485 void respond_to_all_remaining_local_messages(void)
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() ));
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
));
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
{
535 int (*fn
)(connection_struct
*conn
, char *, char *, int, int);
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
)
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;
816 ssize_t ret
= write(fd
, data
, len
);
818 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret
));
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;
833 extern uint16 global_smbpid
;
837 if (pid
== (pid_t
)-1)
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");
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
);
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
);
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... :-).
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
);
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
)
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 */
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
));
947 outsize
= smb_messages
[type
].fn(conn
, inbuf
,outbuf
,size
,bufsize
);
950 smb_dump(smb_fn_name(type
), 0, outbuf
, 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
);
964 int msg_type
= CVAL(inbuf
,0);
966 GetTimeOfDay(&smb_last_time
);
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
;
982 smb_setlen(outbuf
,outsize
- 4);
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)
997 if (lp_max_smbd_processes()) {
999 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds
, 1) == -1)
1001 process_count_update_successful
= True
;
1002 return total_smbds
+ 1;
1007 void decrement_smbd_process_count(void)
1011 if (lp_max_smbd_processes() && process_count_update_successful
) {
1013 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds
, -1);
1017 static BOOL
smbd_process_limit(void)
1021 if (lp_max_smbd_processes()) {
1023 /* Always add one to the smbd process count, as exit_server() always
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"));
1033 total_smbds
= increment_smbd_process_count();
1034 return total_smbds
> lp_max_smbd_processes();
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
) );
1074 else if(msg_type
== SMBkeepalive
)
1075 return; /* Keepalive packet. */
1077 nread
= construct_reply(inbuf
,outbuf
,nread
,max_send
);
1080 if (CVAL(outbuf
,0) == 0)
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.");
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
) |
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
;
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);
1163 if (chain_size
== 0) {
1164 /* this is the first part of the chain */
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"));
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
);
1231 /****************************************************************************
1232 Setup the needed select timeout.
1233 ****************************************************************************/
1235 static int setup_select_timeout(void)
1240 select_timeout
= blocking_locks_timeout(SMBD_SELECT_TIMEOUT
);
1241 select_timeout
*= 1000;
1243 t
= change_notify_timeout();
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;
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();
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;
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"));
1314 if (smb_read_error
== READ_ERROR
) {
1315 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1320 if (smb_read_error
== READ_BAD_SIG
) {
1321 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
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 */
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" ) );
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" ) );
1357 /* send a keepalive for a password server or the like.
1358 This is attached to the auth_info created in the
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"));
1378 if(global_machine_password_needs_changing
&&
1379 /* for ADS we need to do a regular ADS password change, not a domain
1381 lp_security() == SEC_DOMAIN
) {
1383 unsigned char trust_passwd_hash
[16];
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() ));
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
);
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
);
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();
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();
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
))
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
);
1484 max_recv
= MIN(lp_maxxmit(),BUFFER_SIZE
);
1487 int deadtime
= lp_deadtime()*60;
1488 int select_timeout
= setup_select_timeout();
1492 deadtime
= DEFAULT_SMBD_TIMEOUT
;
1496 /* free up temporary memory */
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
))
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
);
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
))
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
))
1539 num_smbs
= 0; /* Reset smb counter. */
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
))
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();