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