r1154: Change default setting for case sensitivity to "auto". If set to auto
[amitay/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 struct timeval smb_last_time;
24
25 static char *InBuffer = NULL;
26 char *OutBuffer = NULL;
27 char *last_inbuf = NULL;
28
29 /* 
30  * Size of data we can send to client. Set
31  *  by the client for all protocols above CORE.
32  *  Set by us for CORE protocol.
33  */
34 int max_send = BUFFER_SIZE;
35 /*
36  * Size of the data we can receive. Set by us.
37  * Can be modified by the max xmit parameter.
38  */
39 int max_recv = BUFFER_SIZE;
40
41 extern int last_message;
42 extern int global_oplock_break;
43 extern userdom_struct current_user_info;
44 extern int smb_read_error;
45 SIG_ATOMIC_T reload_after_sighup = 0;
46 SIG_ATOMIC_T got_sig_term = 0;
47 BOOL global_machine_password_needs_changing = False;
48 extern int max_send;
49
50 /****************************************************************************
51  Function to return the current request mid from Inbuffer.
52 ****************************************************************************/
53
54 uint16 get_current_mid(void)
55 {
56         return SVAL(InBuffer,smb_mid);
57 }
58
59 /****************************************************************************
60  structure to hold a linked list of queued messages.
61  for processing.
62 ****************************************************************************/
63
64 static struct pending_message_list *smb_oplock_queue;
65 static struct pending_message_list *smb_sharing_violation_queue;
66
67 enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE };
68
69 /****************************************************************************
70  Free up a message.
71 ****************************************************************************/
72
73 static void free_queued_message(struct pending_message_list *msg)
74 {
75         data_blob_free(&msg->buf);
76         data_blob_free(&msg->private_data);
77         SAFE_FREE(msg);
78 }
79
80 /****************************************************************************
81  Function to push a message onto the tail of a linked list of smb messages ready
82  for processing.
83 ****************************************************************************/
84
85 static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private, size_t private_len)
86 {
87         struct pending_message_list *tmp_msg;
88         struct pending_message_list *msg = (struct pending_message_list *)
89                                malloc(sizeof(struct pending_message_list));
90
91         if(msg == NULL) {
92                 DEBUG(0,("push_message: malloc fail (1)\n"));
93                 return False;
94         }
95
96         memset(msg,'\0',sizeof(*msg));
97
98         msg->buf = data_blob(buf, msg_len);
99         if(msg->buf.data == NULL) {
100                 DEBUG(0,("push_message: malloc fail (2)\n"));
101                 SAFE_FREE(msg);
102                 return False;
103         }
104
105         if (ptv) {
106                 msg->msg_time = *ptv;
107         }
108
109         if (private) {
110                 msg->private_data = data_blob(private, private_len);
111                 if (msg->private_data.data == NULL) {
112                         DEBUG(0,("push_message: malloc fail (3)\n"));
113                         data_blob_free(&msg->buf);
114                         SAFE_FREE(msg);
115                 }
116         }
117
118         if (qt == OPLOCK_QUEUE) {
119                 DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
120         } else {
121                 DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
122         }
123
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" ));
127
128         return True;
129 }
130
131 /****************************************************************************
132  Function to push an oplock smb message onto a linked list of local smb messages ready
133  for processing.
134 ****************************************************************************/
135
136 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
137 {
138         BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
139         if (ret) {
140                 /* Push the MID of this packet on the signing queue. */
141                 srv_defer_sign_response(SVAL(buf,smb_mid));
142         }
143         return ret;
144 }
145
146 /****************************************************************************
147  Function to delete a sharing violation open message by mid.
148 ****************************************************************************/
149
150 void remove_sharing_violation_open_smb_message(uint16 mid)
151 {
152         struct pending_message_list *pml;
153
154         for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
155                 if (mid == SVAL(pml->buf.data,smb_mid)) {
156                         DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
157                                 (unsigned int)mid, (unsigned int)pml->buf.length ));
158                         DLIST_REMOVE(smb_sharing_violation_queue, pml);
159                         free_queued_message(pml);
160                         return;
161                 }
162         }
163 }
164
165 /****************************************************************************
166  Move a sharing violation open retry message to the front of the list and
167  schedule it for immediate processing.
168 ****************************************************************************/
169
170 void schedule_sharing_violation_open_smb_message(uint16 mid)
171 {
172         struct pending_message_list *pml;
173         int i = 0;
174
175         for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
176                 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
177                 DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
178                         (unsigned int)msg_mid ));
179                 if (mid == msg_mid) {
180                         DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
181                                 mid ));
182                         pml->msg_time.tv_sec = 0;
183                         pml->msg_time.tv_usec = 0;
184                         DLIST_PROMOTE(smb_sharing_violation_queue, pml);
185                         return;
186                 }
187         }
188
189         DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
190                 mid ));
191 }
192
193 /****************************************************************************
194  Return true if this mid is on the deferred queue.
195 ****************************************************************************/
196
197 BOOL open_was_deferred(uint16 mid)
198 {
199         struct pending_message_list *pml;
200         for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
201                 if (SVAL(pml->buf.data,smb_mid) == mid) {
202                         return True;
203                 }
204         }
205         return False;
206 }
207
208 /****************************************************************************
209  Return the message queued by this mid.
210 ****************************************************************************/
211
212 struct pending_message_list *get_open_deferred_message(uint16 mid)
213 {
214         struct pending_message_list *pml;
215         for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
216                 if (SVAL(pml->buf.data,smb_mid) == mid) {
217                         return pml;
218                 }
219         }
220         return NULL;
221 }
222
223 /****************************************************************************
224  Function to push a sharing violation open smb message onto a linked list of local smb messages ready
225  for processing.
226 ****************************************************************************/
227
228 BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private, size_t priv_len)
229 {
230         uint16 mid = SVAL(InBuffer,smb_mid);
231         struct timeval tv;
232         SMB_BIG_INT tdif;
233
234         tv = *ptv;
235         tdif = tv.tv_sec;
236         tdif *= 1000000;
237         tdif += tv.tv_usec;
238
239         /* Add on the timeout. */
240         tdif += SHARING_VIOLATION_USEC_WAIT;
241         
242         tv.tv_sec = tdif / 1000000;
243         tv.tv_usec = tdif % 1000000;
244         
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));
248
249         return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer,
250                         smb_len(InBuffer)+4, &tv, private, priv_len);
251 }
252
253 /****************************************************************************
254  Do all async processing in here. This includes UDB oplock messages, kernel
255  oplock messages, change notify events etc.
256 ****************************************************************************/
257
258 static void async_processing(char *buffer, int buffer_len)
259 {
260         DEBUG(10,("async_processing: Doing async processing.\n"));
261
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);
265         }
266
267         if (got_sig_term) {
268                 exit_server("Caught TERM signal");
269         }
270
271         /* check for async change notify events */
272         process_pending_change_notify_queue(0);
273
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;
280         }
281 }
282
283 /****************************************************************************
284   Do a select on an two fd's - with timeout. 
285
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()
289
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.
293
294   If the first smbfd is ready then read an smb from it.
295   if the second (loopback UDP) fd is ready then read a message
296   from it and setup the buffer header to identify the length
297   and from address.
298   Returns False on timeout or error.
299   Else returns True.
300
301 The timeout is in milliseconds
302 ****************************************************************************/
303
304 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
305 {
306         fd_set fds;
307         int selrtn;
308         struct timeval to;
309         struct timeval *pto;
310         int maxfd;
311
312         smb_read_error = 0;
313
314  again:
315
316         to.tv_sec = timeout / 1000;
317         to.tv_usec = (timeout % 1000) * 1000;
318         pto = timeout > 0 ? &to : NULL;
319
320         /*
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.
324          */
325         message_dispatch();
326
327         /*
328          * Check to see if we already have a message on the smb queue.
329          * If so - copy and return it.
330          */
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));
334   
335                 /* Free the message we just copied. */
336                 DLIST_REMOVE(smb_oplock_queue, msg);
337                 free_queued_message(msg);
338                 
339                 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
340                 return True;
341         }
342
343         /*
344          * Check to see if we already have a message on the deferred open queue
345          * and it's time to schedule.
346          */
347         if(smb_sharing_violation_queue != NULL) {
348                 BOOL pop_message = False;
349                 struct pending_message_list *msg = smb_sharing_violation_queue;
350
351                 if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
352                         pop_message = True;
353                 } else {
354                         struct timeval tv;
355                         SMB_BIG_INT tdif;
356
357                         GetTimeOfDay(&tv);
358                         tdif = usec_time_diff(&msg->msg_time, &tv);
359                         if (tdif <= 0) {
360                                 /* Timed out. Schedule...*/
361                                 pop_message = True;
362                                 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
363                         } else {
364                                 /* Make a more accurate select timeout. */
365                                 to.tv_sec = tdif / 1000000;
366                                 to.tv_usec = tdif % 1000000;
367                                 pto = &to;
368                                 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
369                                         (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
370                         }
371                 }
372
373                 if (pop_message) {
374                         memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
375   
376                         /* We leave this message on the queue so the open code can
377                            know this is a retry. */
378                         DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
379                         return True;
380                 }
381         }
382
383         /*
384          * Setup the select read fd set.
385          */
386
387         FD_ZERO(&fds);
388
389         /*
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.
396          */
397
398         if (oplock_message_waiting(&fds)) {
399                 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
400                 async_processing(buffer, buffer_len);
401                 /*
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.
405                  */
406                 goto again;
407         }
408         
409         FD_SET(smbd_server_fd(),&fds);
410         maxfd = setup_oplock_select_set(&fds);
411
412         selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
413
414         /* if we get EINTR then maybe we have received an oplock
415            signal - treat this as select returning 1. This is ugly, but
416            is the best we can do until the oplock code knows more about
417            signals */
418         if (selrtn == -1 && errno == EINTR) {
419                 async_processing(buffer, buffer_len);
420                 /*
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.
424                  */
425                 goto again;
426         }
427
428         /* Check if error */
429         if (selrtn == -1) {
430                 /* something is wrong. Maybe the socket is dead? */
431                 smb_read_error = READ_ERROR;
432                 return False;
433         } 
434     
435         /* Did we timeout ? */
436         if (selrtn == 0) {
437                 smb_read_error = READ_TIMEOUT;
438                 return False;
439         }
440
441         /*
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.
445          */
446
447         if (oplock_message_waiting(&fds)) {
448                 async_processing(buffer, buffer_len);
449                 /*
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.
453                  */
454                 goto again;
455         }
456         
457         return receive_smb(smbd_server_fd(), buffer, 0);
458 }
459
460 /****************************************************************************
461 Get the next SMB packet, doing the local message processing automatically.
462 ****************************************************************************/
463
464 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
465 {
466         BOOL got_keepalive;
467         BOOL ret;
468
469         do {
470                 ret = receive_message_or_smb(inbuf,bufsize,timeout);
471                 
472                 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
473         } while (ret && got_keepalive);
474
475         return ret;
476 }
477
478 /****************************************************************************
479  We're terminating and have closed all our files/connections etc.
480  If there are any pending local messages we need to respond to them
481  before termination so that other smbds don't think we just died whilst
482  holding oplocks.
483 ****************************************************************************/
484
485 void respond_to_all_remaining_local_messages(void)
486 {
487         char buffer[1024];
488
489         /*
490          * Assert we have no exclusive open oplocks.
491          */
492
493         if(get_number_of_exclusive_open_oplocks()) {
494                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
495                         get_number_of_exclusive_open_oplocks() ));
496                 return;
497         }
498
499         /*
500          * Keep doing receive_local_message with a 1 ms timeout until
501          * we have no more messages.
502          */
503
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));
507         }
508
509         return;
510 }
511
512
513 /*
514 These flags determine some of the permissions required to do an operation 
515
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.
519 */
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)
527
528 /* 
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!
532 */
533 static const struct smb_message_struct {
534         const char *name;
535         int (*fn)(connection_struct *conn, char *, char *, int, int);
536         int flags;
537 } smb_messages[256] = {
538
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 }
795
796 };
797
798 /*******************************************************************
799  Dump a packet to a file.
800 ********************************************************************/
801
802 static void smb_dump(const char *name, int type, char *data, ssize_t len)
803 {
804         int fd, i;
805         pstring fname;
806         if (DEBUGLEVEL < 50) return;
807
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;
814         }
815         if (fd != -1) {
816                 ssize_t ret = write(fd, data, len);
817                 if (ret != len)
818                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
819                 close(fd);
820                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
821         }
822 }
823
824
825 /****************************************************************************
826  Do a switch on the message type, and return the response size
827 ****************************************************************************/
828
829 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
830 {
831         static pid_t pid= (pid_t)-1;
832         int outsize = 0;
833         extern uint16 global_smbpid;
834
835         type &= 0xff;
836
837         if (pid == (pid_t)-1)
838                 pid = sys_getpid();
839
840         errno = 0;
841         last_message = type;
842
843         /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
844         if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
845                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
846                 exit_server("Non-SMB packet");
847                 return(-1);
848         }
849
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);
853
854         if (smb_messages[type].fn == NULL) {
855                 DEBUG(0,("Unknown message type %d!\n",type));
856                 smb_dump("Unknown", 1, inbuf, size);
857                 outsize = reply_unknown(inbuf,outbuf);
858         } else {
859                 int flags = smb_messages[type].flags;
860                 static uint16 last_session_tag = UID_FIELD_INVALID;
861                 /* In share mode security we must ignore the vuid. */
862                 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
863                 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
864
865                 DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn));
866
867                 smb_dump(smb_fn_name(type), 1, inbuf, size);
868                 if(global_oplock_break) {
869                         if(flags & QUEUE_IN_OPLOCK) {
870                                 /* 
871                                  * Queue this message as we are the process of an oplock break.
872                                  */
873
874                                 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
875                                 DEBUGADD( 2, ( "oplock break state.\n" ) );
876
877                                 push_oplock_pending_smb_message( inbuf, size );
878                                 return -1;
879                         }
880                 }
881
882                 /* Ensure this value is replaced in the incoming packet. */
883                 SSVAL(inbuf,smb_uid,session_tag);
884
885                 /*
886                  * Ensure the correct username is in current_user_info.
887                  * This is a really ugly bugfix for problems with
888                  * multiple session_setup_and_X's being done and
889                  * allowing %U and %G substitutions to work correctly.
890                  * There is a reason this code is done here, don't
891                  * move it unless you know what you're doing... :-).
892                  * JRA.
893                  */
894
895                 if (session_tag != last_session_tag) {
896                         user_struct *vuser = NULL;
897
898                         last_session_tag = session_tag;
899                         if(session_tag != UID_FIELD_INVALID)
900                                 vuser = get_valid_user_struct(session_tag);           
901                         if(vuser != NULL)
902                                 set_current_user_info(&vuser->user);
903                 }
904
905                 /* does this protocol need to be run as root? */
906                 if (!(flags & AS_USER))
907                         change_to_root_user();
908
909                 /* does this protocol need a valid tree connection? */
910                 if ((flags & AS_USER) && !conn)
911                         return ERROR_DOS(ERRSRV, ERRinvnid);
912
913
914                 /* does this protocol need to be run as the connected user? */
915                 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
916                         if (flags & AS_GUEST) 
917                                 flags &= ~AS_USER;
918                         else
919                                 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
920                 }
921
922                 /* this code is to work around a bug is MS client 3 without
923                         introducing a security hole - it needs to be able to do
924                         print queue checks as guest if it isn't logged in properly */
925                 if (flags & AS_USER)
926                         flags &= ~AS_GUEST;
927
928                 /* does it need write permission? */
929                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
930                         return(ERROR_DOS(ERRSRV,ERRaccess));
931
932                 /* ipc services are limited */
933                 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
934                         return(ERROR_DOS(ERRSRV,ERRaccess));        
935
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));
939
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));
944
945                 last_inbuf = inbuf;
946
947                 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
948         }
949
950         smb_dump(smb_fn_name(type), 0, outbuf, outsize);
951
952         return(outsize);
953 }
954
955
956 /****************************************************************************
957  Construct a reply to the incoming packet.
958 ****************************************************************************/
959
960 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
961 {
962         int type = CVAL(inbuf,smb_com);
963         int outsize = 0;
964         int msg_type = CVAL(inbuf,0);
965
966         GetTimeOfDay(&smb_last_time);
967
968         chain_size = 0;
969         file_chain_reset();
970         reset_chain_p();
971
972         if (msg_type != 0)
973                 return(reply_special(inbuf,outbuf));  
974
975         construct_reply_common(inbuf, outbuf);
976
977         outsize = switch_message(type,inbuf,outbuf,size,bufsize);
978
979         outsize += chain_size;
980
981         if(outsize > 4)
982                 smb_setlen(outbuf,outsize - 4);
983         return(outsize);
984 }
985
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 ****************************************************************************/
990
991 static BOOL process_count_update_successful = False;
992
993 static int32 increment_smbd_process_count(void)
994 {
995         int32 total_smbds;
996
997         if (lp_max_smbd_processes()) {
998                 total_smbds = 0;
999                 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1000                         return 1;
1001                 process_count_update_successful = True;
1002                 return total_smbds + 1;
1003         }
1004         return 1;
1005 }
1006
1007 void decrement_smbd_process_count(void)
1008 {
1009         int32 total_smbds;
1010
1011         if (lp_max_smbd_processes() && process_count_update_successful) {
1012                 total_smbds = 1;
1013                 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1014         }
1015 }
1016
1017 static BOOL smbd_process_limit(void)
1018 {
1019         int32  total_smbds;
1020         
1021         if (lp_max_smbd_processes()) {
1022
1023                 /* Always add one to the smbd process count, as exit_server() always
1024                  * subtracts one.
1025                  */
1026
1027                 if (!conn_tdb_ctx()) {
1028                         DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1029 set. Ignoring max smbd restriction.\n"));
1030                         return False;
1031                 }
1032
1033                 total_smbds = increment_smbd_process_count();
1034                 return total_smbds > lp_max_smbd_processes();
1035         }
1036         else
1037                 return False;
1038 }
1039
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 ****************************************************************************/
1044
1045 void process_smb(char *inbuf, char *outbuf)
1046 {
1047         static int trans_num;
1048         int msg_type = CVAL(inbuf,0);
1049         int32 len = smb_len(inbuf);
1050         int nread = len + 4;
1051
1052         DO_PROFILE_INC(smb_count);
1053
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");
1066                 }
1067         }
1068
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 ) );
1071
1072         if (msg_type == 0)
1073                 show_msg(inbuf);
1074         else if(msg_type == SMBkeepalive)
1075                 return; /* Keepalive packet. */
1076
1077         nread = construct_reply(inbuf,outbuf,nread,max_send);
1078       
1079         if(nread > 0) {
1080                 if (CVAL(outbuf,0) == 0)
1081                         show_msg(outbuf);
1082         
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.");
1088                 }
1089         }
1090         trans_num++;
1091 }
1092
1093 /****************************************************************************
1094  Return a string containing the function name of a SMB command.
1095 ****************************************************************************/
1096
1097 const char *smb_fn_name(int type)
1098 {
1099         const char *unknown_name = "SMBunknown";
1100
1101         if (smb_messages[type].name == NULL)
1102                 return(unknown_name);
1103
1104         return(smb_messages[type].name);
1105 }
1106
1107 /****************************************************************************
1108  Helper functions for contruct_reply.
1109 ****************************************************************************/
1110
1111 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
1112
1113 void remove_from_common_flags2(uint32 v)
1114 {
1115         common_flags2 &= ~v;
1116 }
1117
1118 void construct_reply_common(char *inbuf,char *outbuf)
1119 {
1120         memset(outbuf,'\0',smb_size);
1121
1122         set_message(outbuf,0,0,True);
1123         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1124         
1125         memcpy(outbuf+4,inbuf+4,4);
1126         SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1127         SCVAL(outbuf,smb_reh,0);
1128         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1129         SSVAL(outbuf,smb_flg2,
1130                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1131                 common_flags2);
1132
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));
1138 }
1139
1140 /****************************************************************************
1141  Construct a chained reply and add it to the already made reply
1142 ****************************************************************************/
1143
1144 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1145 {
1146         static char *orig_inbuf;
1147         static char *orig_outbuf;
1148         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1149         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1150         char *inbuf2, *outbuf2;
1151         int outsize2;
1152         char inbuf_saved[smb_wct];
1153         char outbuf_saved[smb_wct];
1154         int wct = CVAL(outbuf,smb_wct);
1155         int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
1156
1157         /* maybe its not chained */
1158         if (smb_com2 == 0xFF) {
1159                 SCVAL(outbuf,smb_vwv0,0xFF);
1160                 return outsize;
1161         }
1162
1163         if (chain_size == 0) {
1164                 /* this is the first part of the chain */
1165                 orig_inbuf = inbuf;
1166                 orig_outbuf = outbuf;
1167         }
1168
1169         /*
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.
1173          */
1174
1175         outsize = (outsize + 3) & ~3;
1176
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);
1180
1181         /* remember how much the caller added to the chain, only counting stuff
1182                 after the parameter words */
1183         chain_size += outsize - smb_wct;
1184
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;
1189
1190         /* remember the original command type */
1191         smb_com1 = CVAL(orig_inbuf,smb_com);
1192
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);
1196
1197         /* give the new packet the same header as the last part of the SMB */
1198         memmove(inbuf2,inbuf,smb_wct);
1199
1200         /* create the in buffer */
1201         SCVAL(inbuf2,smb_com,smb_com2);
1202
1203         /* create the out buffer */
1204         construct_reply_common(inbuf2, outbuf2);
1205
1206         DEBUG(3,("Chained message\n"));
1207         show_msg(inbuf2);
1208
1209         /* process the request */
1210         outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1211                                 bufsize-chain_size);
1212
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);
1217
1218         /* restore the saved data, being careful not to overwrite any
1219                 data from the reply header */
1220         memcpy(inbuf2,inbuf_saved,smb_wct);
1221
1222         {
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);
1226         }
1227
1228         return outsize2;
1229 }
1230
1231 /****************************************************************************
1232  Setup the needed select timeout.
1233 ****************************************************************************/
1234
1235 static int setup_select_timeout(void)
1236 {
1237         int select_timeout;
1238         int t;
1239
1240         select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1241         select_timeout *= 1000;
1242
1243         t = change_notify_timeout();
1244         if (t != -1)
1245                 select_timeout = MIN(select_timeout, t*1000);
1246
1247         if (print_notify_messages_pending())
1248                 select_timeout = MIN(select_timeout, 1000);
1249
1250         return select_timeout;
1251 }
1252
1253 /****************************************************************************
1254  Check if services need reloading.
1255 ****************************************************************************/
1256
1257 void check_reload(int t)
1258 {
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();
1262
1263         if(last_smb_conf_reload_time == 0) {
1264                 last_smb_conf_reload_time = t;
1265                 /* Our printing subsystem might not be ready at smbd start up.
1266                    Then no printer is available till the first printers check
1267                    is performed.  A lower initial interval circumvents this. */
1268                 if ( printcap_cache_time > 60 )
1269                         last_load_printers_reload_time = t - printcap_cache_time + 60;
1270                 else
1271                         last_load_printers_reload_time = t;
1272         }
1273
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;
1278         }
1279
1280         /* 'printcap cache time = 0' disable the feature */
1281         
1282         if ( printcap_cache_time != 0 )
1283         { 
1284                 /* see if it's time to reload or if the clock has been set back */
1285                 
1286                 if ( (t >= last_load_printers_reload_time+printcap_cache_time) 
1287                         || (t-last_load_printers_reload_time  < 0) ) 
1288                 {
1289                         DEBUG( 3,( "Printcap cache time expired.\n"));
1290                         remove_stale_printers();
1291                         load_printers();
1292                         last_load_printers_reload_time = t;
1293                 }
1294         }
1295 }
1296
1297 /****************************************************************************
1298  Process any timeout housekeeping. Return False if the caller should exit.
1299 ****************************************************************************/
1300
1301 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1302 {
1303         static time_t last_keepalive_sent_time = 0;
1304         static time_t last_idle_closed_check = 0;
1305         time_t t;
1306         BOOL allidle = True;
1307         extern int keepalive;
1308
1309         if (smb_read_error == READ_EOF) {
1310                 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1311                 return False;
1312         }
1313
1314         if (smb_read_error == READ_ERROR) {
1315                 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1316                         strerror(errno)));
1317                 return False;
1318         }
1319
1320         if (smb_read_error == READ_BAD_SIG) {
1321                 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1322                 return False;
1323         }
1324
1325         *last_timeout_processing_time = t = time(NULL);
1326
1327         if(last_keepalive_sent_time == 0)
1328                 last_keepalive_sent_time = t;
1329
1330         if(last_idle_closed_check == 0)
1331                 last_idle_closed_check = t;
1332
1333         /* become root again if waiting */
1334         change_to_root_user();
1335
1336         /* run all registered idle events */
1337         smb_run_idle_events(t);
1338
1339         /* check if we need to reload services */
1340         check_reload(t);
1341
1342         /* automatic timeout if all connections are closed */      
1343         if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1344                 DEBUG( 2, ( "Closing idle connection\n" ) );
1345                 return False;
1346         } else {
1347                 last_idle_closed_check = t;
1348         }
1349
1350         if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1351                 extern struct auth_context *negprot_global_auth_context;
1352                 if (!send_keepalive(smbd_server_fd())) {
1353                         DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1354                         return False;
1355                 }
1356
1357                 /* send a keepalive for a password server or the like.
1358                         This is attached to the auth_info created in the
1359                 negprot */
1360                 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method 
1361                                 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1362
1363                         negprot_global_auth_context->challenge_set_method->send_keepalive
1364                         (&negprot_global_auth_context->challenge_set_method->private_data);
1365                 }
1366
1367                 last_keepalive_sent_time = t;
1368         }
1369
1370         /* check for connection timeouts */
1371         allidle = conn_idle_all(t, deadtime);
1372
1373         if (allidle && conn_num_open()>0) {
1374                 DEBUG(2,("Closing idle connection 2.\n"));
1375                 return False;
1376         }
1377
1378         if(global_machine_password_needs_changing && 
1379                         /* for ADS we need to do a regular ADS password change, not a domain
1380                                         password change */
1381                         lp_security() == SEC_DOMAIN) {
1382
1383                 unsigned char trust_passwd_hash[16];
1384                 time_t lct;
1385
1386                 /*
1387                  * We're in domain level security, and the code that
1388                  * read the machine password flagged that the machine
1389                  * password needs changing.
1390                  */
1391
1392                 /*
1393                  * First, open the machine password file with an exclusive lock.
1394                  */
1395
1396                 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1397                         DEBUG(0,("process: unable to lock the machine account password for \
1398 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1399                         return True;
1400                 }
1401
1402                 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1403                         DEBUG(0,("process: unable to read the machine account password for \
1404 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1405                         secrets_lock_trust_account_password(lp_workgroup(), False);
1406                         return True;
1407                 }
1408
1409                 /*
1410                  * Make sure someone else hasn't already done this.
1411                  */
1412
1413                 if(t < lct + lp_machine_password_timeout()) {
1414                         global_machine_password_needs_changing = False;
1415                         secrets_lock_trust_account_password(lp_workgroup(), False);
1416                         return True;
1417                 }
1418
1419                 /* always just contact the PDC here */
1420     
1421                 change_trust_account_password( lp_workgroup(), NULL);
1422                 global_machine_password_needs_changing = False;
1423                 secrets_lock_trust_account_password(lp_workgroup(), False);
1424         }
1425
1426         /*
1427          * Check to see if we have any blocking locks
1428          * outstanding on the queue.
1429          */
1430         process_blocking_lock_queue(t);
1431
1432         /* update printer queue caches if necessary */
1433   
1434         update_monitored_printq_cache();
1435   
1436         /*
1437          * Check to see if we have any change notifies 
1438          * outstanding on the queue.
1439          */
1440         process_pending_change_notify_queue(t);
1441
1442         /*
1443          * Now we are root, check if the log files need pruning.
1444          * Force a log file check.
1445          */
1446         force_check_log_size();
1447         check_log_size();
1448
1449         /* Send any queued printer notify message to interested smbd's. */
1450
1451         print_notify_send_messages(0);
1452
1453         /*
1454          * Modify the select timeout depending upon
1455          * what we have remaining in our queues.
1456          */
1457
1458         *select_timeout = setup_select_timeout();
1459
1460         return True;
1461 }
1462
1463 /****************************************************************************
1464   process commands from the client
1465 ****************************************************************************/
1466
1467 void smbd_process(void)
1468 {
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;
1473
1474         InBuffer = (char *)malloc(total_buffer_size);
1475         OutBuffer = (char *)malloc(total_buffer_size);
1476         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
1477                 return;
1478
1479 #if defined(DEVELOPER)
1480         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1481         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1482 #endif
1483
1484         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1485
1486         while (True) {
1487                 int deadtime = lp_deadtime()*60;
1488                 int select_timeout = setup_select_timeout();
1489                 int num_echos;
1490
1491                 if (deadtime <= 0)
1492                         deadtime = DEFAULT_SMBD_TIMEOUT;
1493
1494                 errno = 0;      
1495                 
1496                 /* free up temporary memory */
1497                 lp_talloc_free();
1498                 main_loop_talloc_free();
1499
1500                 /* run all registered idle events */
1501                 smb_run_idle_events(time(NULL));
1502
1503
1504                 /* Did someone ask for immediate checks on things like blocking locks ? */
1505                 if (select_timeout == 0) {
1506                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1507                                 return;
1508                         num_smbs = 0; /* Reset smb counter. */
1509                 }
1510
1511 #if defined(DEVELOPER)
1512                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1513 #endif
1514
1515                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1516                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1517                                 return;
1518                         num_smbs = 0; /* Reset smb counter. */
1519                 }
1520
1521                 /*
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.
1529                  */ 
1530                 num_echos = smb_echo_count;
1531
1532                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1533
1534                 process_smb(InBuffer, OutBuffer);
1535
1536                 if (smb_echo_count != num_echos) {
1537                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1538                                 return;
1539                         num_smbs = 0; /* Reset smb counter. */
1540                 }
1541
1542                 num_smbs++;
1543
1544                 /*
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.
1549                  */
1550                 
1551                 if ((num_smbs % 200) == 0) {
1552                         time_t new_check_time = time(NULL);
1553                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1554                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1555                                         return;
1556                                 num_smbs = 0; /* Reset smb counter. */
1557                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1558                         }
1559                 }
1560
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. */
1567
1568                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1569                         change_to_root_user();
1570                         check_log_size();
1571                 }
1572         }
1573 }