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