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