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