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