r15018: Merge Volker's ipc/trans2/nttrans changes over
[jra/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  * Only allow 5 outstanding trans requests. We're allocating memory, so
510  * prevent a DoS.
511  */
512
513 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
514 {
515         int count = 0;
516         for (; list != NULL; list = list->next) {
517
518                 if (list->mid == mid) {
519                         return NT_STATUS_INVALID_PARAMETER;
520                 }
521
522                 count += 1;
523         }
524         if (count > 5) {
525                 return NT_STATUS_INSUFFICIENT_RESOURCES;
526         }
527
528         return NT_STATUS_OK;
529 }
530
531 /****************************************************************************
532  We're terminating and have closed all our files/connections etc.
533  If there are any pending local messages we need to respond to them
534  before termination so that other smbds don't think we just died whilst
535  holding oplocks.
536 ****************************************************************************/
537
538 void respond_to_all_remaining_local_messages(void)
539 {
540         /*
541          * Assert we have no exclusive open oplocks.
542          */
543
544         if(get_number_of_exclusive_open_oplocks()) {
545                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
546                         get_number_of_exclusive_open_oplocks() ));
547                 return;
548         }
549
550         process_kernel_oplocks(NULL);
551
552         return;
553 }
554
555
556 /*
557 These flags determine some of the permissions required to do an operation 
558
559 Note that I don't set NEED_WRITE on some write operations because they
560 are used by some brain-dead clients when printing, and I don't want to
561 force write permissions on print services.
562 */
563 #define AS_USER (1<<0)
564 #define NEED_WRITE (1<<1)
565 #define TIME_INIT (1<<2)
566 #define CAN_IPC (1<<3)
567 #define AS_GUEST (1<<5)
568 #define DO_CHDIR (1<<6)
569
570 /* 
571    define a list of possible SMB messages and their corresponding
572    functions. Any message that has a NULL function is unimplemented -
573    please feel free to contribute implementations!
574 */
575 static const struct smb_message_struct {
576         const char *name;
577         int (*fn)(connection_struct *conn, char *, char *, int, int);
578         int flags;
579 } smb_messages[256] = {
580
581 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
582 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
583 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
584 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
585 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
586 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
587 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, 
588 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
589 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
590 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
591 /* 0x0a */ { "SMBread",reply_read,AS_USER},
592 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
593 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
594 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
595 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
596 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, 
597 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
598 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
599 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
600 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
601 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
602 /* 0x15 */ { NULL, NULL, 0 },
603 /* 0x16 */ { NULL, NULL, 0 },
604 /* 0x17 */ { NULL, NULL, 0 },
605 /* 0x18 */ { NULL, NULL, 0 },
606 /* 0x19 */ { NULL, NULL, 0 },
607 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
608 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
609 /* 0x1c */ { "SMBreadBs",NULL,0 },
610 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
611 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
612 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
613 /* 0x20 */ { "SMBwritec",NULL,0},
614 /* 0x21 */ { NULL, NULL, 0 },
615 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
616 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
617 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
618 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
619 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
620 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
621 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
622 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
623 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
624 /* 0x2b */ { "SMBecho",reply_echo,0},
625 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
626 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
627 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
628 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
629 /* 0x30 */ { NULL, NULL, 0 },
630 /* 0x31 */ { NULL, NULL, 0 },
631 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
632 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
633 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
634 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
635 /* 0x36 */ { NULL, NULL, 0 },
636 /* 0x37 */ { NULL, NULL, 0 },
637 /* 0x38 */ { NULL, NULL, 0 },
638 /* 0x39 */ { NULL, NULL, 0 },
639 /* 0x3a */ { NULL, NULL, 0 },
640 /* 0x3b */ { NULL, NULL, 0 },
641 /* 0x3c */ { NULL, NULL, 0 },
642 /* 0x3d */ { NULL, NULL, 0 },
643 /* 0x3e */ { NULL, NULL, 0 },
644 /* 0x3f */ { NULL, NULL, 0 },
645 /* 0x40 */ { NULL, NULL, 0 },
646 /* 0x41 */ { NULL, NULL, 0 },
647 /* 0x42 */ { NULL, NULL, 0 },
648 /* 0x43 */ { NULL, NULL, 0 },
649 /* 0x44 */ { NULL, NULL, 0 },
650 /* 0x45 */ { NULL, NULL, 0 },
651 /* 0x46 */ { NULL, NULL, 0 },
652 /* 0x47 */ { NULL, NULL, 0 },
653 /* 0x48 */ { NULL, NULL, 0 },
654 /* 0x49 */ { NULL, NULL, 0 },
655 /* 0x4a */ { NULL, NULL, 0 },
656 /* 0x4b */ { NULL, NULL, 0 },
657 /* 0x4c */ { NULL, NULL, 0 },
658 /* 0x4d */ { NULL, NULL, 0 },
659 /* 0x4e */ { NULL, NULL, 0 },
660 /* 0x4f */ { NULL, NULL, 0 },
661 /* 0x50 */ { NULL, NULL, 0 },
662 /* 0x51 */ { NULL, NULL, 0 },
663 /* 0x52 */ { NULL, NULL, 0 },
664 /* 0x53 */ { NULL, NULL, 0 },
665 /* 0x54 */ { NULL, NULL, 0 },
666 /* 0x55 */ { NULL, NULL, 0 },
667 /* 0x56 */ { NULL, NULL, 0 },
668 /* 0x57 */ { NULL, NULL, 0 },
669 /* 0x58 */ { NULL, NULL, 0 },
670 /* 0x59 */ { NULL, NULL, 0 },
671 /* 0x5a */ { NULL, NULL, 0 },
672 /* 0x5b */ { NULL, NULL, 0 },
673 /* 0x5c */ { NULL, NULL, 0 },
674 /* 0x5d */ { NULL, NULL, 0 },
675 /* 0x5e */ { NULL, NULL, 0 },
676 /* 0x5f */ { NULL, NULL, 0 },
677 /* 0x60 */ { NULL, NULL, 0 },
678 /* 0x61 */ { NULL, NULL, 0 },
679 /* 0x62 */ { NULL, NULL, 0 },
680 /* 0x63 */ { NULL, NULL, 0 },
681 /* 0x64 */ { NULL, NULL, 0 },
682 /* 0x65 */ { NULL, NULL, 0 },
683 /* 0x66 */ { NULL, NULL, 0 },
684 /* 0x67 */ { NULL, NULL, 0 },
685 /* 0x68 */ { NULL, NULL, 0 },
686 /* 0x69 */ { NULL, NULL, 0 },
687 /* 0x6a */ { NULL, NULL, 0 },
688 /* 0x6b */ { NULL, NULL, 0 },
689 /* 0x6c */ { NULL, NULL, 0 },
690 /* 0x6d */ { NULL, NULL, 0 },
691 /* 0x6e */ { NULL, NULL, 0 },
692 /* 0x6f */ { NULL, NULL, 0 },
693 /* 0x70 */ { "SMBtcon",reply_tcon,0},
694 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
695 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
696 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
697 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
698 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
699 /* 0x76 */ { NULL, NULL, 0 },
700 /* 0x77 */ { NULL, NULL, 0 },
701 /* 0x78 */ { NULL, NULL, 0 },
702 /* 0x79 */ { NULL, NULL, 0 },
703 /* 0x7a */ { NULL, NULL, 0 },
704 /* 0x7b */ { NULL, NULL, 0 },
705 /* 0x7c */ { NULL, NULL, 0 },
706 /* 0x7d */ { NULL, NULL, 0 },
707 /* 0x7e */ { NULL, NULL, 0 },
708 /* 0x7f */ { NULL, NULL, 0 },
709 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
710 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
711 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
712 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
713 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
714 /* 0x85 */ { NULL, NULL, 0 },
715 /* 0x86 */ { NULL, NULL, 0 },
716 /* 0x87 */ { NULL, NULL, 0 },
717 /* 0x88 */ { NULL, NULL, 0 },
718 /* 0x89 */ { NULL, NULL, 0 },
719 /* 0x8a */ { NULL, NULL, 0 },
720 /* 0x8b */ { NULL, NULL, 0 },
721 /* 0x8c */ { NULL, NULL, 0 },
722 /* 0x8d */ { NULL, NULL, 0 },
723 /* 0x8e */ { NULL, NULL, 0 },
724 /* 0x8f */ { NULL, NULL, 0 },
725 /* 0x90 */ { NULL, NULL, 0 },
726 /* 0x91 */ { NULL, NULL, 0 },
727 /* 0x92 */ { NULL, NULL, 0 },
728 /* 0x93 */ { NULL, NULL, 0 },
729 /* 0x94 */ { NULL, NULL, 0 },
730 /* 0x95 */ { NULL, NULL, 0 },
731 /* 0x96 */ { NULL, NULL, 0 },
732 /* 0x97 */ { NULL, NULL, 0 },
733 /* 0x98 */ { NULL, NULL, 0 },
734 /* 0x99 */ { NULL, NULL, 0 },
735 /* 0x9a */ { NULL, NULL, 0 },
736 /* 0x9b */ { NULL, NULL, 0 },
737 /* 0x9c */ { NULL, NULL, 0 },
738 /* 0x9d */ { NULL, NULL, 0 },
739 /* 0x9e */ { NULL, NULL, 0 },
740 /* 0x9f */ { NULL, NULL, 0 },
741 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
742 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
743 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
744 /* 0xa3 */ { NULL, NULL, 0 },
745 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
746 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE },
747 /* 0xa6 */ { NULL, NULL, 0 },
748 /* 0xa7 */ { NULL, NULL, 0 },
749 /* 0xa8 */ { NULL, NULL, 0 },
750 /* 0xa9 */ { NULL, NULL, 0 },
751 /* 0xaa */ { NULL, NULL, 0 },
752 /* 0xab */ { NULL, NULL, 0 },
753 /* 0xac */ { NULL, NULL, 0 },
754 /* 0xad */ { NULL, NULL, 0 },
755 /* 0xae */ { NULL, NULL, 0 },
756 /* 0xaf */ { NULL, NULL, 0 },
757 /* 0xb0 */ { NULL, NULL, 0 },
758 /* 0xb1 */ { NULL, NULL, 0 },
759 /* 0xb2 */ { NULL, NULL, 0 },
760 /* 0xb3 */ { NULL, NULL, 0 },
761 /* 0xb4 */ { NULL, NULL, 0 },
762 /* 0xb5 */ { NULL, NULL, 0 },
763 /* 0xb6 */ { NULL, NULL, 0 },
764 /* 0xb7 */ { NULL, NULL, 0 },
765 /* 0xb8 */ { NULL, NULL, 0 },
766 /* 0xb9 */ { NULL, NULL, 0 },
767 /* 0xba */ { NULL, NULL, 0 },
768 /* 0xbb */ { NULL, NULL, 0 },
769 /* 0xbc */ { NULL, NULL, 0 },
770 /* 0xbd */ { NULL, NULL, 0 },
771 /* 0xbe */ { NULL, NULL, 0 },
772 /* 0xbf */ { NULL, NULL, 0 },
773 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
774 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
775 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
776 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
777 /* 0xc4 */ { NULL, NULL, 0 },
778 /* 0xc5 */ { NULL, NULL, 0 },
779 /* 0xc6 */ { NULL, NULL, 0 },
780 /* 0xc7 */ { NULL, NULL, 0 },
781 /* 0xc8 */ { NULL, NULL, 0 },
782 /* 0xc9 */ { NULL, NULL, 0 },
783 /* 0xca */ { NULL, NULL, 0 },
784 /* 0xcb */ { NULL, NULL, 0 },
785 /* 0xcc */ { NULL, NULL, 0 },
786 /* 0xcd */ { NULL, NULL, 0 },
787 /* 0xce */ { NULL, NULL, 0 },
788 /* 0xcf */ { NULL, NULL, 0 },
789 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
790 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
791 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
792 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
793 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
794 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
795 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
796 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
797 /* 0xd8 */ { NULL, NULL, 0 },
798 /* 0xd9 */ { NULL, NULL, 0 },
799 /* 0xda */ { NULL, NULL, 0 },
800 /* 0xdb */ { NULL, NULL, 0 },
801 /* 0xdc */ { NULL, NULL, 0 },
802 /* 0xdd */ { NULL, NULL, 0 },
803 /* 0xde */ { NULL, NULL, 0 },
804 /* 0xdf */ { NULL, NULL, 0 },
805 /* 0xe0 */ { NULL, NULL, 0 },
806 /* 0xe1 */ { NULL, NULL, 0 },
807 /* 0xe2 */ { NULL, NULL, 0 },
808 /* 0xe3 */ { NULL, NULL, 0 },
809 /* 0xe4 */ { NULL, NULL, 0 },
810 /* 0xe5 */ { NULL, NULL, 0 },
811 /* 0xe6 */ { NULL, NULL, 0 },
812 /* 0xe7 */ { NULL, NULL, 0 },
813 /* 0xe8 */ { NULL, NULL, 0 },
814 /* 0xe9 */ { NULL, NULL, 0 },
815 /* 0xea */ { NULL, NULL, 0 },
816 /* 0xeb */ { NULL, NULL, 0 },
817 /* 0xec */ { NULL, NULL, 0 },
818 /* 0xed */ { NULL, NULL, 0 },
819 /* 0xee */ { NULL, NULL, 0 },
820 /* 0xef */ { NULL, NULL, 0 },
821 /* 0xf0 */ { NULL, NULL, 0 },
822 /* 0xf1 */ { NULL, NULL, 0 },
823 /* 0xf2 */ { NULL, NULL, 0 },
824 /* 0xf3 */ { NULL, NULL, 0 },
825 /* 0xf4 */ { NULL, NULL, 0 },
826 /* 0xf5 */ { NULL, NULL, 0 },
827 /* 0xf6 */ { NULL, NULL, 0 },
828 /* 0xf7 */ { NULL, NULL, 0 },
829 /* 0xf8 */ { NULL, NULL, 0 },
830 /* 0xf9 */ { NULL, NULL, 0 },
831 /* 0xfa */ { NULL, NULL, 0 },
832 /* 0xfb */ { NULL, NULL, 0 },
833 /* 0xfc */ { NULL, NULL, 0 },
834 /* 0xfd */ { NULL, NULL, 0 },
835 /* 0xfe */ { NULL, NULL, 0 },
836 /* 0xff */ { NULL, NULL, 0 }
837
838 };
839
840 /*******************************************************************
841  Dump a packet to a file.
842 ********************************************************************/
843
844 static void smb_dump(const char *name, int type, char *data, ssize_t len)
845 {
846         int fd, i;
847         pstring fname;
848         if (DEBUGLEVEL < 50) return;
849
850         if (len < 4) len = smb_len(data)+4;
851         for (i=1;i<100;i++) {
852                 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
853                                 type ? "req" : "resp");
854                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
855                 if (fd != -1 || errno != EEXIST) break;
856         }
857         if (fd != -1) {
858                 ssize_t ret = write(fd, data, len);
859                 if (ret != len)
860                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
861                 close(fd);
862                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
863         }
864 }
865
866
867 /****************************************************************************
868  Do a switch on the message type, and return the response size
869 ****************************************************************************/
870
871 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
872 {
873         static pid_t pid= (pid_t)-1;
874         int outsize = 0;
875
876         type &= 0xff;
877
878         if (pid == (pid_t)-1)
879                 pid = sys_getpid();
880
881         errno = 0;
882         set_saved_ntstatus(NT_STATUS_OK);
883
884         last_message = type;
885
886         /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
887         if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
888                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
889                 exit_server("Non-SMB packet");
890                 return(-1);
891         }
892
893         /* yuck! this is an interim measure before we get rid of our
894                 current inbuf/outbuf system */
895         global_smbpid = SVAL(inbuf,smb_pid);
896
897         if (smb_messages[type].fn == NULL) {
898                 DEBUG(0,("Unknown message type %d!\n",type));
899                 smb_dump("Unknown", 1, inbuf, size);
900                 outsize = reply_unknown(inbuf,outbuf);
901         } else {
902                 int flags = smb_messages[type].flags;
903                 static uint16 last_session_tag = UID_FIELD_INVALID;
904                 /* In share mode security we must ignore the vuid. */
905                 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
906                 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
907
908                 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn));
909
910                 smb_dump(smb_fn_name(type), 1, inbuf, size);
911
912                 /* Ensure this value is replaced in the incoming packet. */
913                 SSVAL(inbuf,smb_uid,session_tag);
914
915                 /*
916                  * Ensure the correct username is in current_user_info.
917                  * This is a really ugly bugfix for problems with
918                  * multiple session_setup_and_X's being done and
919                  * allowing %U and %G substitutions to work correctly.
920                  * There is a reason this code is done here, don't
921                  * move it unless you know what you're doing... :-).
922                  * JRA.
923                  */
924
925                 if (session_tag != last_session_tag) {
926                         user_struct *vuser = NULL;
927
928                         last_session_tag = session_tag;
929                         if(session_tag != UID_FIELD_INVALID)
930                                 vuser = get_valid_user_struct(session_tag);           
931                         if(vuser != NULL)
932                                 set_current_user_info(&vuser->user);
933                 }
934
935                 /* does this protocol need to be run as root? */
936                 if (!(flags & AS_USER))
937                         change_to_root_user();
938
939                 /* does this protocol need a valid tree connection? */
940                 if ((flags & AS_USER) && !conn) {
941                         /* Amazingly, the error code depends on the command (from Samba4). */
942                         if (type == SMBntcreateX) {
943                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
944                         } else {
945                                 return ERROR_DOS(ERRSRV, ERRinvnid);
946                         }
947                 }
948
949
950                 /* does this protocol need to be run as the connected user? */
951                 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
952                         if (flags & AS_GUEST) 
953                                 flags &= ~AS_USER;
954                         else
955                                 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
956                 }
957
958                 /* this code is to work around a bug is MS client 3 without
959                         introducing a security hole - it needs to be able to do
960                         print queue checks as guest if it isn't logged in properly */
961                 if (flags & AS_USER)
962                         flags &= ~AS_GUEST;
963
964                 /* does it need write permission? */
965                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
966                         return(ERROR_DOS(ERRSRV,ERRaccess));
967
968                 /* ipc services are limited */
969                 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
970                         return(ERROR_DOS(ERRSRV,ERRaccess));        
971
972                 /* load service specific parameters */
973                 if (conn) {
974                         if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) {
975                                 return(ERROR_DOS(ERRSRV,ERRaccess));
976                         }
977                         conn->num_smb_operations++;
978                 }
979
980                 /* does this protocol need to be run as guest? */
981                 if ((flags & AS_GUEST) && (!change_to_guest() || 
982                                 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
983                         return(ERROR_DOS(ERRSRV,ERRaccess));
984
985                 current_inbuf = inbuf; /* In case we need to defer this message in open... */
986                 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
987         }
988
989         smb_dump(smb_fn_name(type), 0, outbuf, outsize);
990
991         return(outsize);
992 }
993
994
995 /****************************************************************************
996  Construct a reply to the incoming packet.
997 ****************************************************************************/
998
999 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
1000 {
1001         int type = CVAL(inbuf,smb_com);
1002         int outsize = 0;
1003         int msg_type = CVAL(inbuf,0);
1004
1005         GetTimeOfDay(&smb_last_time);
1006
1007         chain_size = 0;
1008         file_chain_reset();
1009         reset_chain_p();
1010
1011         if (msg_type != 0)
1012                 return(reply_special(inbuf,outbuf));  
1013
1014         construct_reply_common(inbuf, outbuf);
1015
1016         outsize = switch_message(type,inbuf,outbuf,size,bufsize);
1017
1018         outsize += chain_size;
1019
1020         if(outsize > 4)
1021                 smb_setlen(outbuf,outsize - 4);
1022         return(outsize);
1023 }
1024
1025 /****************************************************************************
1026  Keep track of the number of running smbd's. This functionality is used to
1027  'hard' limit Samba overhead on resource constrained systems. 
1028 ****************************************************************************/
1029
1030 static BOOL process_count_update_successful = False;
1031
1032 static int32 increment_smbd_process_count(void)
1033 {
1034         int32 total_smbds;
1035
1036         if (lp_max_smbd_processes()) {
1037                 total_smbds = 0;
1038                 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1039                         return 1;
1040                 process_count_update_successful = True;
1041                 return total_smbds + 1;
1042         }
1043         return 1;
1044 }
1045
1046 void decrement_smbd_process_count(void)
1047 {
1048         int32 total_smbds;
1049
1050         if (lp_max_smbd_processes() && process_count_update_successful) {
1051                 total_smbds = 1;
1052                 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1053         }
1054 }
1055
1056 static BOOL smbd_process_limit(void)
1057 {
1058         int32  total_smbds;
1059         
1060         if (lp_max_smbd_processes()) {
1061
1062                 /* Always add one to the smbd process count, as exit_server() always
1063                  * subtracts one.
1064                  */
1065
1066                 if (!conn_tdb_ctx()) {
1067                         DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1068 set. Ignoring max smbd restriction.\n"));
1069                         return False;
1070                 }
1071
1072                 total_smbds = increment_smbd_process_count();
1073                 return total_smbds > lp_max_smbd_processes();
1074         }
1075         else
1076                 return False;
1077 }
1078
1079 /****************************************************************************
1080  Process an smb from the client
1081 ****************************************************************************/
1082
1083 static void process_smb(char *inbuf, char *outbuf)
1084 {
1085         static int trans_num;
1086         int msg_type = CVAL(inbuf,0);
1087         int32 len = smb_len(inbuf);
1088         int nread = len + 4;
1089
1090         DO_PROFILE_INC(smb_count);
1091
1092         if (trans_num == 0) {
1093                 /* on the first packet, check the global hosts allow/ hosts
1094                 deny parameters before doing any parsing of the packet
1095                 passed to us by the client.  This prevents attacks on our
1096                 parsing code from hosts not in the hosts allow list */
1097                 if (smbd_process_limit() ||
1098                                 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1099                         /* send a negative session response "not listening on calling name" */
1100                         static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1101                         DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1102                         (void)send_smb(smbd_server_fd(),(char *)buf);
1103                         exit_server("connection denied");
1104                 }
1105         }
1106
1107         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1108         DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1109
1110         if (msg_type == 0)
1111                 show_msg(inbuf);
1112         else if(msg_type == SMBkeepalive)
1113                 return; /* Keepalive packet. */
1114
1115         nread = construct_reply(inbuf,outbuf,nread,max_send);
1116       
1117         if(nread > 0) {
1118                 if (CVAL(outbuf,0) == 0)
1119                         show_msg(outbuf);
1120         
1121                 if (nread != smb_len(outbuf) + 4) {
1122                         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1123                                 nread, smb_len(outbuf)));
1124                 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1125                         exit_server("process_smb: send_smb failed.");
1126                 }
1127         }
1128         trans_num++;
1129 }
1130
1131 /****************************************************************************
1132  Return a string containing the function name of a SMB command.
1133 ****************************************************************************/
1134
1135 const char *smb_fn_name(int type)
1136 {
1137         const char *unknown_name = "SMBunknown";
1138
1139         if (smb_messages[type].name == NULL)
1140                 return(unknown_name);
1141
1142         return(smb_messages[type].name);
1143 }
1144
1145 /****************************************************************************
1146  Helper functions for contruct_reply.
1147 ****************************************************************************/
1148
1149 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1150
1151 void add_to_common_flags2(uint32 v)
1152 {
1153         common_flags2 |= v;
1154 }
1155
1156 void remove_from_common_flags2(uint32 v)
1157 {
1158         common_flags2 &= ~v;
1159 }
1160
1161 void construct_reply_common(char *inbuf,char *outbuf)
1162 {
1163         memset(outbuf,'\0',smb_size);
1164
1165         set_message(outbuf,0,0,True);
1166         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1167         
1168         memcpy(outbuf+4,inbuf+4,4);
1169         SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1170         SCVAL(outbuf,smb_reh,0);
1171         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1172         SSVAL(outbuf,smb_flg2,
1173                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1174                 common_flags2);
1175
1176         SSVAL(outbuf,smb_err,SMB_SUCCESS);
1177         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1178         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1179         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1180         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1181 }
1182
1183 /****************************************************************************
1184  Construct a chained reply and add it to the already made reply
1185 ****************************************************************************/
1186
1187 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1188 {
1189         static char *orig_inbuf;
1190         static char *orig_outbuf;
1191         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1192         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1193         char *inbuf2, *outbuf2;
1194         int outsize2;
1195         char inbuf_saved[smb_wct];
1196         char outbuf_saved[smb_wct];
1197         int outsize = smb_len(outbuf) + 4;
1198
1199         /* maybe its not chained */
1200         if (smb_com2 == 0xFF) {
1201                 SCVAL(outbuf,smb_vwv0,0xFF);
1202                 return outsize;
1203         }
1204
1205         if (chain_size == 0) {
1206                 /* this is the first part of the chain */
1207                 orig_inbuf = inbuf;
1208                 orig_outbuf = outbuf;
1209         }
1210
1211         /*
1212          * The original Win95 redirector dies on a reply to
1213          * a lockingX and read chain unless the chain reply is
1214          * 4 byte aligned. JRA.
1215          */
1216
1217         outsize = (outsize + 3) & ~3;
1218
1219         /* we need to tell the client where the next part of the reply will be */
1220         SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1221         SCVAL(outbuf,smb_vwv0,smb_com2);
1222
1223         /* remember how much the caller added to the chain, only counting stuff
1224                 after the parameter words */
1225         chain_size += outsize - smb_wct;
1226
1227         /* work out pointers into the original packets. The
1228                 headers on these need to be filled in */
1229         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1230         outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1231
1232         /* remember the original command type */
1233         smb_com1 = CVAL(orig_inbuf,smb_com);
1234
1235         /* save the data which will be overwritten by the new headers */
1236         memcpy(inbuf_saved,inbuf2,smb_wct);
1237         memcpy(outbuf_saved,outbuf2,smb_wct);
1238
1239         /* give the new packet the same header as the last part of the SMB */
1240         memmove(inbuf2,inbuf,smb_wct);
1241
1242         /* create the in buffer */
1243         SCVAL(inbuf2,smb_com,smb_com2);
1244
1245         /* create the out buffer */
1246         construct_reply_common(inbuf2, outbuf2);
1247
1248         DEBUG(3,("Chained message\n"));
1249         show_msg(inbuf2);
1250
1251         /* process the request */
1252         outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1253                                 bufsize-chain_size);
1254
1255         /* copy the new reply and request headers over the old ones, but
1256                 preserve the smb_com field */
1257         memmove(orig_outbuf,outbuf2,smb_wct);
1258         SCVAL(orig_outbuf,smb_com,smb_com1);
1259
1260         /* restore the saved data, being careful not to overwrite any
1261                 data from the reply header */
1262         memcpy(inbuf2,inbuf_saved,smb_wct);
1263
1264         {
1265                 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1266                 if (ofs < 0) ofs = 0;
1267                         memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1268         }
1269
1270         return outsize2;
1271 }
1272
1273 /****************************************************************************
1274  Setup the needed select timeout.
1275 ****************************************************************************/
1276
1277 static int setup_select_timeout(void)
1278 {
1279         int select_timeout;
1280         int t;
1281
1282         select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1283         select_timeout *= 1000;
1284
1285         t = change_notify_timeout();
1286         DEBUG(10, ("change_notify_timeout: %d\n", t));
1287         if (t != -1)
1288                 select_timeout = MIN(select_timeout, t*1000);
1289
1290         if (print_notify_messages_pending())
1291                 select_timeout = MIN(select_timeout, 1000);
1292
1293         return select_timeout;
1294 }
1295
1296 /****************************************************************************
1297  Check if services need reloading.
1298 ****************************************************************************/
1299
1300 void check_reload(time_t t)
1301 {
1302         static pid_t mypid = 0;
1303         static time_t last_smb_conf_reload_time = 0;
1304         static time_t last_printer_reload_time = 0;
1305         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1306
1307         if(last_smb_conf_reload_time == 0) {
1308                 last_smb_conf_reload_time = t;
1309                 /* Our printing subsystem might not be ready at smbd start up.
1310                    Then no printer is available till the first printers check
1311                    is performed.  A lower initial interval circumvents this. */
1312                 if ( printcap_cache_time > 60 )
1313                         last_printer_reload_time = t - printcap_cache_time + 60;
1314                 else
1315                         last_printer_reload_time = t;
1316         }
1317
1318         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1319                 /* randomize over 60 second the printcap reload to avoid all
1320                  * process hitting cupsd at the same time */
1321                 int time_range = 60;
1322
1323                 last_printer_reload_time += random() % time_range;
1324                 mypid = getpid();
1325         }
1326
1327         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1328                 reload_services(True);
1329                 reload_after_sighup = False;
1330                 last_smb_conf_reload_time = t;
1331         }
1332
1333         /* 'printcap cache time = 0' disable the feature */
1334         
1335         if ( printcap_cache_time != 0 )
1336         { 
1337                 /* see if it's time to reload or if the clock has been set back */
1338                 
1339                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1340                         || (t-last_printer_reload_time  < 0) ) 
1341                 {
1342                         DEBUG( 3,( "Printcap cache time expired.\n"));
1343                         reload_printers();
1344                         last_printer_reload_time = t;
1345                 }
1346         }
1347 }
1348
1349 /****************************************************************************
1350  Process any timeout housekeeping. Return False if the caller should exit.
1351 ****************************************************************************/
1352
1353 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1354 {
1355         static time_t last_keepalive_sent_time = 0;
1356         static time_t last_idle_closed_check = 0;
1357         time_t t;
1358         BOOL allidle = True;
1359
1360         if (smb_read_error == READ_EOF) {
1361                 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1362                 return False;
1363         }
1364
1365         if (smb_read_error == READ_ERROR) {
1366                 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1367                         strerror(errno)));
1368                 return False;
1369         }
1370
1371         if (smb_read_error == READ_BAD_SIG) {
1372                 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1373                 return False;
1374         }
1375
1376         *last_timeout_processing_time = t = time(NULL);
1377
1378         if(last_keepalive_sent_time == 0)
1379                 last_keepalive_sent_time = t;
1380
1381         if(last_idle_closed_check == 0)
1382                 last_idle_closed_check = t;
1383
1384         /* become root again if waiting */
1385         change_to_root_user();
1386
1387         /* run all registered idle events */
1388         smb_run_idle_events(t);
1389
1390         /* check if we need to reload services */
1391         check_reload(t);
1392
1393         /* automatic timeout if all connections are closed */      
1394         if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1395                 DEBUG( 2, ( "Closing idle connection\n" ) );
1396                 return False;
1397         } else {
1398                 last_idle_closed_check = t;
1399         }
1400
1401         if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1402                 if (!send_keepalive(smbd_server_fd())) {
1403                         DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1404                         return False;
1405                 }
1406
1407                 /* send a keepalive for a password server or the like.
1408                         This is attached to the auth_info created in the
1409                 negprot */
1410                 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method 
1411                                 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1412
1413                         negprot_global_auth_context->challenge_set_method->send_keepalive
1414                         (&negprot_global_auth_context->challenge_set_method->private_data);
1415                 }
1416
1417                 last_keepalive_sent_time = t;
1418         }
1419
1420         /* check for connection timeouts */
1421         allidle = conn_idle_all(t, deadtime);
1422
1423         if (allidle && conn_num_open()>0) {
1424                 DEBUG(2,("Closing idle connection 2.\n"));
1425                 return False;
1426         }
1427
1428         if(global_machine_password_needs_changing && 
1429                         /* for ADS we need to do a regular ADS password change, not a domain
1430                                         password change */
1431                         lp_security() == SEC_DOMAIN) {
1432
1433                 unsigned char trust_passwd_hash[16];
1434                 time_t lct;
1435
1436                 /*
1437                  * We're in domain level security, and the code that
1438                  * read the machine password flagged that the machine
1439                  * password needs changing.
1440                  */
1441
1442                 /*
1443                  * First, open the machine password file with an exclusive lock.
1444                  */
1445
1446                 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1447                         DEBUG(0,("process: unable to lock the machine account password for \
1448 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1449                         return True;
1450                 }
1451
1452                 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1453                         DEBUG(0,("process: unable to read the machine account password for \
1454 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1455                         secrets_lock_trust_account_password(lp_workgroup(), False);
1456                         return True;
1457                 }
1458
1459                 /*
1460                  * Make sure someone else hasn't already done this.
1461                  */
1462
1463                 if(t < lct + lp_machine_password_timeout()) {
1464                         global_machine_password_needs_changing = False;
1465                         secrets_lock_trust_account_password(lp_workgroup(), False);
1466                         return True;
1467                 }
1468
1469                 /* always just contact the PDC here */
1470     
1471                 change_trust_account_password( lp_workgroup(), NULL);
1472                 global_machine_password_needs_changing = False;
1473                 secrets_lock_trust_account_password(lp_workgroup(), False);
1474         }
1475
1476         /*
1477          * Check to see if we have any blocking locks
1478          * outstanding on the queue.
1479          */
1480         process_blocking_lock_queue(t);
1481
1482         /* update printer queue caches if necessary */
1483   
1484         update_monitored_printq_cache();
1485   
1486         /*
1487          * Check to see if we have any change notifies 
1488          * outstanding on the queue.
1489          */
1490         process_pending_change_notify_queue(t);
1491
1492         /*
1493          * Now we are root, check if the log files need pruning.
1494          * Force a log file check.
1495          */
1496         force_check_log_size();
1497         check_log_size();
1498
1499         /* Send any queued printer notify message to interested smbd's. */
1500
1501         print_notify_send_messages(0);
1502
1503         /*
1504          * Modify the select timeout depending upon
1505          * what we have remaining in our queues.
1506          */
1507
1508         *select_timeout = setup_select_timeout();
1509
1510         return True;
1511 }
1512
1513 /****************************************************************************
1514  Accessor functions for InBuffer, OutBuffer.
1515 ****************************************************************************/
1516
1517 char *get_InBuffer(void)
1518 {
1519         return InBuffer;
1520 }
1521
1522 void set_InBuffer(char *new_inbuf)
1523 {
1524         InBuffer = new_inbuf;
1525         current_inbuf = InBuffer;
1526 }
1527
1528 char *get_OutBuffer(void)
1529 {
1530         return OutBuffer;
1531 }
1532
1533 void set_OutBuffer(char *new_outbuf)
1534 {
1535         OutBuffer = new_outbuf;
1536 }
1537
1538 /****************************************************************************
1539  Free an InBuffer. Checks if not in use by aio system.
1540  Must have been allocated by NewInBuffer.
1541 ****************************************************************************/
1542
1543 void free_InBuffer(char *inbuf)
1544 {
1545         if (!aio_inbuffer_in_use(inbuf)) {
1546                 if (current_inbuf == inbuf) {
1547                         current_inbuf = NULL;
1548                 }
1549                 SAFE_FREE(inbuf);
1550         }
1551 }
1552
1553 /****************************************************************************
1554  Free an OutBuffer. No outbuffers currently stolen by aio system.
1555  Must have been allocated by NewInBuffer.
1556 ****************************************************************************/
1557
1558 void free_OutBuffer(char *outbuf)
1559 {
1560         SAFE_FREE(outbuf);
1561 }
1562
1563 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1564
1565 /****************************************************************************
1566  Allocate a new InBuffer. Returns the new and old ones.
1567 ****************************************************************************/
1568
1569 char *NewInBuffer(char **old_inbuf)
1570 {
1571         char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1572         if (!new_inbuf) {
1573                 return NULL;
1574         }
1575         if (old_inbuf) {
1576                 *old_inbuf = InBuffer;
1577         }
1578         InBuffer = new_inbuf;
1579 #if defined(DEVELOPER)
1580         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1581 #endif
1582         return InBuffer;
1583 }
1584
1585 /****************************************************************************
1586  Allocate a new OutBuffer. Returns the new and old ones.
1587 ****************************************************************************/
1588
1589 char *NewOutBuffer(char **old_outbuf)
1590 {
1591         char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1592         if (!new_outbuf) {
1593                 return NULL;
1594         }
1595         if (old_outbuf) {
1596                 *old_outbuf = OutBuffer;
1597         }
1598         OutBuffer = new_outbuf;
1599 #if defined(DEVELOPER)
1600         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1601 #endif
1602         return OutBuffer;
1603 }
1604
1605 /****************************************************************************
1606  Process commands from the client
1607 ****************************************************************************/
1608
1609 void smbd_process(void)
1610 {
1611         time_t last_timeout_processing_time = time(NULL);
1612         unsigned int num_smbs = 0;
1613
1614         /* Allocate the primary Inbut/Output buffers. */
1615
1616         if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) 
1617                 return;
1618
1619         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1620
1621         while (True) {
1622                 int deadtime = lp_deadtime()*60;
1623                 int select_timeout = setup_select_timeout();
1624                 int num_echos;
1625
1626                 if (deadtime <= 0)
1627                         deadtime = DEFAULT_SMBD_TIMEOUT;
1628
1629                 errno = 0;      
1630                 
1631                 /* free up temporary memory */
1632                 lp_TALLOC_FREE();
1633                 main_loop_TALLOC_FREE();
1634
1635                 /* Did someone ask for immediate checks on things like blocking locks ? */
1636                 if (select_timeout == 0) {
1637                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1638                                 return;
1639                         num_smbs = 0; /* Reset smb counter. */
1640                 }
1641
1642                 run_events();
1643
1644 #if defined(DEVELOPER)
1645                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1646 #endif
1647
1648                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1649                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1650                                 return;
1651                         num_smbs = 0; /* Reset smb counter. */
1652                 }
1653
1654                 /*
1655                  * Ensure we do timeout processing if the SMB we just got was
1656                  * only an echo request. This allows us to set the select
1657                  * timeout in 'receive_message_or_smb()' to any value we like
1658                  * without worrying that the client will send echo requests
1659                  * faster than the select timeout, thus starving out the
1660                  * essential processing (change notify, blocking locks) that
1661                  * the timeout code does. JRA.
1662                  */ 
1663                 num_echos = smb_echo_count;
1664
1665                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1666
1667                 process_smb(InBuffer, OutBuffer);
1668
1669                 if (smb_echo_count != num_echos) {
1670                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1671                                 return;
1672                         num_smbs = 0; /* Reset smb counter. */
1673                 }
1674
1675                 num_smbs++;
1676
1677                 /*
1678                  * If we are getting smb requests in a constant stream
1679                  * with no echos, make sure we attempt timeout processing
1680                  * every select_timeout milliseconds - but only check for this
1681                  * every 200 smb requests.
1682                  */
1683                 
1684                 if ((num_smbs % 200) == 0) {
1685                         time_t new_check_time = time(NULL);
1686                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1687                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1688                                         return;
1689                                 num_smbs = 0; /* Reset smb counter. */
1690                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1691                         }
1692                 }
1693
1694                 /* The timeout_processing function isn't run nearly
1695                    often enough to implement 'max log size' without
1696                    overrunning the size of the file by many megabytes.
1697                    This is especially true if we are running at debug
1698                    level 10.  Checking every 50 SMBs is a nice
1699                    tradeoff of performance vs log file size overrun. */
1700
1701                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1702                         change_to_root_user();
1703                         check_log_size();
1704                 }
1705         }
1706 }