source: branches/samba-3.0/source/smbd/process.c@ 468

Last change on this file since 468 was 468, checked in by Herwig Bauernfeind, 15 years ago

Update Samba 3.0 with CVE-2010-2063 security patch

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