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