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