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