r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/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 wct = CVAL(outbuf,smb_wct);
1181         int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
1182
1183         /* maybe its not chained */
1184         if (smb_com2 == 0xFF) {
1185                 SCVAL(outbuf,smb_vwv0,0xFF);
1186                 return outsize;
1187         }
1188
1189         if (chain_size == 0) {
1190                 /* this is the first part of the chain */
1191                 orig_inbuf = inbuf;
1192                 orig_outbuf = outbuf;
1193         }
1194
1195         /*
1196          * The original Win95 redirector dies on a reply to
1197          * a lockingX and read chain unless the chain reply is
1198          * 4 byte aligned. JRA.
1199          */
1200
1201         outsize = (outsize + 3) & ~3;
1202
1203         /* we need to tell the client where the next part of the reply will be */
1204         SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1205         SCVAL(outbuf,smb_vwv0,smb_com2);
1206
1207         /* remember how much the caller added to the chain, only counting stuff
1208                 after the parameter words */
1209         chain_size += outsize - smb_wct;
1210
1211         /* work out pointers into the original packets. The
1212                 headers on these need to be filled in */
1213         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1214         outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1215
1216         /* remember the original command type */
1217         smb_com1 = CVAL(orig_inbuf,smb_com);
1218
1219         /* save the data which will be overwritten by the new headers */
1220         memcpy(inbuf_saved,inbuf2,smb_wct);
1221         memcpy(outbuf_saved,outbuf2,smb_wct);
1222
1223         /* give the new packet the same header as the last part of the SMB */
1224         memmove(inbuf2,inbuf,smb_wct);
1225
1226         /* create the in buffer */
1227         SCVAL(inbuf2,smb_com,smb_com2);
1228
1229         /* create the out buffer */
1230         construct_reply_common(inbuf2, outbuf2);
1231
1232         DEBUG(3,("Chained message\n"));
1233         show_msg(inbuf2);
1234
1235         /* process the request */
1236         outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1237                                 bufsize-chain_size);
1238
1239         /* copy the new reply and request headers over the old ones, but
1240                 preserve the smb_com field */
1241         memmove(orig_outbuf,outbuf2,smb_wct);
1242         SCVAL(orig_outbuf,smb_com,smb_com1);
1243
1244         /* restore the saved data, being careful not to overwrite any
1245                 data from the reply header */
1246         memcpy(inbuf2,inbuf_saved,smb_wct);
1247
1248         {
1249                 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1250                 if (ofs < 0) ofs = 0;
1251                         memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1252         }
1253
1254         return outsize2;
1255 }
1256
1257 /****************************************************************************
1258  Setup the needed select timeout.
1259 ****************************************************************************/
1260
1261 static int setup_select_timeout(void)
1262 {
1263         int select_timeout;
1264         int t;
1265
1266         select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1267         select_timeout *= 1000;
1268
1269         t = change_notify_timeout();
1270         if (t != -1)
1271                 select_timeout = MIN(select_timeout, t*1000);
1272
1273         if (print_notify_messages_pending())
1274                 select_timeout = MIN(select_timeout, 1000);
1275
1276         return select_timeout;
1277 }
1278
1279 /****************************************************************************
1280  Check if services need reloading.
1281 ****************************************************************************/
1282
1283 void check_reload(int t)
1284 {
1285         static time_t last_smb_conf_reload_time = 0;
1286         static time_t last_load_printers_reload_time = 0;
1287         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1288
1289         if(last_smb_conf_reload_time == 0) {
1290                 last_smb_conf_reload_time = t;
1291                 /* Our printing subsystem might not be ready at smbd start up.
1292                    Then no printer is available till the first printers check
1293                    is performed.  A lower initial interval circumvents this. */
1294                 if ( printcap_cache_time > 60 )
1295                         last_load_printers_reload_time = t - printcap_cache_time + 60;
1296                 else
1297                         last_load_printers_reload_time = t;
1298         }
1299
1300         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1301                 reload_services(True);
1302                 reload_after_sighup = False;
1303                 last_smb_conf_reload_time = t;
1304         }
1305
1306         /* 'printcap cache time = 0' disable the feature */
1307         
1308         if ( printcap_cache_time != 0 )
1309         { 
1310                 /* see if it's time to reload or if the clock has been set back */
1311                 
1312                 if ( (t >= last_load_printers_reload_time+printcap_cache_time) 
1313                         || (t-last_load_printers_reload_time  < 0) ) 
1314                 {
1315                         DEBUG( 3,( "Printcap cache time expired.\n"));
1316                         remove_stale_printers();
1317                         load_printers();
1318                         last_load_printers_reload_time = t;
1319                 }
1320         }
1321 }
1322
1323 /****************************************************************************
1324  Process any timeout housekeeping. Return False if the caller should exit.
1325 ****************************************************************************/
1326
1327 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1328 {
1329         static time_t last_keepalive_sent_time = 0;
1330         static time_t last_idle_closed_check = 0;
1331         time_t t;
1332         BOOL allidle = True;
1333         extern int keepalive;
1334
1335         if (smb_read_error == READ_EOF) {
1336                 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1337                 return False;
1338         }
1339
1340         if (smb_read_error == READ_ERROR) {
1341                 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1342                         strerror(errno)));
1343                 return False;
1344         }
1345
1346         if (smb_read_error == READ_BAD_SIG) {
1347                 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1348                 return False;
1349         }
1350
1351         *last_timeout_processing_time = t = time(NULL);
1352
1353         if(last_keepalive_sent_time == 0)
1354                 last_keepalive_sent_time = t;
1355
1356         if(last_idle_closed_check == 0)
1357                 last_idle_closed_check = t;
1358
1359         /* become root again if waiting */
1360         change_to_root_user();
1361
1362         /* run all registered idle events */
1363         smb_run_idle_events(t);
1364
1365         /* check if we need to reload services */
1366         check_reload(t);
1367
1368         /* automatic timeout if all connections are closed */      
1369         if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1370                 DEBUG( 2, ( "Closing idle connection\n" ) );
1371                 return False;
1372         } else {
1373                 last_idle_closed_check = t;
1374         }
1375
1376         if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1377                 extern struct auth_context *negprot_global_auth_context;
1378                 if (!send_keepalive(smbd_server_fd())) {
1379                         DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1380                         return False;
1381                 }
1382
1383                 /* send a keepalive for a password server or the like.
1384                         This is attached to the auth_info created in the
1385                 negprot */
1386                 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method 
1387                                 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1388
1389                         negprot_global_auth_context->challenge_set_method->send_keepalive
1390                         (&negprot_global_auth_context->challenge_set_method->private_data);
1391                 }
1392
1393                 last_keepalive_sent_time = t;
1394         }
1395
1396         /* check for connection timeouts */
1397         allidle = conn_idle_all(t, deadtime);
1398
1399         if (allidle && conn_num_open()>0) {
1400                 DEBUG(2,("Closing idle connection 2.\n"));
1401                 return False;
1402         }
1403
1404         if(global_machine_password_needs_changing && 
1405                         /* for ADS we need to do a regular ADS password change, not a domain
1406                                         password change */
1407                         lp_security() == SEC_DOMAIN) {
1408
1409                 unsigned char trust_passwd_hash[16];
1410                 time_t lct;
1411
1412                 /*
1413                  * We're in domain level security, and the code that
1414                  * read the machine password flagged that the machine
1415                  * password needs changing.
1416                  */
1417
1418                 /*
1419                  * First, open the machine password file with an exclusive lock.
1420                  */
1421
1422                 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1423                         DEBUG(0,("process: unable to lock the machine account password for \
1424 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1425                         return True;
1426                 }
1427
1428                 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1429                         DEBUG(0,("process: unable to read the machine account password for \
1430 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1431                         secrets_lock_trust_account_password(lp_workgroup(), False);
1432                         return True;
1433                 }
1434
1435                 /*
1436                  * Make sure someone else hasn't already done this.
1437                  */
1438
1439                 if(t < lct + lp_machine_password_timeout()) {
1440                         global_machine_password_needs_changing = False;
1441                         secrets_lock_trust_account_password(lp_workgroup(), False);
1442                         return True;
1443                 }
1444
1445                 /* always just contact the PDC here */
1446     
1447                 change_trust_account_password( lp_workgroup(), NULL);
1448                 global_machine_password_needs_changing = False;
1449                 secrets_lock_trust_account_password(lp_workgroup(), False);
1450         }
1451
1452         /*
1453          * Check to see if we have any blocking locks
1454          * outstanding on the queue.
1455          */
1456         process_blocking_lock_queue(t);
1457
1458         /* update printer queue caches if necessary */
1459   
1460         update_monitored_printq_cache();
1461   
1462         /*
1463          * Check to see if we have any change notifies 
1464          * outstanding on the queue.
1465          */
1466         process_pending_change_notify_queue(t);
1467
1468         /*
1469          * Now we are root, check if the log files need pruning.
1470          * Force a log file check.
1471          */
1472         force_check_log_size();
1473         check_log_size();
1474
1475         /* Send any queued printer notify message to interested smbd's. */
1476
1477         print_notify_send_messages(0);
1478
1479         /*
1480          * Modify the select timeout depending upon
1481          * what we have remaining in our queues.
1482          */
1483
1484         *select_timeout = setup_select_timeout();
1485
1486         return True;
1487 }
1488
1489 /****************************************************************************
1490   process commands from the client
1491 ****************************************************************************/
1492
1493 void smbd_process(void)
1494 {
1495         extern int smb_echo_count;
1496         time_t last_timeout_processing_time = time(NULL);
1497         unsigned int num_smbs = 0;
1498         const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN;
1499
1500         InBuffer = (char *)SMB_MALLOC(total_buffer_size);
1501         OutBuffer = (char *)SMB_MALLOC(total_buffer_size);
1502         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
1503                 return;
1504
1505 #if defined(DEVELOPER)
1506         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1507         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1508 #endif
1509
1510         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1511
1512         while (True) {
1513                 int deadtime = lp_deadtime()*60;
1514                 int select_timeout = setup_select_timeout();
1515                 int num_echos;
1516
1517                 if (deadtime <= 0)
1518                         deadtime = DEFAULT_SMBD_TIMEOUT;
1519
1520                 errno = 0;      
1521                 
1522                 /* free up temporary memory */
1523                 lp_talloc_free();
1524                 main_loop_talloc_free();
1525
1526                 /* run all registered idle events */
1527                 smb_run_idle_events(time(NULL));
1528
1529
1530                 /* Did someone ask for immediate checks on things like blocking locks ? */
1531                 if (select_timeout == 0) {
1532                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1533                                 return;
1534                         num_smbs = 0; /* Reset smb counter. */
1535                 }
1536
1537 #if defined(DEVELOPER)
1538                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1539 #endif
1540
1541                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1542                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1543                                 return;
1544                         num_smbs = 0; /* Reset smb counter. */
1545                 }
1546
1547                 /*
1548                  * Ensure we do timeout processing if the SMB we just got was
1549                  * only an echo request. This allows us to set the select
1550                  * timeout in 'receive_message_or_smb()' to any value we like
1551                  * without worrying that the client will send echo requests
1552                  * faster than the select timeout, thus starving out the
1553                  * essential processing (change notify, blocking locks) that
1554                  * the timeout code does. JRA.
1555                  */ 
1556                 num_echos = smb_echo_count;
1557
1558                 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1559
1560                 process_smb(InBuffer, OutBuffer);
1561
1562                 if (smb_echo_count != num_echos) {
1563                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1564                                 return;
1565                         num_smbs = 0; /* Reset smb counter. */
1566                 }
1567
1568                 num_smbs++;
1569
1570                 /*
1571                  * If we are getting smb requests in a constant stream
1572                  * with no echos, make sure we attempt timeout processing
1573                  * every select_timeout milliseconds - but only check for this
1574                  * every 200 smb requests.
1575                  */
1576                 
1577                 if ((num_smbs % 200) == 0) {
1578                         time_t new_check_time = time(NULL);
1579                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1580                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1581                                         return;
1582                                 num_smbs = 0; /* Reset smb counter. */
1583                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1584                         }
1585                 }
1586
1587                 /* The timeout_processing function isn't run nearly
1588                    often enough to implement 'max log size' without
1589                    overrunning the size of the file by many megabytes.
1590                    This is especially true if we are running at debug
1591                    level 10.  Checking every 50 SMBs is a nice
1592                    tradeoff of performance vs log file size overrun. */
1593
1594                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1595                         change_to_root_user();
1596                         check_log_size();
1597                 }
1598         }
1599 }