40d6818f3f059e264e1e2648be2d80268bc85698
[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("Caught TERM signal");
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 - split out from the smbd_process() code so
1076  it can be used by the oplock break code.
1077 ****************************************************************************/
1078
1079 void process_smb(char *inbuf, char *outbuf)
1080 {
1081         static int trans_num;
1082         int msg_type = CVAL(inbuf,0);
1083         int32 len = smb_len(inbuf);
1084         int nread = len + 4;
1085
1086         DO_PROFILE_INC(smb_count);
1087
1088         if (trans_num == 0) {
1089                 /* on the first packet, check the global hosts allow/ hosts
1090                 deny parameters before doing any parsing of the packet
1091                 passed to us by the client.  This prevents attacks on our
1092                 parsing code from hosts not in the hosts allow list */
1093                 if (smbd_process_limit() ||
1094                                 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1095                         /* send a negative session response "not listening on calling name" */
1096                         static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1097                         DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1098                         (void)send_smb(smbd_server_fd(),(char *)buf);
1099                         exit_server("connection denied");
1100                 }
1101         }
1102
1103         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1104         DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1105
1106         if (msg_type == 0)
1107                 show_msg(inbuf);
1108         else if(msg_type == SMBkeepalive)
1109                 return; /* Keepalive packet. */
1110
1111         nread = construct_reply(inbuf,outbuf,nread,max_send);
1112       
1113         if(nread > 0) {
1114                 if (CVAL(outbuf,0) == 0)
1115                         show_msg(outbuf);
1116         
1117                 if (nread != smb_len(outbuf) + 4) {
1118                         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1119                                 nread, smb_len(outbuf)));
1120                 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1121                         exit_server("process_smb: send_smb failed.");
1122                 }
1123         }
1124         trans_num++;
1125 }
1126
1127 /****************************************************************************
1128  Return a string containing the function name of a SMB command.
1129 ****************************************************************************/
1130
1131 const char *smb_fn_name(int type)
1132 {
1133         const char *unknown_name = "SMBunknown";
1134
1135         if (smb_messages[type].name == NULL)
1136                 return(unknown_name);
1137
1138         return(smb_messages[type].name);
1139 }
1140
1141 /****************************************************************************
1142  Helper functions for contruct_reply.
1143 ****************************************************************************/
1144
1145 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1146
1147 void add_to_common_flags2(uint32 v)
1148 {
1149         common_flags2 |= v;
1150 }
1151
1152 void remove_from_common_flags2(uint32 v)
1153 {
1154         common_flags2 &= ~v;
1155 }
1156
1157 void construct_reply_common(char *inbuf,char *outbuf)
1158 {
1159         memset(outbuf,'\0',smb_size);
1160
1161         set_message(outbuf,0,0,True);
1162         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1163         
1164         memcpy(outbuf+4,inbuf+4,4);
1165         SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1166         SCVAL(outbuf,smb_reh,0);
1167         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1168         SSVAL(outbuf,smb_flg2,
1169                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1170                 common_flags2);
1171
1172         SSVAL(outbuf,smb_err,SMB_SUCCESS);
1173         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1174         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1175         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1176         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1177 }
1178
1179 /****************************************************************************
1180  Construct a chained reply and add it to the already made reply
1181 ****************************************************************************/
1182
1183 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1184 {
1185         static char *orig_inbuf;
1186         static char *orig_outbuf;
1187         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1188         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1189         char *inbuf2, *outbuf2;
1190         int outsize2;
1191         char inbuf_saved[smb_wct];
1192         char outbuf_saved[smb_wct];
1193         int outsize = smb_len(outbuf) + 4;
1194
1195         /* maybe its not chained */
1196         if (smb_com2 == 0xFF) {
1197                 SCVAL(outbuf,smb_vwv0,0xFF);
1198                 return outsize;
1199         }
1200
1201         if (chain_size == 0) {
1202                 /* this is the first part of the chain */
1203                 orig_inbuf = inbuf;
1204                 orig_outbuf = outbuf;
1205         }
1206
1207         /*
1208          * The original Win95 redirector dies on a reply to
1209          * a lockingX and read chain unless the chain reply is
1210          * 4 byte aligned. JRA.
1211          */
1212
1213         outsize = (outsize + 3) & ~3;
1214
1215         /* we need to tell the client where the next part of the reply will be */
1216         SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1217         SCVAL(outbuf,smb_vwv0,smb_com2);
1218
1219         /* remember how much the caller added to the chain, only counting stuff
1220                 after the parameter words */
1221         chain_size += outsize - smb_wct;
1222
1223         /* work out pointers into the original packets. The
1224                 headers on these need to be filled in */
1225         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1226         outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1227
1228         /* remember the original command type */
1229         smb_com1 = CVAL(orig_inbuf,smb_com);
1230
1231         /* save the data which will be overwritten by the new headers */
1232         memcpy(inbuf_saved,inbuf2,smb_wct);
1233         memcpy(outbuf_saved,outbuf2,smb_wct);
1234
1235         /* give the new packet the same header as the last part of the SMB */
1236         memmove(inbuf2,inbuf,smb_wct);
1237
1238         /* create the in buffer */
1239         SCVAL(inbuf2,smb_com,smb_com2);
1240
1241         /* create the out buffer */
1242         construct_reply_common(inbuf2, outbuf2);
1243
1244         DEBUG(3,("Chained message\n"));
1245         show_msg(inbuf2);
1246
1247         /* process the request */
1248         outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1249                                 bufsize-chain_size);
1250
1251         /* copy the new reply and request headers over the old ones, but
1252                 preserve the smb_com field */
1253         memmove(orig_outbuf,outbuf2,smb_wct);
1254         SCVAL(orig_outbuf,smb_com,smb_com1);
1255
1256         /* restore the saved data, being careful not to overwrite any
1257                 data from the reply header */
1258         memcpy(inbuf2,inbuf_saved,smb_wct);
1259
1260         {
1261                 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1262                 if (ofs < 0) ofs = 0;
1263                         memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1264         }
1265
1266         return outsize2;
1267 }
1268
1269 /****************************************************************************
1270  Setup the needed select timeout.
1271 ****************************************************************************/
1272
1273 static int setup_select_timeout(void)
1274 {
1275         int select_timeout;
1276         int t;
1277
1278         select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1279         select_timeout *= 1000;
1280
1281         t = change_notify_timeout();
1282         DEBUG(10, ("change_notify_timeout: %d\n", t));
1283         if (t != -1)
1284                 select_timeout = MIN(select_timeout, t*1000);
1285
1286         if (print_notify_messages_pending())
1287                 select_timeout = MIN(select_timeout, 1000);
1288
1289         return select_timeout;
1290 }
1291
1292 /****************************************************************************
1293  Check if services need reloading.
1294 ****************************************************************************/
1295
1296 void check_reload(time_t t)
1297 {
1298         static pid_t mypid = 0;
1299         static time_t last_smb_conf_reload_time = 0;
1300         static time_t last_printer_reload_time = 0;
1301         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1302
1303         if(last_smb_conf_reload_time == 0) {
1304                 last_smb_conf_reload_time = t;
1305                 /* Our printing subsystem might not be ready at smbd start up.
1306                    Then no printer is available till the first printers check
1307                    is performed.  A lower initial interval circumvents this. */
1308                 if ( printcap_cache_time > 60 )
1309                         last_printer_reload_time = t - printcap_cache_time + 60;
1310                 else
1311                         last_printer_reload_time = t;
1312         }
1313
1314         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1315                 /* randomize over 60 second the printcap reload to avoid all
1316                  * process hitting cupsd at the same time */
1317                 int time_range = 60;
1318
1319                 last_printer_reload_time += random() % time_range;
1320                 mypid = getpid();
1321         }
1322
1323         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1324                 reload_services(True);
1325                 reload_after_sighup = False;
1326                 last_smb_conf_reload_time = t;
1327         }
1328
1329         /* 'printcap cache time = 0' disable the feature */
1330         
1331         if ( printcap_cache_time != 0 )
1332         { 
1333                 /* see if it's time to reload or if the clock has been set back */
1334                 
1335                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1336                         || (t-last_printer_reload_time  < 0) ) 
1337                 {
1338                         DEBUG( 3,( "Printcap cache time expired.\n"));
1339                         reload_printers();
1340                         last_printer_reload_time = t;
1341                 }
1342         }
1343 }
1344
1345 /****************************************************************************
1346  Process any timeout housekeeping. Return False if the caller should exit.
1347 ****************************************************************************/
1348
1349 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1350 {
1351         static time_t last_keepalive_sent_time = 0;
1352         static time_t last_idle_closed_check = 0;
1353         time_t t;
1354         BOOL allidle = True;
1355
1356         if (smb_read_error == READ_EOF) {
1357                 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1358                 return False;
1359         }
1360
1361         if (smb_read_error == READ_ERROR) {
1362                 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1363                         strerror(errno)));
1364                 return False;
1365         }
1366
1367         if (smb_read_error == READ_BAD_SIG) {
1368                 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1369                 return False;
1370         }
1371
1372         *last_timeout_processing_time = t = time(NULL);
1373
1374         if(last_keepalive_sent_time == 0)
1375                 last_keepalive_sent_time = t;
1376
1377         if(last_idle_closed_check == 0)
1378                 last_idle_closed_check = t;
1379
1380         /* become root again if waiting */
1381         change_to_root_user();
1382
1383         /* run all registered idle events */
1384         smb_run_idle_events(t);
1385
1386         /* check if we need to reload services */
1387         check_reload(t);
1388
1389         /* automatic timeout if all connections are closed */      
1390         if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1391                 DEBUG( 2, ( "Closing idle connection\n" ) );
1392                 return False;
1393         } else {
1394                 last_idle_closed_check = t;
1395         }
1396
1397         if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1398                 if (!send_keepalive(smbd_server_fd())) {
1399                         DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1400                         return False;
1401                 }
1402
1403                 /* send a keepalive for a password server or the like.
1404                         This is attached to the auth_info created in the
1405                 negprot */
1406                 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method 
1407                                 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1408
1409                         negprot_global_auth_context->challenge_set_method->send_keepalive
1410                         (&negprot_global_auth_context->challenge_set_method->private_data);
1411                 }
1412
1413                 last_keepalive_sent_time = t;
1414         }
1415
1416         /* check for connection timeouts */
1417         allidle = conn_idle_all(t, deadtime);
1418
1419         if (allidle && conn_num_open()>0) {
1420                 DEBUG(2,("Closing idle connection 2.\n"));
1421                 return False;
1422         }
1423
1424         if(global_machine_password_needs_changing && 
1425                         /* for ADS we need to do a regular ADS password change, not a domain
1426                                         password change */
1427                         lp_security() == SEC_DOMAIN) {
1428
1429                 unsigned char trust_passwd_hash[16];
1430                 time_t lct;
1431
1432                 /*
1433                  * We're in domain level security, and the code that
1434                  * read the machine password flagged that the machine
1435                  * password needs changing.
1436                  */
1437
1438                 /*
1439                  * First, open the machine password file with an exclusive lock.
1440                  */
1441
1442                 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1443                         DEBUG(0,("process: unable to lock the machine account password for \
1444 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1445                         return True;
1446                 }
1447
1448                 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1449                         DEBUG(0,("process: unable to read the machine account password for \
1450 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1451                         secrets_lock_trust_account_password(lp_workgroup(), False);
1452                         return True;
1453                 }
1454
1455                 /*
1456                  * Make sure someone else hasn't already done this.
1457                  */
1458
1459                 if(t < lct + lp_machine_password_timeout()) {
1460                         global_machine_password_needs_changing = False;
1461                         secrets_lock_trust_account_password(lp_workgroup(), False);
1462                         return True;
1463                 }
1464
1465                 /* always just contact the PDC here */
1466     
1467                 change_trust_account_password( lp_workgroup(), NULL);
1468                 global_machine_password_needs_changing = False;
1469                 secrets_lock_trust_account_password(lp_workgroup(), False);
1470         }
1471
1472         /*
1473          * Check to see if we have any blocking locks
1474          * outstanding on the queue.
1475          */
1476         process_blocking_lock_queue(t);
1477
1478         /* update printer queue caches if necessary */
1479   
1480         update_monitored_printq_cache();
1481   
1482         /*
1483          * Check to see if we have any change notifies 
1484          * outstanding on the queue.
1485          */
1486         process_pending_change_notify_queue(t);
1487
1488         /*
1489          * Now we are root, check if the log files need pruning.
1490          * Force a log file check.
1491          */
1492         force_check_log_size();
1493         check_log_size();
1494
1495         /* Send any queued printer notify message to interested smbd's. */
1496
1497         print_notify_send_messages(0);
1498
1499         /*
1500          * Modify the select timeout depending upon
1501          * what we have remaining in our queues.
1502          */
1503
1504         *select_timeout = setup_select_timeout();
1505
1506         return True;
1507 }
1508
1509 /****************************************************************************
1510  Accessor functions for InBuffer, OutBuffer.
1511 ****************************************************************************/
1512
1513 char *get_InBuffer(void)
1514 {
1515         return InBuffer;
1516 }
1517
1518 void set_InBuffer(char *new_inbuf)
1519 {
1520         InBuffer = new_inbuf;
1521         current_inbuf = InBuffer;
1522 }
1523
1524 char *get_OutBuffer(void)
1525 {
1526         return OutBuffer;
1527 }
1528
1529 void set_OutBuffer(char *new_outbuf)
1530 {
1531         OutBuffer = new_outbuf;
1532 }
1533
1534 /****************************************************************************
1535  Free an InBuffer. Checks if not in use by aio system.
1536  Must have been allocated by NewInBuffer.
1537 ****************************************************************************/
1538
1539 void free_InBuffer(char *inbuf)
1540 {
1541         if (!aio_inbuffer_in_use(inbuf)) {
1542                 if (current_inbuf == inbuf) {
1543                         current_inbuf = NULL;
1544                 }
1545                 SAFE_FREE(inbuf);
1546         }
1547 }
1548
1549 /****************************************************************************
1550  Free an OutBuffer. No outbuffers currently stolen by aio system.
1551  Must have been allocated by NewInBuffer.
1552 ****************************************************************************/
1553
1554 void free_OutBuffer(char *outbuf)
1555 {
1556         SAFE_FREE(outbuf);
1557 }
1558
1559 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1560
1561 /****************************************************************************
1562  Allocate a new InBuffer. Returns the new and old ones.
1563 ****************************************************************************/
1564
1565 char *NewInBuffer(char **old_inbuf)
1566 {
1567         char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1568         if (!new_inbuf) {
1569                 return NULL;
1570         }
1571         if (old_inbuf) {
1572                 *old_inbuf = InBuffer;
1573         }
1574         InBuffer = new_inbuf;
1575 #if defined(DEVELOPER)
1576         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1577 #endif
1578         return InBuffer;
1579 }
1580
1581 /****************************************************************************
1582  Allocate a new OutBuffer. Returns the new and old ones.
1583 ****************************************************************************/
1584
1585 char *NewOutBuffer(char **old_outbuf)
1586 {
1587         char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1588         if (!new_outbuf) {
1589                 return NULL;
1590         }
1591         if (old_outbuf) {
1592                 *old_outbuf = OutBuffer;
1593         }
1594         OutBuffer = new_outbuf;
1595 #if defined(DEVELOPER)
1596         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1597 #endif
1598         return OutBuffer;
1599 }
1600
1601 /****************************************************************************
1602  Process commands from the client
1603 ****************************************************************************/
1604
1605 void smbd_process(void)
1606 {
1607         time_t last_timeout_processing_time = time(NULL);
1608         unsigned int num_smbs = 0;
1609
1610         /* Allocate the primary Inbut/Output buffers. */
1611
1612         if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) 
1613                 return;
1614
1615         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1616
1617         while (True) {
1618                 int deadtime = lp_deadtime()*60;
1619                 int select_timeout = setup_select_timeout();
1620                 int num_echos;
1621
1622                 if (deadtime <= 0)
1623                         deadtime = DEFAULT_SMBD_TIMEOUT;
1624
1625                 errno = 0;      
1626                 
1627                 /* free up temporary memory */
1628                 lp_TALLOC_FREE();
1629                 main_loop_TALLOC_FREE();
1630
1631                 /* Did someone ask for immediate checks on things like blocking locks ? */
1632                 if (select_timeout == 0) {
1633                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1634                                 return;
1635                         num_smbs = 0; /* Reset smb counter. */
1636                 }
1637
1638                 run_events();
1639
1640 #if defined(DEVELOPER)
1641                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1642 #endif
1643
1644                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1645                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1646                                 return;
1647                         num_smbs = 0; /* Reset smb counter. */
1648                 }
1649
1650                 /*
1651                  * Ensure we do timeout processing if the SMB we just got was
1652                  * only an echo request. This allows us to set the select
1653                  * timeout in 'receive_message_or_smb()' to any value we like
1654                  * without worrying that the client will send echo requests
1655                  * faster than the select timeout, thus starving out the
1656                  * essential processing (change notify, blocking locks) that
1657                  * the timeout code does. JRA.
1658                  */ 
1659                 num_echos = smb_echo_count;
1660
1661                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1662
1663                 process_smb(InBuffer, OutBuffer);
1664
1665                 if (smb_echo_count != num_echos) {
1666                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1667                                 return;
1668                         num_smbs = 0; /* Reset smb counter. */
1669                 }
1670
1671                 num_smbs++;
1672
1673                 /*
1674                  * If we are getting smb requests in a constant stream
1675                  * with no echos, make sure we attempt timeout processing
1676                  * every select_timeout milliseconds - but only check for this
1677                  * every 200 smb requests.
1678                  */
1679                 
1680                 if ((num_smbs % 200) == 0) {
1681                         time_t new_check_time = time(NULL);
1682                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1683                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1684                                         return;
1685                                 num_smbs = 0; /* Reset smb counter. */
1686                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1687                         }
1688                 }
1689
1690                 /* The timeout_processing function isn't run nearly
1691                    often enough to implement 'max log size' without
1692                    overrunning the size of the file by many megabytes.
1693                    This is especially true if we are running at debug
1694                    level 10.  Checking every 50 SMBs is a nice
1695                    tradeoff of performance vs log file size overrun. */
1696
1697                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1698                         change_to_root_user();
1699                         check_log_size();
1700                 }
1701         }
1702 }