r23537: Revert the inbuf/outbuf part of r23528: This caused the Solaris CC make test
[sfrench/samba-autobuild/.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_deferred_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] "
148                            "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
149                 if (mid == msg_mid) {
150                         DEBUG(10, ("schedule_deferred_open_smb_message: "
151                                    "scheduling mid %u\n", 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 "
160                    "message mid %u\n", 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(smbd_messaging_context(), 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(smbd_messaging_context());
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(smbd_messaging_context(), 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(inbuf,outbuf,outsize - 4);
1044         }
1045         return(outsize);
1046 }
1047
1048 /****************************************************************************
1049  Process an smb from the client
1050 ****************************************************************************/
1051
1052 static void process_smb(char *inbuf, char *outbuf)
1053 {
1054         static int trans_num;
1055         int msg_type = CVAL(inbuf,0);
1056         int32 len = smb_len(inbuf);
1057         int nread = len + 4;
1058
1059         DO_PROFILE_INC(smb_count);
1060
1061         if (trans_num == 0) {
1062                 /* on the first packet, check the global hosts allow/ hosts
1063                 deny parameters before doing any parsing of the packet
1064                 passed to us by the client.  This prevents attacks on our
1065                 parsing code from hosts not in the hosts allow list */
1066                 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1067                                   lp_hostsdeny(-1))) {
1068                         /* send a negative session response "not listening on calling name" */
1069                         static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1070                         DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1071                         (void)send_smb(smbd_server_fd(),(char *)buf);
1072                         exit_server_cleanly("connection denied");
1073                 }
1074         }
1075
1076         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1077         DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1078
1079         if (msg_type == 0)
1080                 show_msg(inbuf);
1081         else if(msg_type == SMBkeepalive)
1082                 return; /* Keepalive packet. */
1083
1084         nread = construct_reply(inbuf,outbuf,nread,max_send);
1085       
1086         if(nread > 0) {
1087                 if (CVAL(outbuf,0) == 0)
1088                         show_msg(outbuf);
1089         
1090                 if (nread != smb_len(outbuf) + 4) {
1091                         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1092                                 nread, smb_len(outbuf)));
1093                 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1094                         exit_server_cleanly("process_smb: send_smb failed.");
1095                 }
1096         }
1097         trans_num++;
1098 }
1099
1100 /****************************************************************************
1101  Return a string containing the function name of a SMB command.
1102 ****************************************************************************/
1103
1104 const char *smb_fn_name(int type)
1105 {
1106         const char *unknown_name = "SMBunknown";
1107
1108         if (smb_messages[type].name == NULL)
1109                 return(unknown_name);
1110
1111         return(smb_messages[type].name);
1112 }
1113
1114 /****************************************************************************
1115  Helper functions for contruct_reply.
1116 ****************************************************************************/
1117
1118 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1119
1120 void add_to_common_flags2(uint32 v)
1121 {
1122         common_flags2 |= v;
1123 }
1124
1125 void remove_from_common_flags2(uint32 v)
1126 {
1127         common_flags2 &= ~v;
1128 }
1129
1130 void construct_reply_common(const char *inbuf, char *outbuf)
1131 {
1132         set_message(inbuf,outbuf,0,0,False);
1133         
1134         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1135         SIVAL(outbuf,smb_rcls,0);
1136         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1137         SSVAL(outbuf,smb_flg2,
1138                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1139                 common_flags2);
1140         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1141
1142         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1143         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1144         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1145         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1146 }
1147
1148 /****************************************************************************
1149  Construct a chained reply and add it to the already made reply
1150 ****************************************************************************/
1151
1152 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1153 {
1154         static char *orig_inbuf;
1155         static char *orig_outbuf;
1156         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1157         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1158         char *inbuf2, *outbuf2;
1159         int outsize2;
1160         int new_size;
1161         char inbuf_saved[smb_wct];
1162         char outbuf_saved[smb_wct];
1163         int outsize = smb_len(outbuf) + 4;
1164
1165         /* Maybe its not chained, or it's an error packet. */
1166         if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1167                 SCVAL(outbuf,smb_vwv0,0xFF);
1168                 return outsize;
1169         }
1170
1171         if (chain_size == 0) {
1172                 /* this is the first part of the chain */
1173                 orig_inbuf = inbuf;
1174                 orig_outbuf = outbuf;
1175         }
1176
1177         /*
1178          * The original Win95 redirector dies on a reply to
1179          * a lockingX and read chain unless the chain reply is
1180          * 4 byte aligned. JRA.
1181          */
1182
1183         outsize = (outsize + 3) & ~3;
1184
1185         /* we need to tell the client where the next part of the reply will be */
1186         SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1187         SCVAL(outbuf,smb_vwv0,smb_com2);
1188
1189         /* remember how much the caller added to the chain, only counting stuff
1190                 after the parameter words */
1191         chain_size += outsize - smb_wct;
1192
1193         /* work out pointers into the original packets. The
1194                 headers on these need to be filled in */
1195         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1196         outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1197
1198         /* remember the original command type */
1199         smb_com1 = CVAL(orig_inbuf,smb_com);
1200
1201         /* save the data which will be overwritten by the new headers */
1202         memcpy(inbuf_saved,inbuf2,smb_wct);
1203         memcpy(outbuf_saved,outbuf2,smb_wct);
1204
1205         /* give the new packet the same header as the last part of the SMB */
1206         memmove(inbuf2,inbuf,smb_wct);
1207
1208         /* create the in buffer */
1209         SCVAL(inbuf2,smb_com,smb_com2);
1210
1211         /* work out the new size for the in buffer. */
1212         new_size = size - (inbuf2 - inbuf);
1213         if (new_size < 0) {
1214                 DEBUG(0,("chain_reply: chain packet size incorrect "
1215                          "(orig size = %d, offset = %d)\n",
1216                          size, (int)(inbuf2 - inbuf) ));
1217                 exit_server_cleanly("Bad chained packet");
1218                 return(-1);
1219         }
1220
1221         /* And set it in the header. */
1222         smb_setlen(inbuf, 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         /*
1410          * Now we are root, check if the log files need pruning.
1411          * Force a log file check.
1412          */
1413         force_check_log_size();
1414         check_log_size();
1415
1416         /* Send any queued printer notify message to interested smbd's. */
1417
1418         print_notify_send_messages(smbd_messaging_context(), 0);
1419
1420         /*
1421          * Modify the select timeout depending upon
1422          * what we have remaining in our queues.
1423          */
1424
1425         *select_timeout = setup_select_timeout();
1426
1427         return True;
1428 }
1429
1430 /****************************************************************************
1431  Accessor functions for InBuffer, OutBuffer.
1432 ****************************************************************************/
1433
1434 char *get_InBuffer(void)
1435 {
1436         return InBuffer;
1437 }
1438
1439 char *get_OutBuffer(void)
1440 {
1441         return OutBuffer;
1442 }
1443
1444 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1445
1446 /****************************************************************************
1447  Allocate a new InBuffer. Returns the new and old ones.
1448 ****************************************************************************/
1449
1450 static char *NewInBuffer(char **old_inbuf)
1451 {
1452         char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1453         if (!new_inbuf) {
1454                 return NULL;
1455         }
1456         if (old_inbuf) {
1457                 *old_inbuf = InBuffer;
1458         }
1459         InBuffer = new_inbuf;
1460 #if defined(DEVELOPER)
1461         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1462 #endif
1463         return InBuffer;
1464 }
1465
1466 /****************************************************************************
1467  Allocate a new OutBuffer. Returns the new and old ones.
1468 ****************************************************************************/
1469
1470 static char *NewOutBuffer(char **old_outbuf)
1471 {
1472         char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1473         if (!new_outbuf) {
1474                 return NULL;
1475         }
1476         if (old_outbuf) {
1477                 *old_outbuf = OutBuffer;
1478         }
1479         OutBuffer = new_outbuf;
1480 #if defined(DEVELOPER)
1481         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1482 #endif
1483         return OutBuffer;
1484 }
1485
1486 /****************************************************************************
1487  Process commands from the client
1488 ****************************************************************************/
1489
1490 void smbd_process(void)
1491 {
1492         time_t last_timeout_processing_time = time(NULL);
1493         unsigned int num_smbs = 0;
1494
1495         /* Allocate the primary Inbut/Output buffers. */
1496
1497         if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) 
1498                 return;
1499
1500         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1501
1502         while (True) {
1503                 int select_timeout = setup_select_timeout();
1504                 int num_echos;
1505
1506                 errno = 0;      
1507                 
1508                 /* free up temporary memory */
1509                 lp_TALLOC_FREE();
1510                 main_loop_TALLOC_FREE();
1511
1512                 /* Did someone ask for immediate checks on things like blocking locks ? */
1513                 if (select_timeout == 0) {
1514                         if(!timeout_processing(&select_timeout,
1515                                                &last_timeout_processing_time))
1516                                 return;
1517                         num_smbs = 0; /* Reset smb counter. */
1518                 }
1519
1520                 run_events(smbd_event_context(), 0, NULL, NULL);
1521
1522 #if defined(DEVELOPER)
1523                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1524 #endif
1525
1526                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1527                         if(!timeout_processing(&select_timeout,
1528                                                &last_timeout_processing_time))
1529                                 return;
1530                         num_smbs = 0; /* Reset smb counter. */
1531                 }
1532
1533                 /*
1534                  * Ensure we do timeout processing if the SMB we just got was
1535                  * only an echo request. This allows us to set the select
1536                  * timeout in 'receive_message_or_smb()' to any value we like
1537                  * without worrying that the client will send echo requests
1538                  * faster than the select timeout, thus starving out the
1539                  * essential processing (change notify, blocking locks) that
1540                  * the timeout code does. JRA.
1541                  */ 
1542                 num_echos = smb_echo_count;
1543
1544                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1545
1546                 process_smb(InBuffer, OutBuffer);
1547
1548                 if (smb_echo_count != num_echos) {
1549                         if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
1550                                 return;
1551                         num_smbs = 0; /* Reset smb counter. */
1552                 }
1553
1554                 num_smbs++;
1555
1556                 /*
1557                  * If we are getting smb requests in a constant stream
1558                  * with no echos, make sure we attempt timeout processing
1559                  * every select_timeout milliseconds - but only check for this
1560                  * every 200 smb requests.
1561                  */
1562                 
1563                 if ((num_smbs % 200) == 0) {
1564                         time_t new_check_time = time(NULL);
1565                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1566                                 if(!timeout_processing(
1567                                            &select_timeout,
1568                                            &last_timeout_processing_time))
1569                                         return;
1570                                 num_smbs = 0; /* Reset smb counter. */
1571                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1572                         }
1573                 }
1574
1575                 /* The timeout_processing function isn't run nearly
1576                    often enough to implement 'max log size' without
1577                    overrunning the size of the file by many megabytes.
1578                    This is especially true if we are running at debug
1579                    level 10.  Checking every 50 SMBs is a nice
1580                    tradeoff of performance vs log file size overrun. */
1581
1582                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1583                         change_to_root_user();
1584                         check_log_size();
1585                 }
1586         }
1587 }