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