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

Last change on this file since 347 was 336, checked in by Herwig Bauernfeind, 16 years ago

Update 3.0 to 3.0.37 (unsupported security update)

File size: 49.8 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 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1163 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1164 char *inbuf2, *outbuf2;
1165 int outsize2;
1166 int new_size;
1167 char inbuf_saved[smb_wct];
1168 char outbuf_saved[smb_wct];
1169 int outsize = smb_len(outbuf) + 4;
1170
1171 /* Maybe its not chained, or it's an error packet. */
1172 if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1173 SCVAL(outbuf,smb_vwv0,0xFF);
1174 return outsize;
1175 }
1176
1177 if (chain_size == 0) {
1178 /* this is the first part of the chain */
1179 orig_inbuf = inbuf;
1180 orig_outbuf = outbuf;
1181 }
1182
1183 /*
1184 * The original Win95 redirector dies on a reply to
1185 * a lockingX and read chain unless the chain reply is
1186 * 4 byte aligned. JRA.
1187 */
1188
1189 outsize = (outsize + 3) & ~3;
1190
1191 /* we need to tell the client where the next part of the reply will be */
1192 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1193 SCVAL(outbuf,smb_vwv0,smb_com2);
1194
1195 /* remember how much the caller added to the chain, only counting stuff
1196 after the parameter words */
1197 chain_size += outsize - smb_wct;
1198
1199 /* work out pointers into the original packets. The
1200 headers on these need to be filled in */
1201 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1202 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1203
1204 /* remember the original command type */
1205 smb_com1 = CVAL(orig_inbuf,smb_com);
1206
1207 /* save the data which will be overwritten by the new headers */
1208 memcpy(inbuf_saved,inbuf2,smb_wct);
1209 memcpy(outbuf_saved,outbuf2,smb_wct);
1210
1211 /* give the new packet the same header as the last part of the SMB */
1212 memmove(inbuf2,inbuf,smb_wct);
1213
1214 /* create the in buffer */
1215 SCVAL(inbuf2,smb_com,smb_com2);
1216
1217 /* work out the new size for the in buffer. */
1218 new_size = size - (inbuf2 - inbuf);
1219 if (new_size < 0) {
1220 DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, "
1221 "offset = %d)\n",
1222 size,
1223 (inbuf2 - inbuf) ));
1224 exit_server_cleanly("Bad chained packet");
1225 return(-1);
1226 }
1227
1228 /* And set it in the header. */
1229 smb_setlen(inbuf2, new_size);
1230
1231 /* create the out buffer */
1232 construct_reply_common(inbuf2, outbuf2);
1233
1234 DEBUG(3,("Chained message\n"));
1235 show_msg(inbuf2);
1236
1237 /* process the request */
1238 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size,
1239 bufsize-chain_size);
1240
1241 /* copy the new reply and request headers over the old ones, but
1242 preserve the smb_com field */
1243 memmove(orig_outbuf,outbuf2,smb_wct);
1244 SCVAL(orig_outbuf,smb_com,smb_com1);
1245
1246 /* restore the saved data, being careful not to overwrite any
1247 data from the reply header */
1248 memcpy(inbuf2,inbuf_saved,smb_wct);
1249
1250 {
1251 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1252 if (ofs < 0) {
1253 ofs = 0;
1254 }
1255 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1256 }
1257
1258 return outsize2;
1259}
1260
1261/****************************************************************************
1262 Setup the needed select timeout in milliseconds.
1263****************************************************************************/
1264
1265static int setup_select_timeout(void)
1266{
1267 int select_timeout;
1268
1269 select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000);
1270
1271 if (print_notify_messages_pending()) {
1272 select_timeout = MIN(select_timeout, 1000);
1273 }
1274
1275 return select_timeout;
1276}
1277
1278/****************************************************************************
1279 Check if services need reloading.
1280****************************************************************************/
1281
1282void check_reload(time_t t)
1283{
1284 static pid_t mypid = 0;
1285 static time_t last_smb_conf_reload_time = 0;
1286 static time_t last_printer_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_printer_reload_time = t - printcap_cache_time + 60;
1296 else
1297 last_printer_reload_time = t;
1298 }
1299
1300 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1301 /* randomize over 60 second the printcap reload to avoid all
1302 * process hitting cupsd at the same time */
1303 int time_range = 60;
1304
1305 last_printer_reload_time += random() % time_range;
1306 mypid = getpid();
1307 }
1308
1309 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1310 reload_services(True);
1311 reload_after_sighup = False;
1312 last_smb_conf_reload_time = t;
1313 }
1314
1315 /* 'printcap cache time = 0' disable the feature */
1316
1317 if ( printcap_cache_time != 0 )
1318 {
1319 /* see if it's time to reload or if the clock has been set back */
1320
1321 if ( (t >= last_printer_reload_time+printcap_cache_time)
1322 || (t-last_printer_reload_time < 0) )
1323 {
1324 DEBUG( 3,( "Printcap cache time expired.\n"));
1325 reload_printers();
1326 last_printer_reload_time = t;
1327 }
1328 }
1329}
1330
1331/****************************************************************************
1332 Process any timeout housekeeping. Return False if the caller should exit.
1333****************************************************************************/
1334
1335static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1336{
1337 static time_t last_keepalive_sent_time = 0;
1338 static time_t last_idle_closed_check = 0;
1339 time_t t;
1340 BOOL allidle = True;
1341
1342 if (smb_read_error == READ_EOF) {
1343 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1344 return False;
1345 }
1346
1347 if (smb_read_error == READ_ERROR) {
1348 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1349 strerror(errno)));
1350 return False;
1351 }
1352
1353 if (smb_read_error == READ_BAD_SIG) {
1354 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1355 return False;
1356 }
1357
1358 *last_timeout_processing_time = t = time(NULL);
1359
1360 if(last_keepalive_sent_time == 0)
1361 last_keepalive_sent_time = t;
1362
1363 if(last_idle_closed_check == 0)
1364 last_idle_closed_check = t;
1365
1366 /* become root again if waiting */
1367 change_to_root_user();
1368
1369 /* run all registered idle events */
1370 smb_run_idle_events(t);
1371
1372 /* check if we need to reload services */
1373 check_reload(t);
1374
1375 /* automatic timeout if all connections are closed */
1376 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1377 DEBUG( 2, ( "Closing idle connection\n" ) );
1378 return False;
1379 } else {
1380 last_idle_closed_check = t;
1381 }
1382
1383 if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1384 if (!send_keepalive(smbd_server_fd())) {
1385 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1386 return False;
1387 }
1388
1389 /* send a keepalive for a password server or the like.
1390 This is attached to the auth_info created in the
1391 negprot */
1392 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
1393 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1394
1395 negprot_global_auth_context->challenge_set_method->send_keepalive
1396 (&negprot_global_auth_context->challenge_set_method->private_data);
1397 }
1398
1399 last_keepalive_sent_time = t;
1400 }
1401
1402 /* check for connection timeouts */
1403 allidle = conn_idle_all(t, deadtime);
1404
1405 if (allidle && conn_num_open()>0) {
1406 DEBUG(2,("Closing idle connection 2.\n"));
1407 return False;
1408 }
1409
1410 if(global_machine_password_needs_changing &&
1411 /* for ADS we need to do a regular ADS password change, not a domain
1412 password change */
1413 lp_security() == SEC_DOMAIN) {
1414
1415 unsigned char trust_passwd_hash[16];
1416 time_t lct;
1417
1418 /*
1419 * We're in domain level security, and the code that
1420 * read the machine password flagged that the machine
1421 * password needs changing.
1422 */
1423
1424 /*
1425 * First, open the machine password file with an exclusive lock.
1426 */
1427
1428 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1429 DEBUG(0,("process: unable to lock the machine account password for \
1430machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1431 return True;
1432 }
1433
1434 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1435 DEBUG(0,("process: unable to read the machine account password for \
1436machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1437 secrets_lock_trust_account_password(lp_workgroup(), False);
1438 return True;
1439 }
1440
1441 /*
1442 * Make sure someone else hasn't already done this.
1443 */
1444
1445 if(t < lct + lp_machine_password_timeout()) {
1446 global_machine_password_needs_changing = False;
1447 secrets_lock_trust_account_password(lp_workgroup(), False);
1448 return True;
1449 }
1450
1451 /* always just contact the PDC here */
1452
1453 change_trust_account_password( lp_workgroup(), NULL);
1454 global_machine_password_needs_changing = False;
1455 secrets_lock_trust_account_password(lp_workgroup(), False);
1456 }
1457
1458 /*
1459 * Check to see if we have any blocking locks
1460 * outstanding on the queue.
1461 */
1462 process_blocking_lock_queue();
1463
1464 /* update printer queue caches if necessary */
1465
1466 update_monitored_printq_cache();
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 Accessor functions for InBuffer, OutBuffer.
1491****************************************************************************/
1492
1493char *get_InBuffer(void)
1494{
1495 return InBuffer;
1496}
1497
1498char *get_OutBuffer(void)
1499{
1500 return OutBuffer;
1501}
1502
1503const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1504
1505/****************************************************************************
1506 Allocate a new InBuffer. Returns the new and old ones.
1507****************************************************************************/
1508
1509static char *NewInBuffer(char **old_inbuf)
1510{
1511 char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1512 if (!new_inbuf) {
1513 return NULL;
1514 }
1515 if (old_inbuf) {
1516 *old_inbuf = InBuffer;
1517 }
1518 InBuffer = new_inbuf;
1519#if defined(DEVELOPER)
1520 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1521#endif
1522 return InBuffer;
1523}
1524
1525/****************************************************************************
1526 Allocate a new OutBuffer. Returns the new and old ones.
1527****************************************************************************/
1528
1529static char *NewOutBuffer(char **old_outbuf)
1530{
1531 char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1532 if (!new_outbuf) {
1533 return NULL;
1534 }
1535 if (old_outbuf) {
1536 *old_outbuf = OutBuffer;
1537 }
1538 OutBuffer = new_outbuf;
1539#if defined(DEVELOPER)
1540 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1541#endif
1542 return OutBuffer;
1543}
1544
1545/****************************************************************************
1546 Process commands from the client
1547****************************************************************************/
1548
1549void smbd_process(void)
1550{
1551 time_t last_timeout_processing_time = time(NULL);
1552 unsigned int num_smbs = 0;
1553
1554 /* Allocate the primary Inbut/Output buffers. */
1555
1556 if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL))
1557 return;
1558
1559 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1560
1561 while (True) {
1562 int deadtime = lp_deadtime()*60;
1563 int select_timeout = setup_select_timeout();
1564 int num_echos;
1565
1566 if (deadtime <= 0)
1567 deadtime = DEFAULT_SMBD_TIMEOUT;
1568
1569 errno = 0;
1570
1571 /* free up temporary memory */
1572 lp_TALLOC_FREE();
1573 main_loop_TALLOC_FREE();
1574
1575 /* Did someone ask for immediate checks on things like blocking locks ? */
1576 if (select_timeout == 0) {
1577 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1578 return;
1579 num_smbs = 0; /* Reset smb counter. */
1580 }
1581
1582 run_events(smbd_event_context(), 0, NULL, NULL);
1583
1584#if defined(DEVELOPER)
1585 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1586#endif
1587
1588 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1589 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1590 return;
1591 num_smbs = 0; /* Reset smb counter. */
1592 }
1593
1594 /*
1595 * Ensure we do timeout processing if the SMB we just got was
1596 * only an echo request. This allows us to set the select
1597 * timeout in 'receive_message_or_smb()' to any value we like
1598 * without worrying that the client will send echo requests
1599 * faster than the select timeout, thus starving out the
1600 * essential processing (change notify, blocking locks) that
1601 * the timeout code does. JRA.
1602 */
1603 num_echos = smb_echo_count;
1604
1605 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1606
1607 process_smb(InBuffer, OutBuffer);
1608
1609 if (smb_echo_count != num_echos) {
1610 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1611 return;
1612 num_smbs = 0; /* Reset smb counter. */
1613 }
1614
1615 num_smbs++;
1616
1617 /*
1618 * If we are getting smb requests in a constant stream
1619 * with no echos, make sure we attempt timeout processing
1620 * every select_timeout milliseconds - but only check for this
1621 * every 200 smb requests.
1622 */
1623
1624 if ((num_smbs % 200) == 0) {
1625 time_t new_check_time = time(NULL);
1626 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1627 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1628 return;
1629 num_smbs = 0; /* Reset smb counter. */
1630 last_timeout_processing_time = new_check_time; /* Reset time. */
1631 }
1632 }
1633
1634 /* The timeout_processing function isn't run nearly
1635 often enough to implement 'max log size' without
1636 overrunning the size of the file by many megabytes.
1637 This is especially true if we are running at debug
1638 level 10. Checking every 50 SMBs is a nice
1639 tradeoff of performance vs log file size overrun. */
1640
1641 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1642 change_to_root_user();
1643 check_log_size();
1644 }
1645 }
1646}
Note: See TracBrowser for help on using the repository browser.