3 Unix SMB/Netbios implementation.
5 process incoming packets - main loop
6 Copyright (C) Andrew Tridgell 1992-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern int DEBUGLEVEL;
27 struct timeval smb_last_time;
29 static char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
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.
38 int max_send = BUFFER_SIZE;
40 * Size of the data we can receive. Set by us.
41 * Can be modified by the max xmit parameter.
43 int max_recv = BUFFER_SIZE;
45 extern int last_message;
46 extern int global_oplock_break;
47 extern userdom_struct current_user_info;
48 extern char *last_inbuf;
49 extern char *InBuffer;
50 extern char *OutBuffer;
51 extern int smb_read_error;
52 extern VOLATILE SIG_ATOMIC_T reload_after_sighup;
53 extern BOOL global_machine_password_needs_changing;
54 extern fstring global_myworkgroup;
55 extern pstring global_myname;
58 /****************************************************************************
59 structure to hold a linked list of queued messages.
61 ****************************************************************************/
67 } pending_message_list;
69 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
71 /****************************************************************************
72 Function to push a message onto the tail of a linked list of smb messages ready
74 ****************************************************************************/
76 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
78 pending_message_list *msg = (pending_message_list *)
79 malloc(sizeof(pending_message_list));
83 DEBUG(0,("push_message: malloc fail (1)\n"));
87 msg->msg_buf = (char *)malloc(msg_len);
88 if(msg->msg_buf == NULL)
90 DEBUG(0,("push_message: malloc fail (2)\n"));
95 memcpy(msg->msg_buf, buf, msg_len);
96 msg->msg_len = msg_len;
98 ubi_slAddTail( list_head, msg);
103 /****************************************************************************
104 Function to push a smb message onto a linked list of local smb messages ready
106 ****************************************************************************/
108 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
110 return push_message(&smb_oplock_queue, buf, msg_len);
113 /****************************************************************************
114 do all async processing in here. This includes UDB oplock messages, kernel
115 oplock messages, change notify events etc.
116 ****************************************************************************/
117 static void async_processing(fd_set *fds, char *buffer, int buffer_len)
119 /* check for oplock messages (both UDP and kernel) */
120 if (receive_local_message(fds, buffer, buffer_len, 0)) {
121 process_local_message(buffer, buffer_len);
124 /* check for async change notify events */
125 process_pending_change_notify_queue(0);
127 /* check for sighup processing */
128 if (reload_after_sighup) {
130 DEBUG(1,("Reloading services after SIGHUP\n"));
131 reload_services(False);
132 reload_after_sighup = False;
136 /****************************************************************************
137 Do a select on an two fd's - with timeout.
139 If a local udp message has been pushed onto the
140 queue (this can only happen during oplock break
141 processing) call async_processing()
143 If a pending smb message has been pushed onto the
144 queue (this can only happen during oplock break
145 processing) return this next.
147 If the first smbfd is ready then read an smb from it.
148 if the second (loopback UDP) fd is ready then read a message
149 from it and setup the buffer header to identify the length
151 Returns False on timeout or error.
154 The timeout is in milli seconds
155 ****************************************************************************/
157 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
169 * Note that this call must be before processing any SMB
170 * messages as we need to synchronously process any messages
171 * we may have sent to ourselves from the previous SMB.
176 * Check to see if we already have a message on the smb queue.
177 * If so - copy and return it.
179 if(ubi_slCount(&smb_oplock_queue) != 0) {
180 pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
181 memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
183 /* Free the message we just copied. */
184 free((char *)msg->msg_buf);
187 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
193 * Setup the select read fd set.
197 FD_SET(smbd_server_fd(),&fds);
198 maxfd = setup_oplock_select_set(&fds);
200 to.tv_sec = timeout / 1000;
201 to.tv_usec = (timeout % 1000) * 1000;
203 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
205 /* if we get EINTR then maybe we have received an oplock
206 signal - treat this as select returning 1. This is ugly, but
207 is the best we can do until the oplock code knows more about
209 if (selrtn == -1 && errno == EINTR) {
210 async_processing(&fds, buffer, buffer_len);
216 /* something is wrong. Maybe the socket is dead? */
217 smb_read_error = READ_ERROR;
221 /* Did we timeout ? */
223 smb_read_error = READ_TIMEOUT;
227 if (!FD_ISSET(smbd_server_fd(),&fds) || selrtn > 1) {
228 async_processing(&fds, buffer, buffer_len);
229 if (!FD_ISSET(smbd_server_fd(),&fds)) goto again;
232 return receive_smb(smbd_server_fd(), buffer, 0);
235 /****************************************************************************
236 Get the next SMB packet, doing the local message processing automatically.
237 ****************************************************************************/
239 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
245 ret = receive_message_or_smb(inbuf,bufsize,timeout);
247 got_keepalive = (ret && (CVAL(inbuf,0) == 0x85));
248 } while (ret && got_keepalive);
253 /****************************************************************************
254 We're terminating and have closed all our files/connections etc.
255 If there are any pending local messages we need to respond to them
256 before termination so that other smbds don't think we just died whilst
258 ****************************************************************************/
260 void respond_to_all_remaining_local_messages(void)
266 * Assert we have no exclusive open oplocks.
269 if(get_number_of_exclusive_open_oplocks()) {
270 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
271 get_number_of_exclusive_open_oplocks() ));
276 * Setup the select read fd set.
280 if(!setup_oplock_select_set(&fds))
284 * Keep doing receive_local_message with a 1 ms timeout until
285 * we have no more messages.
287 while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
288 /* Deal with oplock break requests from other smbd's. */
289 process_local_message(buffer, sizeof(buffer));
292 (void)setup_oplock_select_set(&fds);
300 These flags determine some of the permissions required to do an operation
302 Note that I don't set NEED_WRITE on some write operations because they
303 are used by some brain-dead clients when printing, and I don't want to
304 force write permissions on print services.
306 #define AS_USER (1<<0)
307 #define NEED_WRITE (1<<1)
308 #define TIME_INIT (1<<2)
309 #define CAN_IPC (1<<3)
310 #define AS_GUEST (1<<5)
311 #define QUEUE_IN_OPLOCK (1<<6)
314 define a list of possible SMB messages and their corresponding
315 functions. Any message that has a NULL function is unimplemented -
316 please feel free to contribute implementations!
318 struct smb_message_struct
321 int (*fn)(connection_struct *conn, char *, char *, int, int);
324 smb_messages[256] = {
326 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
327 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
328 /* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
329 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
330 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
331 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
332 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
333 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
334 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
335 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
336 /* 0x0a */ { "SMBread",reply_read,AS_USER},
337 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
338 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
339 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
340 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
341 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
342 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
343 /* 0x11 */ { "SMBexit",reply_exit,0},
344 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
345 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
346 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
347 /* 0x15 */ { NULL, NULL, 0 },
348 /* 0x16 */ { NULL, NULL, 0 },
349 /* 0x17 */ { NULL, NULL, 0 },
350 /* 0x18 */ { NULL, NULL, 0 },
351 /* 0x19 */ { NULL, NULL, 0 },
352 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
353 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
354 /* 0x1c */ { "SMBreadBs",NULL,AS_USER},
355 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
356 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
357 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
358 /* 0x20 */ { "SMBwritec",NULL,AS_USER},
359 /* 0x21 */ { NULL, NULL, 0 },
360 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
361 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
362 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
363 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
364 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
365 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
366 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
367 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
368 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
369 /* 0x2b */ { "SMBecho",reply_echo,0},
370 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
371 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
372 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
373 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
374 /* 0x30 */ { NULL, NULL, 0 },
375 /* 0x31 */ { NULL, NULL, 0 },
376 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
377 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
378 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
379 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
380 /* 0x36 */ { NULL, NULL, 0 },
381 /* 0x37 */ { NULL, NULL, 0 },
382 /* 0x38 */ { NULL, NULL, 0 },
383 /* 0x39 */ { NULL, NULL, 0 },
384 /* 0x3a */ { NULL, NULL, 0 },
385 /* 0x3b */ { NULL, NULL, 0 },
386 /* 0x3c */ { NULL, NULL, 0 },
387 /* 0x3d */ { NULL, NULL, 0 },
388 /* 0x3e */ { NULL, NULL, 0 },
389 /* 0x3f */ { NULL, NULL, 0 },
390 /* 0x40 */ { NULL, NULL, 0 },
391 /* 0x41 */ { NULL, NULL, 0 },
392 /* 0x42 */ { NULL, NULL, 0 },
393 /* 0x43 */ { NULL, NULL, 0 },
394 /* 0x44 */ { NULL, NULL, 0 },
395 /* 0x45 */ { NULL, NULL, 0 },
396 /* 0x46 */ { NULL, NULL, 0 },
397 /* 0x47 */ { NULL, NULL, 0 },
398 /* 0x48 */ { NULL, NULL, 0 },
399 /* 0x49 */ { NULL, NULL, 0 },
400 /* 0x4a */ { NULL, NULL, 0 },
401 /* 0x4b */ { NULL, NULL, 0 },
402 /* 0x4c */ { NULL, NULL, 0 },
403 /* 0x4d */ { NULL, NULL, 0 },
404 /* 0x4e */ { NULL, NULL, 0 },
405 /* 0x4f */ { NULL, NULL, 0 },
406 /* 0x50 */ { NULL, NULL, 0 },
407 /* 0x51 */ { NULL, NULL, 0 },
408 /* 0x52 */ { NULL, NULL, 0 },
409 /* 0x53 */ { NULL, NULL, 0 },
410 /* 0x54 */ { NULL, NULL, 0 },
411 /* 0x55 */ { NULL, NULL, 0 },
412 /* 0x56 */ { NULL, NULL, 0 },
413 /* 0x57 */ { NULL, NULL, 0 },
414 /* 0x58 */ { NULL, NULL, 0 },
415 /* 0x59 */ { NULL, NULL, 0 },
416 /* 0x5a */ { NULL, NULL, 0 },
417 /* 0x5b */ { NULL, NULL, 0 },
418 /* 0x5c */ { NULL, NULL, 0 },
419 /* 0x5d */ { NULL, NULL, 0 },
420 /* 0x5e */ { NULL, NULL, 0 },
421 /* 0x5f */ { NULL, NULL, 0 },
422 /* 0x60 */ { NULL, NULL, 0 },
423 /* 0x61 */ { NULL, NULL, 0 },
424 /* 0x62 */ { NULL, NULL, 0 },
425 /* 0x63 */ { NULL, NULL, 0 },
426 /* 0x64 */ { NULL, NULL, 0 },
427 /* 0x65 */ { NULL, NULL, 0 },
428 /* 0x66 */ { NULL, NULL, 0 },
429 /* 0x67 */ { NULL, NULL, 0 },
430 /* 0x68 */ { NULL, NULL, 0 },
431 /* 0x69 */ { NULL, NULL, 0 },
432 /* 0x6a */ { NULL, NULL, 0 },
433 /* 0x6b */ { NULL, NULL, 0 },
434 /* 0x6c */ { NULL, NULL, 0 },
435 /* 0x6d */ { NULL, NULL, 0 },
436 /* 0x6e */ { NULL, NULL, 0 },
437 /* 0x6f */ { NULL, NULL, 0 },
438 /* 0x70 */ { "SMBtcon",reply_tcon,0},
439 /* 0x71 */ { "SMBtdis",reply_tdis,0},
440 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
441 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
442 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
443 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
444 /* 0x76 */ { NULL, NULL, 0 },
445 /* 0x77 */ { NULL, NULL, 0 },
446 /* 0x78 */ { NULL, NULL, 0 },
447 /* 0x79 */ { NULL, NULL, 0 },
448 /* 0x7a */ { NULL, NULL, 0 },
449 /* 0x7b */ { NULL, NULL, 0 },
450 /* 0x7c */ { NULL, NULL, 0 },
451 /* 0x7d */ { NULL, NULL, 0 },
452 /* 0x7e */ { NULL, NULL, 0 },
453 /* 0x7f */ { NULL, NULL, 0 },
454 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
455 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
456 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
457 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
458 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
459 /* 0x85 */ { NULL, NULL, 0 },
460 /* 0x86 */ { NULL, NULL, 0 },
461 /* 0x87 */ { NULL, NULL, 0 },
462 /* 0x88 */ { NULL, NULL, 0 },
463 /* 0x89 */ { NULL, NULL, 0 },
464 /* 0x8a */ { NULL, NULL, 0 },
465 /* 0x8b */ { NULL, NULL, 0 },
466 /* 0x8c */ { NULL, NULL, 0 },
467 /* 0x8d */ { NULL, NULL, 0 },
468 /* 0x8e */ { NULL, NULL, 0 },
469 /* 0x8f */ { NULL, NULL, 0 },
470 /* 0x90 */ { NULL, NULL, 0 },
471 /* 0x91 */ { NULL, NULL, 0 },
472 /* 0x92 */ { NULL, NULL, 0 },
473 /* 0x93 */ { NULL, NULL, 0 },
474 /* 0x94 */ { NULL, NULL, 0 },
475 /* 0x95 */ { NULL, NULL, 0 },
476 /* 0x96 */ { NULL, NULL, 0 },
477 /* 0x97 */ { NULL, NULL, 0 },
478 /* 0x98 */ { NULL, NULL, 0 },
479 /* 0x99 */ { NULL, NULL, 0 },
480 /* 0x9a */ { NULL, NULL, 0 },
481 /* 0x9b */ { NULL, NULL, 0 },
482 /* 0x9c */ { NULL, NULL, 0 },
483 /* 0x9d */ { NULL, NULL, 0 },
484 /* 0x9e */ { NULL, NULL, 0 },
485 /* 0x9f */ { NULL, NULL, 0 },
486 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
487 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
488 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
489 /* 0xa3 */ { NULL, NULL, 0 },
490 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
491 /* 0xa5 */ { NULL, NULL, 0 },
492 /* 0xa6 */ { NULL, NULL, 0 },
493 /* 0xa7 */ { NULL, NULL, 0 },
494 /* 0xa8 */ { NULL, NULL, 0 },
495 /* 0xa9 */ { NULL, NULL, 0 },
496 /* 0xaa */ { NULL, NULL, 0 },
497 /* 0xab */ { NULL, NULL, 0 },
498 /* 0xac */ { NULL, NULL, 0 },
499 /* 0xad */ { NULL, NULL, 0 },
500 /* 0xae */ { NULL, NULL, 0 },
501 /* 0xaf */ { NULL, NULL, 0 },
502 /* 0xb0 */ { NULL, NULL, 0 },
503 /* 0xb1 */ { NULL, NULL, 0 },
504 /* 0xb2 */ { NULL, NULL, 0 },
505 /* 0xb3 */ { NULL, NULL, 0 },
506 /* 0xb4 */ { NULL, NULL, 0 },
507 /* 0xb5 */ { NULL, NULL, 0 },
508 /* 0xb6 */ { NULL, NULL, 0 },
509 /* 0xb7 */ { NULL, NULL, 0 },
510 /* 0xb8 */ { NULL, NULL, 0 },
511 /* 0xb9 */ { NULL, NULL, 0 },
512 /* 0xba */ { NULL, NULL, 0 },
513 /* 0xbb */ { NULL, NULL, 0 },
514 /* 0xbc */ { NULL, NULL, 0 },
515 /* 0xbd */ { NULL, NULL, 0 },
516 /* 0xbe */ { NULL, NULL, 0 },
517 /* 0xbf */ { NULL, NULL, 0 },
518 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
519 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
520 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
521 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
522 /* 0xc4 */ { NULL, NULL, 0 },
523 /* 0xc5 */ { NULL, NULL, 0 },
524 /* 0xc6 */ { NULL, NULL, 0 },
525 /* 0xc7 */ { NULL, NULL, 0 },
526 /* 0xc8 */ { NULL, NULL, 0 },
527 /* 0xc9 */ { NULL, NULL, 0 },
528 /* 0xca */ { NULL, NULL, 0 },
529 /* 0xcb */ { NULL, NULL, 0 },
530 /* 0xcc */ { NULL, NULL, 0 },
531 /* 0xcd */ { NULL, NULL, 0 },
532 /* 0xce */ { NULL, NULL, 0 },
533 /* 0xcf */ { NULL, NULL, 0 },
534 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
535 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
536 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
537 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
538 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
539 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
540 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
541 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
542 /* 0xd8 */ { NULL, NULL, 0 },
543 /* 0xd9 */ { NULL, NULL, 0 },
544 /* 0xda */ { NULL, NULL, 0 },
545 /* 0xdb */ { NULL, NULL, 0 },
546 /* 0xdc */ { NULL, NULL, 0 },
547 /* 0xdd */ { NULL, NULL, 0 },
548 /* 0xde */ { NULL, NULL, 0 },
549 /* 0xdf */ { NULL, NULL, 0 },
550 /* 0xe0 */ { NULL, NULL, 0 },
551 /* 0xe1 */ { NULL, NULL, 0 },
552 /* 0xe2 */ { NULL, NULL, 0 },
553 /* 0xe3 */ { NULL, NULL, 0 },
554 /* 0xe4 */ { NULL, NULL, 0 },
555 /* 0xe5 */ { NULL, NULL, 0 },
556 /* 0xe6 */ { NULL, NULL, 0 },
557 /* 0xe7 */ { NULL, NULL, 0 },
558 /* 0xe8 */ { NULL, NULL, 0 },
559 /* 0xe9 */ { NULL, NULL, 0 },
560 /* 0xea */ { NULL, NULL, 0 },
561 /* 0xeb */ { NULL, NULL, 0 },
562 /* 0xec */ { NULL, NULL, 0 },
563 /* 0xed */ { NULL, NULL, 0 },
564 /* 0xee */ { NULL, NULL, 0 },
565 /* 0xef */ { NULL, NULL, 0 },
566 /* 0xf0 */ { NULL, NULL, 0 },
567 /* 0xf1 */ { NULL, NULL, 0 },
568 /* 0xf2 */ { NULL, NULL, 0 },
569 /* 0xf3 */ { NULL, NULL, 0 },
570 /* 0xf4 */ { NULL, NULL, 0 },
571 /* 0xf5 */ { NULL, NULL, 0 },
572 /* 0xf6 */ { NULL, NULL, 0 },
573 /* 0xf7 */ { NULL, NULL, 0 },
574 /* 0xf8 */ { NULL, NULL, 0 },
575 /* 0xf9 */ { NULL, NULL, 0 },
576 /* 0xfa */ { NULL, NULL, 0 },
577 /* 0xfb */ { NULL, NULL, 0 },
578 /* 0xfc */ { NULL, NULL, 0 },
579 /* 0xfd */ { NULL, NULL, 0 },
580 /* 0xfe */ { NULL, NULL, 0 },
581 /* 0xff */ { NULL, NULL, 0 }
585 /*******************************************************************
587 ********************************************************************/
588 static void smb_dump(char *name, int type, char *data, ssize_t len)
592 if (DEBUGLEVEL < 50) return;
594 if (len < 4) len = smb_len(data)+4;
595 for (i=1;i<100;i++) {
596 slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i,
597 type ? "req" : "resp");
598 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
599 if (fd != -1 || errno != EEXIST) break;
602 write(fd, data, len);
604 DEBUG(0,("created %s len %d\n", fname, len));
609 /****************************************************************************
610 do a switch on the message type, and return the response size
611 ****************************************************************************/
612 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
614 static pid_t pid= (pid_t)-1;
616 extern int global_smbpid;
618 if (pid == (pid_t)-1)
624 /* make sure this is an SMB packet */
625 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
627 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
631 /* yuck! this is an interim measure before we get rid of our
632 current inbuf/outbuf system */
633 global_smbpid = SVAL(inbuf,smb_pid);
635 if (smb_messages[type].fn == NULL)
637 DEBUG(0,("Unknown message type %d!\n",type));
638 smb_dump("Unknown", 1, inbuf, size);
639 outsize = reply_unknown(inbuf,outbuf);
643 int flags = smb_messages[type].flags;
644 static uint16 last_session_tag = UID_FIELD_INVALID;
645 /* In share mode security we must ignore the vuid. */
646 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
647 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
649 DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
651 smb_dump(smb_fn_name(type), 1, inbuf, size);
652 if(global_oplock_break)
654 if(flags & QUEUE_IN_OPLOCK)
657 * Queue this message as we are the process of an oplock break.
660 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
661 DEBUGADD( 2, ( "oplock break state.\n" ) );
663 push_oplock_pending_smb_message( inbuf, size );
668 /* Ensure this value is replaced in the incoming packet. */
669 SSVAL(inbuf,smb_uid,session_tag);
672 * Ensure the correct username is in current_user_info.
673 * This is a really ugly bugfix for problems with
674 * multiple session_setup_and_X's being done and
675 * allowing %U and %G substitutions to work correctly.
676 * There is a reason this code is done here, don't
677 * move it unless you know what you're doing... :-).
681 if (session_tag != last_session_tag) {
682 user_struct *vuser = NULL;
684 last_session_tag = session_tag;
685 if(session_tag != UID_FIELD_INVALID)
686 vuser = get_valid_user_struct(session_tag);
688 current_user_info = vuser->user;
691 /* does this protocol need to be run as root? */
692 if (!(flags & AS_USER))
695 /* does this protocol need to be run as the connected user? */
696 if ((flags & AS_USER) && !become_user(conn,session_tag)) {
697 if (flags & AS_GUEST)
700 return(ERROR(ERRSRV,ERRaccess));
703 /* this code is to work around a bug is MS client 3 without
704 introducing a security hole - it needs to be able to do
705 print queue checks as guest if it isn't logged in properly */
709 /* does it need write permission? */
710 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
711 return(ERROR(ERRSRV,ERRaccess));
713 /* ipc services are limited */
714 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
715 return(ERROR(ERRSRV,ERRaccess));
718 /* load service specific parameters */
719 if (conn && !become_service(conn,(flags & AS_USER)?True:False)) {
720 return(ERROR(ERRSRV,ERRaccess));
723 /* does this protocol need to be run as guest? */
724 if ((flags & AS_GUEST) &&
726 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
727 return(ERROR(ERRSRV,ERRaccess));
732 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
735 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
741 /****************************************************************************
742 construct a reply to the incoming packet
743 ****************************************************************************/
744 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
746 int type = CVAL(inbuf,smb_com);
748 int msg_type = CVAL(inbuf,0);
750 GetTimeOfDay(&smb_last_time);
757 return(reply_special(inbuf,outbuf));
759 construct_reply_common(inbuf, outbuf);
761 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
763 outsize += chain_size;
766 smb_setlen(outbuf,outsize - 4);
771 /****************************************************************************
772 process an smb from the client - split out from the process() code so
773 it can be used by the oplock break code.
774 ****************************************************************************/
775 void process_smb(char *inbuf, char *outbuf)
778 extern BOOL sslEnabled; /* don't use function for performance reasons */
779 static int sslConnected = 0;
780 #endif /* WITH_SSL */
781 static int trans_num;
782 int msg_type = CVAL(inbuf,0);
783 int32 len = smb_len(inbuf);
786 DO_PROFILE_INC(smb_count);
788 if (trans_num == 0) {
789 /* on the first packet, check the global hosts allow/ hosts
790 deny parameters before doing any parsing of the packet
791 passed to us by the client. This prevents attacks on our
792 parsing code from hosts not in the hosts allow list */
793 if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
794 /* send a negative session response "not listining on calling
796 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
797 DEBUG( 1, ( "Connection denied from %s\n",
799 send_smb(smbd_server_fd(),(char *)buf);
800 exit_server("connection denied");
804 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
805 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
808 if(sslEnabled && !sslConnected){
809 sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
810 if(sslConnected < 0){ /* an error occured */
811 exit_server("SSL negotiation failed");
812 }else if(sslConnected){
817 #endif /* WITH_SSL */
821 else if(msg_type == 0x85)
822 return; /* Keepalive packet. */
824 nread = construct_reply(inbuf,outbuf,nread,max_send);
828 if (CVAL(outbuf,0) == 0)
831 if (nread != smb_len(outbuf) + 4)
833 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
834 nread, smb_len(outbuf)));
837 send_smb(smbd_server_fd(),outbuf);
844 /****************************************************************************
845 return a string containing the function name of a SMB command
846 ****************************************************************************/
847 char *smb_fn_name(int type)
849 static char *unknown_name = "SMBunknown";
851 if (smb_messages[type].name == NULL)
852 return(unknown_name);
854 return(smb_messages[type].name);
858 /****************************************************************************
859 Helper function for contruct_reply.
860 ****************************************************************************/
862 void construct_reply_common(char *inbuf,char *outbuf)
864 memset(outbuf,'\0',smb_size);
866 set_message(outbuf,0,0,True);
867 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
869 memcpy(outbuf+4,inbuf+4,4);
870 CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
871 CVAL(outbuf,smb_reh) = 0;
872 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
874 SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
875 /* say we support long filenames */
877 SSVAL(outbuf,smb_err,SMB_SUCCESS);
878 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
879 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
880 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
881 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
884 /****************************************************************************
885 construct a chained reply and add it to the already made reply
886 **************************************************************************/
887 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
889 static char *orig_inbuf;
890 static char *orig_outbuf;
891 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
892 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
893 char *inbuf2, *outbuf2;
895 char inbuf_saved[smb_wct];
896 char outbuf_saved[smb_wct];
897 int wct = CVAL(outbuf,smb_wct);
898 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
900 /* maybe its not chained */
901 if (smb_com2 == 0xFF) {
902 CVAL(outbuf,smb_vwv0) = 0xFF;
906 if (chain_size == 0) {
907 /* this is the first part of the chain */
909 orig_outbuf = outbuf;
913 * The original Win95 redirector dies on a reply to
914 * a lockingX and read chain unless the chain reply is
915 * 4 byte aligned. JRA.
918 outsize = (outsize + 3) & ~3;
920 /* we need to tell the client where the next part of the reply will be */
921 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
922 CVAL(outbuf,smb_vwv0) = smb_com2;
924 /* remember how much the caller added to the chain, only counting stuff
925 after the parameter words */
926 chain_size += outsize - smb_wct;
928 /* work out pointers into the original packets. The
929 headers on these need to be filled in */
930 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
931 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
933 /* remember the original command type */
934 smb_com1 = CVAL(orig_inbuf,smb_com);
936 /* save the data which will be overwritten by the new headers */
937 memcpy(inbuf_saved,inbuf2,smb_wct);
938 memcpy(outbuf_saved,outbuf2,smb_wct);
940 /* give the new packet the same header as the last part of the SMB */
941 memmove(inbuf2,inbuf,smb_wct);
943 /* create the in buffer */
944 CVAL(inbuf2,smb_com) = smb_com2;
946 /* create the out buffer */
947 construct_reply_common(inbuf2, outbuf2);
949 DEBUG(3,("Chained message\n"));
952 /* process the request */
953 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
956 /* copy the new reply and request headers over the old ones, but
957 preserve the smb_com field */
958 memmove(orig_outbuf,outbuf2,smb_wct);
959 CVAL(orig_outbuf,smb_com) = smb_com1;
961 /* restore the saved data, being careful not to overwrite any
962 data from the reply header */
963 memcpy(inbuf2,inbuf_saved,smb_wct);
965 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
966 if (ofs < 0) ofs = 0;
967 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
973 /****************************************************************************
974 Setup the needed select timeout.
975 ****************************************************************************/
977 static int setup_select_timeout(void)
983 * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
984 * have removed any blocking locks. JRA.
987 select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
988 SMBD_SELECT_TIMEOUT*1000;
990 t = change_notify_timeout();
991 if (t != -1) select_timeout = MIN(select_timeout, t*1000);
993 return select_timeout;
996 /****************************************************************************
997 Check if services need reloading.
998 ****************************************************************************/
1000 void check_reload(int t)
1002 static time_t last_smb_conf_reload_time = 0;
1004 if(last_smb_conf_reload_time == 0)
1005 last_smb_conf_reload_time = t;
1007 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
1009 reload_services(True);
1010 reload_after_sighup = False;
1011 last_smb_conf_reload_time = t;
1015 /****************************************************************************
1016 Process any timeout housekeeping. Return False if the caller should exit.
1017 ****************************************************************************/
1019 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1021 static time_t last_keepalive_sent_time = 0;
1022 static time_t last_idle_closed_check = 0;
1024 BOOL allidle = True;
1025 extern int keepalive;
1027 if (smb_read_error == READ_EOF)
1029 DEBUG(3,("end of file from client\n"));
1033 if (smb_read_error == READ_ERROR)
1035 DEBUG(3,("receive_smb error (%s) exiting\n",
1040 *last_timeout_processing_time = t = time(NULL);
1042 if(last_keepalive_sent_time == 0)
1043 last_keepalive_sent_time = t;
1045 if(last_idle_closed_check == 0)
1046 last_idle_closed_check = t;
1048 /* become root again if waiting */
1051 /* check if we need to reload services */
1054 /* automatic timeout if all connections are closed */
1055 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT)
1057 DEBUG( 2, ( "Closing idle connection\n" ) );
1061 last_idle_closed_check = t;
1063 if (keepalive && (t - last_keepalive_sent_time)>keepalive)
1065 struct cli_state *cli = server_client();
1066 if (!send_keepalive(smbd_server_fd())) {
1067 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1070 /* also send a keepalive to the password server if its still
1072 if (cli && cli->initialised)
1073 send_keepalive(cli->fd);
1074 last_keepalive_sent_time = t;
1077 /* check for connection timeouts */
1078 allidle = conn_idle_all(t, deadtime);
1080 if (allidle && conn_num_open()>0) {
1081 DEBUG(2,("Closing idle connection 2.\n"));
1085 if(global_machine_password_needs_changing)
1087 unsigned char trust_passwd_hash[16];
1089 pstring remote_machine_list;
1092 * We're in domain level security, and the code that
1093 * read the machine password flagged that the machine
1094 * password needs changing.
1098 * First, open the machine password file with an exclusive lock.
1101 if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
1102 DEBUG(0,("process: unable to read the machine account password for \
1103 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1108 * Make sure someone else hasn't already done this.
1111 if(t < lct + lp_machine_password_timeout()) {
1112 global_machine_password_needs_changing = False;
1116 pstrcpy(remote_machine_list, lp_passwordserver());
1118 change_trust_account_password( global_myworkgroup, remote_machine_list);
1119 global_machine_password_needs_changing = False;
1123 * Check to see if we have any blocking locks
1124 * outstanding on the queue.
1126 process_blocking_lock_queue(t);
1129 * Check to see if we have any change notifies
1130 * outstanding on the queue.
1132 process_pending_change_notify_queue(t);
1135 * Now we are root, check if the log files need pruning.
1137 if(need_to_check_log_size())
1141 * Modify the select timeout depending upon
1142 * what we have remaining in our queues.
1145 *select_timeout = setup_select_timeout();
1150 /****************************************************************************
1151 process commands from the client
1152 ****************************************************************************/
1154 void smbd_process(void)
1156 extern int smb_echo_count;
1157 time_t last_timeout_processing_time = time(NULL);
1158 unsigned int num_smbs = 0;
1160 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1161 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1162 if ((InBuffer == NULL) || (OutBuffer == NULL))
1165 InBuffer += SMB_ALIGNMENT;
1166 OutBuffer += SMB_ALIGNMENT;
1168 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1170 /* re-initialise the timezone */
1174 int deadtime = lp_deadtime()*60;
1175 int select_timeout = setup_select_timeout();
1179 deadtime = DEFAULT_SMBD_TIMEOUT;
1183 /* free up temporary memory */
1185 parse_talloc_free();
1187 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) {
1188 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1190 num_smbs = 0; /* Reset smb counter. */
1194 * Ensure we do timeout processing if the SMB we just got was
1195 * only an echo request. This allows us to set the select
1196 * timeout in 'receive_message_or_smb()' to any value we like
1197 * without worrying that the client will send echo requests
1198 * faster than the select timeout, thus starving out the
1199 * essential processing (change notify, blocking locks) that
1200 * the timeout code does. JRA.
1202 num_echos = smb_echo_count;
1204 process_smb(InBuffer, OutBuffer);
1206 if (smb_echo_count != num_echos) {
1207 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1209 num_smbs = 0; /* Reset smb counter. */
1215 * If we are getting smb requests in a constant stream
1216 * with no echos, make sure we attempt timeout processing
1217 * every select_timeout milliseconds - but only check for this
1218 * every 200 smb requests.
1221 if ((num_smbs % 200) == 0) {
1222 time_t new_check_time = time(NULL);
1223 if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1224 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1226 num_smbs = 0; /* Reset smb counter. */
1227 last_timeout_processing_time = new_check_time; /* Reset time. */