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