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