root/source3/smbd/process.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. srv_send_smb
  2. srv_set_message
  3. valid_smb_header
  4. valid_packet_size
  5. read_packet_remainder
  6. receive_smb_raw_talloc_partial_read
  7. receive_smb_raw_talloc
  8. receive_smb_talloc
  9. init_smb_request
  10. smbd_deferred_open_timer
  11. push_queued_message
  12. remove_deferred_open_smb_message
  13. schedule_deferred_open_smb_message
  14. open_was_deferred
  15. get_open_deferred_message
  16. push_deferred_smb_message
  17. smbd_idle_event_handler
  18. event_add_idle
  19. smbd_sig_term_handler
  20. smbd_setup_sig_term_handler
  21. smbd_sig_hup_handler
  22. smbd_setup_sig_hup_handler
  23. smbd_server_connection_loop_once
  24. allow_new_trans
  25. create_outbuf
  26. reply_outbuf
  27. smb_dump
  28. switch_message
  29. construct_reply
  30. process_smb
  31. smb_fn_name
  32. add_to_common_flags2
  33. remove_from_common_flags2
  34. construct_reply_common
  35. construct_reply_common_req
  36. req_wct_ofs
  37. fixup_chain_error_packet
  38. chain_reply
  39. check_reload
  40. smbd_server_connection_write_handler
  41. smbd_server_connection_read_handler
  42. smbd_server_connection_handler
  43. release_ip
  44. msg_release_ip
  45. client_get_tcp_info
  46. keepalive_fn
  47. deadtime_fn
  48. housekeeping_fn
  49. smbd_process
  50. req_is_in_chain

   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-2007
   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 3 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, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "smbd/globals.h"
  23 
  24 extern bool global_machine_password_needs_changing;
  25 
  26 static void construct_reply_common(struct smb_request *req, const char *inbuf,
  27                                    char *outbuf);
  28 
  29 /* Accessor function for smb_read_error for smbd functions. */
  30 
  31 /****************************************************************************
  32  Send an smb to a fd.
  33 ****************************************************************************/
  34 
  35 bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
     /* [<][>][^][v][top][bottom][index][help] */
  36                   struct smb_perfcount_data *pcd)
  37 {
  38         size_t len = 0;
  39         size_t nwritten=0;
  40         ssize_t ret;
  41         char *buf_out = buffer;
  42 
  43         /* Sign the outgoing packet if required. */
  44         srv_calculate_sign_mac(buf_out);
  45 
  46         if (do_encrypt) {
  47                 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
  48                 if (!NT_STATUS_IS_OK(status)) {
  49                         DEBUG(0, ("send_smb: SMB encryption failed "
  50                                 "on outgoing packet! Error %s\n",
  51                                 nt_errstr(status) ));
  52                         goto out;
  53                 }
  54         }
  55 
  56         len = smb_len(buf_out) + 4;
  57 
  58         while (nwritten < len) {
  59                 ret = write_data(fd,buf_out+nwritten,len - nwritten);
  60                 if (ret <= 0) {
  61                         DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
  62                                 (int)len,(int)ret, strerror(errno) ));
  63                         srv_free_enc_buffer(buf_out);
  64                         goto out;
  65                 }
  66                 nwritten += ret;
  67         }
  68 
  69         SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
  70         srv_free_enc_buffer(buf_out);
  71 out:
  72         SMB_PERFCOUNT_END(pcd);
  73         return true;
  74 }
  75 
  76 /*******************************************************************
  77  Setup the word count and byte count for a smb message.
  78 ********************************************************************/
  79 
  80 int srv_set_message(char *buf,
     /* [<][>][^][v][top][bottom][index][help] */
  81                         int num_words,
  82                         int num_bytes,
  83                         bool zero)
  84 {
  85         if (zero && (num_words || num_bytes)) {
  86                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
  87         }
  88         SCVAL(buf,smb_wct,num_words);
  89         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
  90         smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
  91         return (smb_size + num_words*2 + num_bytes);
  92 }
  93 
  94 static bool valid_smb_header(const uint8_t *inbuf)
     /* [<][>][^][v][top][bottom][index][help] */
  95 {
  96         if (is_encrypted_packet(inbuf)) {
  97                 return true;
  98         }
  99         /*
 100          * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
 101          * but it just looks weird to call strncmp for this one.
 102          */
 103         return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
 104 }
 105 
 106 /* Socket functions for smbd packet processing. */
 107 
 108 static bool valid_packet_size(size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
 109 {
 110         /*
 111          * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
 112          * of header. Don't print the error if this fits.... JRA.
 113          */
 114 
 115         if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
 116                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
 117                                         (unsigned long)len));
 118                 return false;
 119         }
 120         return true;
 121 }
 122 
 123 static NTSTATUS read_packet_remainder(int fd, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 124                                       unsigned int timeout, ssize_t len)
 125 {
 126         if (len <= 0) {
 127                 return NT_STATUS_OK;
 128         }
 129 
 130         return read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
 131 }
 132 
 133 /****************************************************************************
 134  Attempt a zerocopy writeX read. We know here that len > smb_size-4
 135 ****************************************************************************/
 136 
 137 /*
 138  * Unfortunately, earlier versions of smbclient/libsmbclient
 139  * don't send this "standard" writeX header. I've fixed this
 140  * for 3.2 but we'll use the old method with earlier versions.
 141  * Windows and CIFSFS at least use this standard size. Not
 142  * sure about MacOSX.
 143  */
 144 
 145 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
 146                                 (2*14) + /* word count (including bcc) */ \
 147                                 1 /* pad byte */)
 148 
 149 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 150                                                     const char lenbuf[4],
 151                                                     int fd, char **buffer,
 152                                                     unsigned int timeout,
 153                                                     size_t *p_unread,
 154                                                     size_t *len_ret)
 155 {
 156         /* Size of a WRITEX call (+4 byte len). */
 157         char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
 158         ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
 159         ssize_t toread;
 160         NTSTATUS status;
 161 
 162         memcpy(writeX_header, lenbuf, 4);
 163 
 164         status = read_fd_with_timeout(
 165                 fd, writeX_header + 4,
 166                 STANDARD_WRITE_AND_X_HEADER_SIZE,
 167                 STANDARD_WRITE_AND_X_HEADER_SIZE,
 168                 timeout, NULL);
 169 
 170         if (!NT_STATUS_IS_OK(status)) {
 171                 return status;
 172         }
 173 
 174         /*
 175          * Ok - now try and see if this is a possible
 176          * valid writeX call.
 177          */
 178 
 179         if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
 180                 /*
 181                  * If the data offset is beyond what
 182                  * we've read, drain the extra bytes.
 183                  */
 184                 uint16_t doff = SVAL(writeX_header,smb_vwv11);
 185                 ssize_t newlen;
 186 
 187                 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
 188                         size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
 189                         if (drain_socket(smbd_server_fd(), drain) != drain) {
 190                                 smb_panic("receive_smb_raw_talloc_partial_read:"
 191                                         " failed to drain pending bytes");
 192                         }
 193                 } else {
 194                         doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
 195                 }
 196 
 197                 /* Spoof down the length and null out the bcc. */
 198                 set_message_bcc(writeX_header, 0);
 199                 newlen = smb_len(writeX_header);
 200 
 201                 /* Copy the header we've written. */
 202 
 203                 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
 204                                 writeX_header,
 205                                 sizeof(writeX_header));
 206 
 207                 if (*buffer == NULL) {
 208                         DEBUG(0, ("Could not allocate inbuf of length %d\n",
 209                                   (int)sizeof(writeX_header)));
 210                         return NT_STATUS_NO_MEMORY;
 211                 }
 212 
 213                 /* Work out the remaining bytes. */
 214                 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
 215                 *len_ret = newlen + 4;
 216                 return NT_STATUS_OK;
 217         }
 218 
 219         if (!valid_packet_size(len)) {
 220                 return NT_STATUS_INVALID_PARAMETER;
 221         }
 222 
 223         /*
 224          * Not a valid writeX call. Just do the standard
 225          * talloc and return.
 226          */
 227 
 228         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
 229 
 230         if (*buffer == NULL) {
 231                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
 232                           (int)len+4));
 233                 return NT_STATUS_NO_MEMORY;
 234         }
 235 
 236         /* Copy in what we already read. */
 237         memcpy(*buffer,
 238                 writeX_header,
 239                 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
 240         toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
 241 
 242         if(toread > 0) {
 243                 status = read_packet_remainder(
 244                         fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
 245                         timeout, toread);
 246 
 247                 if (!NT_STATUS_IS_OK(status)) {
 248                         DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
 249                                    nt_errstr(status)));
 250                         return status;
 251                 }
 252         }
 253 
 254         *len_ret = len + 4;
 255         return NT_STATUS_OK;
 256 }
 257 
 258 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
     /* [<][>][^][v][top][bottom][index][help] */
 259                                        char **buffer, unsigned int timeout,
 260                                        size_t *p_unread, size_t *plen)
 261 {
 262         char lenbuf[4];
 263         size_t len;
 264         int min_recv_size = lp_min_receive_file_size();
 265         NTSTATUS status;
 266 
 267         *p_unread = 0;
 268 
 269         status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
 270         if (!NT_STATUS_IS_OK(status)) {
 271                 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
 272                 return status;
 273         }
 274 
 275         if (CVAL(lenbuf,0) == 0 && min_recv_size &&
 276             (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
 277                 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
 278             !srv_is_signing_active()) {
 279 
 280                 return receive_smb_raw_talloc_partial_read(
 281                         mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
 282         }
 283 
 284         if (!valid_packet_size(len)) {
 285                 return NT_STATUS_INVALID_PARAMETER;
 286         }
 287 
 288         /*
 289          * The +4 here can't wrap, we've checked the length above already.
 290          */
 291 
 292         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
 293 
 294         if (*buffer == NULL) {
 295                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
 296                           (int)len+4));
 297                 return NT_STATUS_NO_MEMORY;
 298         }
 299 
 300         memcpy(*buffer, lenbuf, sizeof(lenbuf));
 301 
 302         status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
 303         if (!NT_STATUS_IS_OK(status)) {
 304                 return status;
 305         }
 306 
 307         *plen = len + 4;
 308         return NT_STATUS_OK;
 309 }
 310 
 311 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
     /* [<][>][^][v][top][bottom][index][help] */
 312                                    char **buffer, unsigned int timeout,
 313                                    size_t *p_unread, bool *p_encrypted,
 314                                    size_t *p_len)
 315 {
 316         size_t len = 0;
 317         NTSTATUS status;
 318 
 319         *p_encrypted = false;
 320 
 321         status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
 322                                         p_unread, &len);
 323         if (!NT_STATUS_IS_OK(status)) {
 324                 return status;
 325         }
 326 
 327         if (is_encrypted_packet((uint8_t *)*buffer)) {
 328                 status = srv_decrypt_buffer(*buffer);
 329                 if (!NT_STATUS_IS_OK(status)) {
 330                         DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
 331                                 "incoming packet! Error %s\n",
 332                                 nt_errstr(status) ));
 333                         return status;
 334                 }
 335                 *p_encrypted = true;
 336         }
 337 
 338         /* Check the incoming SMB signature. */
 339         if (!srv_check_sign_mac(*buffer, true)) {
 340                 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
 341                           "incoming packet!\n"));
 342                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
 343         }
 344 
 345         *p_len = len;
 346         return NT_STATUS_OK;
 347 }
 348 
 349 /*
 350  * Initialize a struct smb_request from an inbuf
 351  */
 352 
 353 void init_smb_request(struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
 354                         const uint8 *inbuf,
 355                         size_t unread_bytes,
 356                         bool encrypted)
 357 {
 358         size_t req_size = smb_len(inbuf) + 4;
 359         /* Ensure we have at least smb_size bytes. */
 360         if (req_size < smb_size) {
 361                 DEBUG(0,("init_smb_request: invalid request size %u\n",
 362                         (unsigned int)req_size ));
 363                 exit_server_cleanly("Invalid SMB request");
 364         }
 365         req->cmd    = CVAL(inbuf, smb_com);
 366         req->flags2 = SVAL(inbuf, smb_flg2);
 367         req->smbpid = SVAL(inbuf, smb_pid);
 368         req->mid    = SVAL(inbuf, smb_mid);
 369         req->vuid   = SVAL(inbuf, smb_uid);
 370         req->tid    = SVAL(inbuf, smb_tid);
 371         req->wct    = CVAL(inbuf, smb_wct);
 372         req->vwv    = (uint16_t *)(inbuf+smb_vwv);
 373         req->buflen = smb_buflen(inbuf);
 374         req->buf    = (const uint8_t *)smb_buf(inbuf);
 375         req->unread_bytes = unread_bytes;
 376         req->encrypted = encrypted;
 377         req->conn = conn_find(req->tid);
 378         req->chain_fsp = NULL;
 379         req->chain_outbuf = NULL;
 380         req->done = false;
 381         smb_init_perfcount_data(&req->pcd);
 382 
 383         /* Ensure we have at least wct words and 2 bytes of bcc. */
 384         if (smb_size + req->wct*2 > req_size) {
 385                 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
 386                         (unsigned int)req->wct,
 387                         (unsigned int)req_size));
 388                 exit_server_cleanly("Invalid SMB request");
 389         }
 390         /* Ensure bcc is correct. */
 391         if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
 392                 DEBUG(0,("init_smb_request: invalid bcc number %u "
 393                         "(wct = %u, size %u)\n",
 394                         (unsigned int)req->buflen,
 395                         (unsigned int)req->wct,
 396                         (unsigned int)req_size));
 397                 exit_server_cleanly("Invalid SMB request");
 398         }
 399 
 400         req->outbuf = NULL;
 401 }
 402 
 403 static void process_smb(struct smbd_server_connection *conn,
 404                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
 405                         bool encrypted, struct smb_perfcount_data *deferred_pcd);
 406 
 407 static void smbd_deferred_open_timer(struct event_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 408                                      struct timed_event *te,
 409                                      struct timeval _tval,
 410                                      void *private_data)
 411 {
 412         struct pending_message_list *msg = talloc_get_type(private_data,
 413                                            struct pending_message_list);
 414         TALLOC_CTX *mem_ctx = talloc_tos();
 415         uint16_t mid = SVAL(msg->buf.data,smb_mid);
 416         uint8_t *inbuf;
 417 
 418         inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
 419                                          msg->buf.length);
 420         if (inbuf == NULL) {
 421                 exit_server("smbd_deferred_open_timer: talloc failed\n");
 422                 return;
 423         }
 424 
 425         /* We leave this message on the queue so the open code can
 426            know this is a retry. */
 427         DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
 428                 (unsigned int)mid));
 429 
 430         /* Mark the message as processed so this is not
 431          * re-processed in error. */
 432         msg->processed = true;
 433 
 434         process_smb(smbd_server_conn, inbuf,
 435                     msg->buf.length, 0,
 436                     msg->encrypted, &msg->pcd);
 437 
 438         /* If it's still there and was processed, remove it. */
 439         msg = get_open_deferred_message(mid);
 440         if (msg && msg->processed) {
 441                 remove_deferred_open_smb_message(mid);
 442         }
 443 }
 444 
 445 /****************************************************************************
 446  Function to push a message onto the tail of a linked list of smb messages ready
 447  for processing.
 448 ****************************************************************************/
 449 
 450 static bool push_queued_message(struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
 451                                 struct timeval request_time,
 452                                 struct timeval end_time,
 453                                 char *private_data, size_t private_len)
 454 {
 455         int msg_len = smb_len(req->inbuf) + 4;
 456         struct pending_message_list *msg;
 457 
 458         msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
 459 
 460         if(msg == NULL) {
 461                 DEBUG(0,("push_message: malloc fail (1)\n"));
 462                 return False;
 463         }
 464 
 465         msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
 466         if(msg->buf.data == NULL) {
 467                 DEBUG(0,("push_message: malloc fail (2)\n"));
 468                 TALLOC_FREE(msg);
 469                 return False;
 470         }
 471 
 472         msg->request_time = request_time;
 473         msg->encrypted = req->encrypted;
 474         msg->processed = false;
 475         SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
 476 
 477         if (private_data) {
 478                 msg->private_data = data_blob_talloc(msg, private_data,
 479                                                      private_len);
 480                 if (msg->private_data.data == NULL) {
 481                         DEBUG(0,("push_message: malloc fail (3)\n"));
 482                         TALLOC_FREE(msg);
 483                         return False;
 484                 }
 485         }
 486 
 487         msg->te = event_add_timed(smbd_event_context(),
 488                                   msg,
 489                                   end_time,
 490                                   smbd_deferred_open_timer,
 491                                   msg);
 492         if (!msg->te) {
 493                 DEBUG(0,("push_message: event_add_timed failed\n"));
 494                 TALLOC_FREE(msg);
 495                 return false;
 496         }
 497 
 498         DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
 499 
 500         DEBUG(10,("push_message: pushed message length %u on "
 501                   "deferred_open_queue\n", (unsigned int)msg_len));
 502 
 503         return True;
 504 }
 505 
 506 /****************************************************************************
 507  Function to delete a sharing violation open message by mid.
 508 ****************************************************************************/
 509 
 510 void remove_deferred_open_smb_message(uint16 mid)
     /* [<][>][^][v][top][bottom][index][help] */
 511 {
 512         struct pending_message_list *pml;
 513 
 514         for (pml = deferred_open_queue; pml; pml = pml->next) {
 515                 if (mid == SVAL(pml->buf.data,smb_mid)) {
 516                         DEBUG(10,("remove_deferred_open_smb_message: "
 517                                   "deleting mid %u len %u\n",
 518                                   (unsigned int)mid,
 519                                   (unsigned int)pml->buf.length ));
 520                         DLIST_REMOVE(deferred_open_queue, pml);
 521                         TALLOC_FREE(pml);
 522                         return;
 523                 }
 524         }
 525 }
 526 
 527 /****************************************************************************
 528  Move a sharing violation open retry message to the front of the list and
 529  schedule it for immediate processing.
 530 ****************************************************************************/
 531 
 532 void schedule_deferred_open_smb_message(uint16 mid)
     /* [<][>][^][v][top][bottom][index][help] */
 533 {
 534         struct pending_message_list *pml;
 535         int i = 0;
 536 
 537         for (pml = deferred_open_queue; pml; pml = pml->next) {
 538                 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
 539 
 540                 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
 541                         (unsigned int)msg_mid ));
 542 
 543                 if (mid == msg_mid) {
 544                         struct timed_event *te;
 545 
 546                         if (pml->processed) {
 547                                 /* A processed message should not be
 548                                  * rescheduled. */
 549                                 DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
 550                                         "message mid %u was already processed\n",
 551                                         msg_mid ));
 552                                 continue;
 553                         }
 554 
 555                         DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
 556                                 mid ));
 557 
 558                         te = event_add_timed(smbd_event_context(),
 559                                              pml,
 560                                              timeval_zero(),
 561                                              smbd_deferred_open_timer,
 562                                              pml);
 563                         if (!te) {
 564                                 DEBUG(10,("schedule_deferred_open_smb_message: "
 565                                           "event_add_timed() failed, skipping mid %u\n",
 566                                           mid ));
 567                         }
 568 
 569                         TALLOC_FREE(pml->te);
 570                         pml->te = te;
 571                         DLIST_PROMOTE(deferred_open_queue, pml);
 572                         return;
 573                 }
 574         }
 575 
 576         DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
 577                 mid ));
 578 }
 579 
 580 /****************************************************************************
 581  Return true if this mid is on the deferred queue and was not yet processed.
 582 ****************************************************************************/
 583 
 584 bool open_was_deferred(uint16 mid)
     /* [<][>][^][v][top][bottom][index][help] */
 585 {
 586         struct pending_message_list *pml;
 587 
 588         for (pml = deferred_open_queue; pml; pml = pml->next) {
 589                 if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) {
 590                         return True;
 591                 }
 592         }
 593         return False;
 594 }
 595 
 596 /****************************************************************************
 597  Return the message queued by this mid.
 598 ****************************************************************************/
 599 
 600 struct pending_message_list *get_open_deferred_message(uint16 mid)
     /* [<][>][^][v][top][bottom][index][help] */
 601 {
 602         struct pending_message_list *pml;
 603 
 604         for (pml = deferred_open_queue; pml; pml = pml->next) {
 605                 if (SVAL(pml->buf.data,smb_mid) == mid) {
 606                         return pml;
 607                 }
 608         }
 609         return NULL;
 610 }
 611 
 612 /****************************************************************************
 613  Function to push a deferred open smb message onto a linked list of local smb
 614  messages ready for processing.
 615 ****************************************************************************/
 616 
 617 bool push_deferred_smb_message(struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
 618                                struct timeval request_time,
 619                                struct timeval timeout,
 620                                char *private_data, size_t priv_len)
 621 {
 622         struct timeval end_time;
 623 
 624         if (req->unread_bytes) {
 625                 DEBUG(0,("push_deferred_smb_message: logic error ! "
 626                         "unread_bytes = %u\n",
 627                         (unsigned int)req->unread_bytes ));
 628                 smb_panic("push_deferred_smb_message: "
 629                         "logic error unread_bytes != 0" );
 630         }
 631 
 632         end_time = timeval_sum(&request_time, &timeout);
 633 
 634         DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
 635                   "timeout time [%u.%06u]\n",
 636                   (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
 637                   (unsigned int)end_time.tv_sec,
 638                   (unsigned int)end_time.tv_usec));
 639 
 640         return push_queued_message(req, request_time, end_time,
 641                                    private_data, priv_len);
 642 }
 643 
 644 struct idle_event {
 645         struct timed_event *te;
 646         struct timeval interval;
 647         char *name;
 648         bool (*handler)(const struct timeval *now, void *private_data);
 649         void *private_data;
 650 };
 651 
 652 static void smbd_idle_event_handler(struct event_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 653                                     struct timed_event *te,
 654                                     struct timeval now,
 655                                     void *private_data)
 656 {
 657         struct idle_event *event =
 658                 talloc_get_type_abort(private_data, struct idle_event);
 659 
 660         TALLOC_FREE(event->te);
 661 
 662         DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
 663                   event->name, event->te));
 664 
 665         if (!event->handler(&now, event->private_data)) {
 666                 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
 667                           event->name, event->te));
 668                 /* Don't repeat, delete ourselves */
 669                 TALLOC_FREE(event);
 670                 return;
 671         }
 672 
 673         DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
 674                   event->name, event->te));
 675 
 676         event->te = event_add_timed(ctx, event,
 677                                     timeval_sum(&now, &event->interval),
 678                                     smbd_idle_event_handler, event);
 679 
 680         /* We can't do much but fail here. */
 681         SMB_ASSERT(event->te != NULL);
 682 }
 683 
 684 struct idle_event *event_add_idle(struct event_context *event_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 685                                   TALLOC_CTX *mem_ctx,
 686                                   struct timeval interval,
 687                                   const char *name,
 688                                   bool (*handler)(const struct timeval *now,
 689                                                   void *private_data),
 690                                   void *private_data)
 691 {
 692         struct idle_event *result;
 693         struct timeval now = timeval_current();
 694 
 695         result = TALLOC_P(mem_ctx, struct idle_event);
 696         if (result == NULL) {
 697                 DEBUG(0, ("talloc failed\n"));
 698                 return NULL;
 699         }
 700 
 701         result->interval = interval;
 702         result->handler = handler;
 703         result->private_data = private_data;
 704 
 705         if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
 706                 DEBUG(0, ("talloc failed\n"));
 707                 TALLOC_FREE(result);
 708                 return NULL;
 709         }
 710 
 711         result->te = event_add_timed(event_ctx, result,
 712                                      timeval_sum(&now, &interval),
 713                                      smbd_idle_event_handler, result);
 714         if (result->te == NULL) {
 715                 DEBUG(0, ("event_add_timed failed\n"));
 716                 TALLOC_FREE(result);
 717                 return NULL;
 718         }
 719 
 720         DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
 721         return result;
 722 }
 723 
 724 static void smbd_sig_term_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 725                                   struct tevent_signal *se,
 726                                   int signum,
 727                                   int count,
 728                                   void *siginfo,
 729                                   void *private_data)
 730 {
 731         exit_server_cleanly("termination signal");
 732 }
 733 
 734 void smbd_setup_sig_term_handler(void)
     /* [<][>][^][v][top][bottom][index][help] */
 735 {
 736         struct tevent_signal *se;
 737 
 738         se = tevent_add_signal(smbd_event_context(),
 739                                smbd_event_context(),
 740                                SIGTERM, 0,
 741                                smbd_sig_term_handler,
 742                                NULL);
 743         if (!se) {
 744                 exit_server("failed to setup SIGTERM handler");
 745         }
 746 }
 747 
 748 static void smbd_sig_hup_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 749                                   struct tevent_signal *se,
 750                                   int signum,
 751                                   int count,
 752                                   void *siginfo,
 753                                   void *private_data)
 754 {
 755         change_to_root_user();
 756         DEBUG(1,("Reloading services after SIGHUP\n"));
 757         reload_services(False);
 758 }
 759 
 760 void smbd_setup_sig_hup_handler(void)
     /* [<][>][^][v][top][bottom][index][help] */
 761 {
 762         struct tevent_signal *se;
 763 
 764         se = tevent_add_signal(smbd_event_context(),
 765                                smbd_event_context(),
 766                                SIGHUP, 0,
 767                                smbd_sig_hup_handler,
 768                                NULL);
 769         if (!se) {
 770                 exit_server("failed to setup SIGHUP handler");
 771         }
 772 }
 773 
 774 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
     /* [<][>][^][v][top][bottom][index][help] */
 775 {
 776         fd_set r_fds, w_fds;
 777         int selrtn;
 778         struct timeval to;
 779         int maxfd = 0;
 780 
 781         to.tv_sec = SMBD_SELECT_TIMEOUT;
 782         to.tv_usec = 0;
 783 
 784         /*
 785          * Setup the select fd sets.
 786          */
 787 
 788         FD_ZERO(&r_fds);
 789         FD_ZERO(&w_fds);
 790 
 791         /*
 792          * Are there any timed events waiting ? If so, ensure we don't
 793          * select for longer than it would take to wait for them.
 794          */
 795 
 796         {
 797                 struct timeval now;
 798                 GetTimeOfDay(&now);
 799 
 800                 event_add_to_select_args(smbd_event_context(), &now,
 801                                          &r_fds, &w_fds, &to, &maxfd);
 802         }
 803 
 804         /* Process a signal and timed events now... */
 805         if (run_events(smbd_event_context(), 0, NULL, NULL)) {
 806                 return NT_STATUS_RETRY;
 807         }
 808 
 809         {
 810                 int sav;
 811                 START_PROFILE(smbd_idle);
 812 
 813                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
 814                 sav = errno;
 815 
 816                 END_PROFILE(smbd_idle);
 817                 errno = sav;
 818         }
 819 
 820         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
 821                 return NT_STATUS_RETRY;
 822         }
 823 
 824         /* Check if error */
 825         if (selrtn == -1) {
 826                 /* something is wrong. Maybe the socket is dead? */
 827                 return map_nt_error_from_unix(errno);
 828         }
 829 
 830         /* Did we timeout ? */
 831         if (selrtn == 0) {
 832                 return NT_STATUS_RETRY;
 833         }
 834 
 835         /* should not be reached */
 836         return NT_STATUS_INTERNAL_ERROR;
 837 }
 838 
 839 /*
 840  * Only allow 5 outstanding trans requests. We're allocating memory, so
 841  * prevent a DoS.
 842  */
 843 
 844 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
     /* [<][>][^][v][top][bottom][index][help] */
 845 {
 846         int count = 0;
 847         for (; list != NULL; list = list->next) {
 848 
 849                 if (list->mid == mid) {
 850                         return NT_STATUS_INVALID_PARAMETER;
 851                 }
 852 
 853                 count += 1;
 854         }
 855         if (count > 5) {
 856                 return NT_STATUS_INSUFFICIENT_RESOURCES;
 857         }
 858 
 859         return NT_STATUS_OK;
 860 }
 861 
 862 /*
 863 These flags determine some of the permissions required to do an operation 
 864 
 865 Note that I don't set NEED_WRITE on some write operations because they
 866 are used by some brain-dead clients when printing, and I don't want to
 867 force write permissions on print services.
 868 */
 869 #define AS_USER (1<<0)
 870 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
 871 #define TIME_INIT (1<<2)
 872 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
 873 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
 874 #define DO_CHDIR (1<<6)
 875 
 876 /* 
 877    define a list of possible SMB messages and their corresponding
 878    functions. Any message that has a NULL function is unimplemented -
 879    please feel free to contribute implementations!
 880 */
 881 static const struct smb_message_struct {
 882         const char *name;
 883         void (*fn)(struct smb_request *req);
 884         int flags;
 885 } smb_messages[256] = {
 886 
 887 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
 888 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
 889 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
 890 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
 891 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
 892 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
 893 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
 894 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
 895 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
 896 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
 897 /* 0x0a */ { "SMBread",reply_read,AS_USER},
 898 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
 899 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
 900 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
 901 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
 902 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
 903 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
 904 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
 905 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
 906 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
 907 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
 908 /* 0x15 */ { NULL, NULL, 0 },
 909 /* 0x16 */ { NULL, NULL, 0 },
 910 /* 0x17 */ { NULL, NULL, 0 },
 911 /* 0x18 */ { NULL, NULL, 0 },
 912 /* 0x19 */ { NULL, NULL, 0 },
 913 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
 914 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
 915 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
 916 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
 917 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
 918 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
 919 /* 0x20 */ { "SMBwritec", NULL,0},
 920 /* 0x21 */ { NULL, NULL, 0 },
 921 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
 922 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
 923 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
 924 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
 925 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
 926 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
 927 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
 928 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
 929 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
 930 /* 0x2b */ { "SMBecho",reply_echo,0},
 931 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
 932 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
 933 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
 934 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
 935 /* 0x30 */ { NULL, NULL, 0 },
 936 /* 0x31 */ { NULL, NULL, 0 },
 937 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
 938 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
 939 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
 940 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
 941 /* 0x36 */ { NULL, NULL, 0 },
 942 /* 0x37 */ { NULL, NULL, 0 },
 943 /* 0x38 */ { NULL, NULL, 0 },
 944 /* 0x39 */ { NULL, NULL, 0 },
 945 /* 0x3a */ { NULL, NULL, 0 },
 946 /* 0x3b */ { NULL, NULL, 0 },
 947 /* 0x3c */ { NULL, NULL, 0 },
 948 /* 0x3d */ { NULL, NULL, 0 },
 949 /* 0x3e */ { NULL, NULL, 0 },
 950 /* 0x3f */ { NULL, NULL, 0 },
 951 /* 0x40 */ { NULL, NULL, 0 },
 952 /* 0x41 */ { NULL, NULL, 0 },
 953 /* 0x42 */ { NULL, NULL, 0 },
 954 /* 0x43 */ { NULL, NULL, 0 },
 955 /* 0x44 */ { NULL, NULL, 0 },
 956 /* 0x45 */ { NULL, NULL, 0 },
 957 /* 0x46 */ { NULL, NULL, 0 },
 958 /* 0x47 */ { NULL, NULL, 0 },
 959 /* 0x48 */ { NULL, NULL, 0 },
 960 /* 0x49 */ { NULL, NULL, 0 },
 961 /* 0x4a */ { NULL, NULL, 0 },
 962 /* 0x4b */ { NULL, NULL, 0 },
 963 /* 0x4c */ { NULL, NULL, 0 },
 964 /* 0x4d */ { NULL, NULL, 0 },
 965 /* 0x4e */ { NULL, NULL, 0 },
 966 /* 0x4f */ { NULL, NULL, 0 },
 967 /* 0x50 */ { NULL, NULL, 0 },
 968 /* 0x51 */ { NULL, NULL, 0 },
 969 /* 0x52 */ { NULL, NULL, 0 },
 970 /* 0x53 */ { NULL, NULL, 0 },
 971 /* 0x54 */ { NULL, NULL, 0 },
 972 /* 0x55 */ { NULL, NULL, 0 },
 973 /* 0x56 */ { NULL, NULL, 0 },
 974 /* 0x57 */ { NULL, NULL, 0 },
 975 /* 0x58 */ { NULL, NULL, 0 },
 976 /* 0x59 */ { NULL, NULL, 0 },
 977 /* 0x5a */ { NULL, NULL, 0 },
 978 /* 0x5b */ { NULL, NULL, 0 },
 979 /* 0x5c */ { NULL, NULL, 0 },
 980 /* 0x5d */ { NULL, NULL, 0 },
 981 /* 0x5e */ { NULL, NULL, 0 },
 982 /* 0x5f */ { NULL, NULL, 0 },
 983 /* 0x60 */ { NULL, NULL, 0 },
 984 /* 0x61 */ { NULL, NULL, 0 },
 985 /* 0x62 */ { NULL, NULL, 0 },
 986 /* 0x63 */ { NULL, NULL, 0 },
 987 /* 0x64 */ { NULL, NULL, 0 },
 988 /* 0x65 */ { NULL, NULL, 0 },
 989 /* 0x66 */ { NULL, NULL, 0 },
 990 /* 0x67 */ { NULL, NULL, 0 },
 991 /* 0x68 */ { NULL, NULL, 0 },
 992 /* 0x69 */ { NULL, NULL, 0 },
 993 /* 0x6a */ { NULL, NULL, 0 },
 994 /* 0x6b */ { NULL, NULL, 0 },
 995 /* 0x6c */ { NULL, NULL, 0 },
 996 /* 0x6d */ { NULL, NULL, 0 },
 997 /* 0x6e */ { NULL, NULL, 0 },
 998 /* 0x6f */ { NULL, NULL, 0 },
 999 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1000 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1001 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1002 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1003 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1004 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1005 /* 0x76 */ { NULL, NULL, 0 },
1006 /* 0x77 */ { NULL, NULL, 0 },
1007 /* 0x78 */ { NULL, NULL, 0 },
1008 /* 0x79 */ { NULL, NULL, 0 },
1009 /* 0x7a */ { NULL, NULL, 0 },
1010 /* 0x7b */ { NULL, NULL, 0 },
1011 /* 0x7c */ { NULL, NULL, 0 },
1012 /* 0x7d */ { NULL, NULL, 0 },
1013 /* 0x7e */ { NULL, NULL, 0 },
1014 /* 0x7f */ { NULL, NULL, 0 },
1015 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1016 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1017 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1018 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1019 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1020 /* 0x85 */ { NULL, NULL, 0 },
1021 /* 0x86 */ { NULL, NULL, 0 },
1022 /* 0x87 */ { NULL, NULL, 0 },
1023 /* 0x88 */ { NULL, NULL, 0 },
1024 /* 0x89 */ { NULL, NULL, 0 },
1025 /* 0x8a */ { NULL, NULL, 0 },
1026 /* 0x8b */ { NULL, NULL, 0 },
1027 /* 0x8c */ { NULL, NULL, 0 },
1028 /* 0x8d */ { NULL, NULL, 0 },
1029 /* 0x8e */ { NULL, NULL, 0 },
1030 /* 0x8f */ { NULL, NULL, 0 },
1031 /* 0x90 */ { NULL, NULL, 0 },
1032 /* 0x91 */ { NULL, NULL, 0 },
1033 /* 0x92 */ { NULL, NULL, 0 },
1034 /* 0x93 */ { NULL, NULL, 0 },
1035 /* 0x94 */ { NULL, NULL, 0 },
1036 /* 0x95 */ { NULL, NULL, 0 },
1037 /* 0x96 */ { NULL, NULL, 0 },
1038 /* 0x97 */ { NULL, NULL, 0 },
1039 /* 0x98 */ { NULL, NULL, 0 },
1040 /* 0x99 */ { NULL, NULL, 0 },
1041 /* 0x9a */ { NULL, NULL, 0 },
1042 /* 0x9b */ { NULL, NULL, 0 },
1043 /* 0x9c */ { NULL, NULL, 0 },
1044 /* 0x9d */ { NULL, NULL, 0 },
1045 /* 0x9e */ { NULL, NULL, 0 },
1046 /* 0x9f */ { NULL, NULL, 0 },
1047 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1048 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1049 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1050 /* 0xa3 */ { NULL, NULL, 0 },
1051 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1052 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1053 /* 0xa6 */ { NULL, NULL, 0 },
1054 /* 0xa7 */ { NULL, NULL, 0 },
1055 /* 0xa8 */ { NULL, NULL, 0 },
1056 /* 0xa9 */ { NULL, NULL, 0 },
1057 /* 0xaa */ { NULL, NULL, 0 },
1058 /* 0xab */ { NULL, NULL, 0 },
1059 /* 0xac */ { NULL, NULL, 0 },
1060 /* 0xad */ { NULL, NULL, 0 },
1061 /* 0xae */ { NULL, NULL, 0 },
1062 /* 0xaf */ { NULL, NULL, 0 },
1063 /* 0xb0 */ { NULL, NULL, 0 },
1064 /* 0xb1 */ { NULL, NULL, 0 },
1065 /* 0xb2 */ { NULL, NULL, 0 },
1066 /* 0xb3 */ { NULL, NULL, 0 },
1067 /* 0xb4 */ { NULL, NULL, 0 },
1068 /* 0xb5 */ { NULL, NULL, 0 },
1069 /* 0xb6 */ { NULL, NULL, 0 },
1070 /* 0xb7 */ { NULL, NULL, 0 },
1071 /* 0xb8 */ { NULL, NULL, 0 },
1072 /* 0xb9 */ { NULL, NULL, 0 },
1073 /* 0xba */ { NULL, NULL, 0 },
1074 /* 0xbb */ { NULL, NULL, 0 },
1075 /* 0xbc */ { NULL, NULL, 0 },
1076 /* 0xbd */ { NULL, NULL, 0 },
1077 /* 0xbe */ { NULL, NULL, 0 },
1078 /* 0xbf */ { NULL, NULL, 0 },
1079 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1080 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1081 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1082 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1083 /* 0xc4 */ { NULL, NULL, 0 },
1084 /* 0xc5 */ { NULL, NULL, 0 },
1085 /* 0xc6 */ { NULL, NULL, 0 },
1086 /* 0xc7 */ { NULL, NULL, 0 },
1087 /* 0xc8 */ { NULL, NULL, 0 },
1088 /* 0xc9 */ { NULL, NULL, 0 },
1089 /* 0xca */ { NULL, NULL, 0 },
1090 /* 0xcb */ { NULL, NULL, 0 },
1091 /* 0xcc */ { NULL, NULL, 0 },
1092 /* 0xcd */ { NULL, NULL, 0 },
1093 /* 0xce */ { NULL, NULL, 0 },
1094 /* 0xcf */ { NULL, NULL, 0 },
1095 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1096 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1097 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1098 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1099 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1100 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1101 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1102 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1103 /* 0xd8 */ { NULL, NULL, 0 },
1104 /* 0xd9 */ { NULL, NULL, 0 },
1105 /* 0xda */ { NULL, NULL, 0 },
1106 /* 0xdb */ { NULL, NULL, 0 },
1107 /* 0xdc */ { NULL, NULL, 0 },
1108 /* 0xdd */ { NULL, NULL, 0 },
1109 /* 0xde */ { NULL, NULL, 0 },
1110 /* 0xdf */ { NULL, NULL, 0 },
1111 /* 0xe0 */ { NULL, NULL, 0 },
1112 /* 0xe1 */ { NULL, NULL, 0 },
1113 /* 0xe2 */ { NULL, NULL, 0 },
1114 /* 0xe3 */ { NULL, NULL, 0 },
1115 /* 0xe4 */ { NULL, NULL, 0 },
1116 /* 0xe5 */ { NULL, NULL, 0 },
1117 /* 0xe6 */ { NULL, NULL, 0 },
1118 /* 0xe7 */ { NULL, NULL, 0 },
1119 /* 0xe8 */ { NULL, NULL, 0 },
1120 /* 0xe9 */ { NULL, NULL, 0 },
1121 /* 0xea */ { NULL, NULL, 0 },
1122 /* 0xeb */ { NULL, NULL, 0 },
1123 /* 0xec */ { NULL, NULL, 0 },
1124 /* 0xed */ { NULL, NULL, 0 },
1125 /* 0xee */ { NULL, NULL, 0 },
1126 /* 0xef */ { NULL, NULL, 0 },
1127 /* 0xf0 */ { NULL, NULL, 0 },
1128 /* 0xf1 */ { NULL, NULL, 0 },
1129 /* 0xf2 */ { NULL, NULL, 0 },
1130 /* 0xf3 */ { NULL, NULL, 0 },
1131 /* 0xf4 */ { NULL, NULL, 0 },
1132 /* 0xf5 */ { NULL, NULL, 0 },
1133 /* 0xf6 */ { NULL, NULL, 0 },
1134 /* 0xf7 */ { NULL, NULL, 0 },
1135 /* 0xf8 */ { NULL, NULL, 0 },
1136 /* 0xf9 */ { NULL, NULL, 0 },
1137 /* 0xfa */ { NULL, NULL, 0 },
1138 /* 0xfb */ { NULL, NULL, 0 },
1139 /* 0xfc */ { NULL, NULL, 0 },
1140 /* 0xfd */ { NULL, NULL, 0 },
1141 /* 0xfe */ { NULL, NULL, 0 },
1142 /* 0xff */ { NULL, NULL, 0 }
1143 
1144 };
1145 
1146 /*******************************************************************
1147  allocate and initialize a reply packet
1148 ********************************************************************/
1149 
1150 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
1151                           const char *inbuf, char **outbuf, uint8_t num_words,
1152                           uint32_t num_bytes)
1153 {
1154         /*
1155          * Protect against integer wrap
1156          */
1157         if ((num_bytes > 0xffffff)
1158             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1159                 char *msg;
1160                 if (asprintf(&msg, "num_bytes too large: %u",
1161                              (unsigned)num_bytes) == -1) {
1162                         msg = CONST_DISCARD(char *, "num_bytes too large");
1163                 }
1164                 smb_panic(msg);
1165         }
1166 
1167         *outbuf = TALLOC_ARRAY(mem_ctx, char,
1168                                smb_size + num_words*2 + num_bytes);
1169         if (*outbuf == NULL) {
1170                 return false;
1171         }
1172 
1173         construct_reply_common(req, inbuf, *outbuf);
1174         srv_set_message(*outbuf, num_words, num_bytes, false);
1175         /*
1176          * Zero out the word area, the caller has to take care of the bcc area
1177          * himself
1178          */
1179         if (num_words != 0) {
1180                 memset(*outbuf + smb_vwv0, 0, num_words*2);
1181         }
1182 
1183         return true;
1184 }
1185 
1186 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
     /* [<][>][^][v][top][bottom][index][help] */
1187 {
1188         char *outbuf;
1189         if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1190                            num_bytes)) {
1191                 smb_panic("could not allocate output buffer\n");
1192         }
1193         req->outbuf = (uint8_t *)outbuf;
1194 }
1195 
1196 
1197 /*******************************************************************
1198  Dump a packet to a file.
1199 ********************************************************************/
1200 
1201 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
     /* [<][>][^][v][top][bottom][index][help] */
1202 {
1203         int fd, i;
1204         char *fname = NULL;
1205         if (DEBUGLEVEL < 50) {
1206                 return;
1207         }
1208 
1209         if (len < 4) len = smb_len(data)+4;
1210         for (i=1;i<100;i++) {
1211                 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1212                              type ? "req" : "resp") == -1) {
1213                         return;
1214                 }
1215                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1216                 if (fd != -1 || errno != EEXIST) break;
1217         }
1218         if (fd != -1) {
1219                 ssize_t ret = write(fd, data, len);
1220                 if (ret != len)
1221                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1222                 close(fd);
1223                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1224         }
1225         SAFE_FREE(fname);
1226 }
1227 
1228 /****************************************************************************
1229  Prepare everything for calling the actual request function, and potentially
1230  call the request function via the "new" interface.
1231 
1232  Return False if the "legacy" function needs to be called, everything is
1233  prepared.
1234 
1235  Return True if we're done.
1236 
1237  I know this API sucks, but it is the one with the least code change I could
1238  find.
1239 ****************************************************************************/
1240 
1241 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
     /* [<][>][^][v][top][bottom][index][help] */
1242 {
1243         int flags;
1244         uint16 session_tag;
1245         connection_struct *conn = NULL;
1246 
1247         errno = 0;
1248 
1249         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1250          * so subtract 4 from it. */
1251         if (!valid_smb_header(req->inbuf)
1252             || (size < (smb_size - 4))) {
1253                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1254                          smb_len(req->inbuf)));
1255                 exit_server_cleanly("Non-SMB packet");
1256         }
1257 
1258         if (smb_messages[type].fn == NULL) {
1259                 DEBUG(0,("Unknown message type %d!\n",type));
1260                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1261                 reply_unknown_new(req, type);
1262                 return NULL;
1263         }
1264 
1265         flags = smb_messages[type].flags;
1266 
1267         /* In share mode security we must ignore the vuid. */
1268         session_tag = (lp_security() == SEC_SHARE)
1269                 ? UID_FIELD_INVALID : req->vuid;
1270         conn = req->conn;
1271 
1272         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1273                  (int)sys_getpid(), (unsigned long)conn));
1274 
1275         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1276 
1277         /* Ensure this value is replaced in the incoming packet. */
1278         SSVAL(req->inbuf,smb_uid,session_tag);
1279 
1280         /*
1281          * Ensure the correct username is in current_user_info.  This is a
1282          * really ugly bugfix for problems with multiple session_setup_and_X's
1283          * being done and allowing %U and %G substitutions to work correctly.
1284          * There is a reason this code is done here, don't move it unless you
1285          * know what you're doing... :-).
1286          * JRA.
1287          */
1288 
1289         if (session_tag != last_session_tag) {
1290                 user_struct *vuser = NULL;
1291 
1292                 last_session_tag = session_tag;
1293                 if(session_tag != UID_FIELD_INVALID) {
1294                         vuser = get_valid_user_struct(session_tag);
1295                         if (vuser) {
1296                                 set_current_user_info(
1297                                         vuser->server_info->sanitized_username,
1298                                         vuser->server_info->unix_name,
1299                                         pdb_get_domain(vuser->server_info
1300                                                        ->sam_account));
1301                         }
1302                 }
1303         }
1304 
1305         /* Does this call need to be run as the connected user? */
1306         if (flags & AS_USER) {
1307 
1308                 /* Does this call need a valid tree connection? */
1309                 if (!conn) {
1310                         /*
1311                          * Amazingly, the error code depends on the command
1312                          * (from Samba4).
1313                          */
1314                         if (type == SMBntcreateX) {
1315                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1316                         } else {
1317                                 reply_doserror(req, ERRSRV, ERRinvnid);
1318                         }
1319                         return NULL;
1320                 }
1321 
1322                 if (!change_to_user(conn,session_tag)) {
1323                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1324                         return conn;
1325                 }
1326 
1327                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1328 
1329                 /* Does it need write permission? */
1330                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1331                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1332                         return conn;
1333                 }
1334 
1335                 /* IPC services are limited */
1336                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1337                         reply_doserror(req, ERRSRV,ERRaccess);
1338                         return conn;
1339                 }
1340         } else {
1341                 /* This call needs to be run as root */
1342                 change_to_root_user();
1343         }
1344 
1345         /* load service specific parameters */
1346         if (conn) {
1347                 if (req->encrypted) {
1348                         conn->encrypted_tid = true;
1349                         /* encrypted required from now on. */
1350                         conn->encrypt_level = Required;
1351                 } else if (ENCRYPTION_REQUIRED(conn)) {
1352                         if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1353                                 exit_server_cleanly("encryption required "
1354                                         "on connection");
1355                                 return conn;
1356                         }
1357                 }
1358 
1359                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1360                                          (flags & (AS_USER|DO_CHDIR)
1361                                           ?True:False))) {
1362                         reply_doserror(req, ERRSRV, ERRaccess);
1363                         return conn;
1364                 }
1365                 conn->num_smb_operations++;
1366         }
1367 
1368         /* does this protocol need to be run as guest? */
1369         if ((flags & AS_GUEST)
1370             && (!change_to_guest() ||
1371                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1372                               lp_hostsdeny(-1)))) {
1373                 reply_doserror(req, ERRSRV, ERRaccess);
1374                 return conn;
1375         }
1376 
1377         smb_messages[type].fn(req);
1378         return req->conn;
1379 }
1380 
1381 /****************************************************************************
1382  Construct a reply to the incoming packet.
1383 ****************************************************************************/
1384 
1385 static void construct_reply(char *inbuf, int size, size_t unread_bytes,
     /* [<][>][^][v][top][bottom][index][help] */
1386                             bool encrypted,
1387                             struct smb_perfcount_data *deferred_pcd)
1388 {
1389         connection_struct *conn;
1390         struct smb_request *req;
1391 
1392         if (!(req = talloc(talloc_tos(), struct smb_request))) {
1393                 smb_panic("could not allocate smb_request");
1394         }
1395 
1396         init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1397         req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
1398 
1399         /* we popped this message off the queue - keep original perf data */
1400         if (deferred_pcd)
1401                 req->pcd = *deferred_pcd;
1402         else {
1403                 SMB_PERFCOUNT_START(&req->pcd);
1404                 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1405                 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1406         }
1407 
1408         conn = switch_message(req->cmd, req, size);
1409 
1410         if (req->unread_bytes) {
1411                 /* writeX failed. drain socket. */
1412                 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1413                                 req->unread_bytes) {
1414                         smb_panic("failed to drain pending bytes");
1415                 }
1416                 req->unread_bytes = 0;
1417         }
1418 
1419         if (req->done) {
1420                 TALLOC_FREE(req);
1421                 return;
1422         }
1423 
1424         if (req->outbuf == NULL) {
1425                 return;
1426         }
1427 
1428         if (CVAL(req->outbuf,0) == 0) {
1429                 show_msg((char *)req->outbuf);
1430         }
1431 
1432         if (!srv_send_smb(smbd_server_fd(),
1433                         (char *)req->outbuf,
1434                         IS_CONN_ENCRYPTED(conn)||req->encrypted,
1435                         &req->pcd)) {
1436                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1437         }
1438 
1439         TALLOC_FREE(req);
1440 
1441         return;
1442 }
1443 
1444 /****************************************************************************
1445  Process an smb from the client
1446 ****************************************************************************/
1447 static void process_smb(struct smbd_server_connection *conn,
     /* [<][>][^][v][top][bottom][index][help] */
1448                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
1449                         bool encrypted, struct smb_perfcount_data *deferred_pcd)
1450 {
1451         int msg_type = CVAL(inbuf,0);
1452 
1453         DO_PROFILE_INC(smb_count);
1454 
1455         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1456                     smb_len(inbuf) ) );
1457         DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1458                                 (int)nread,
1459                                 (unsigned int)unread_bytes ));
1460 
1461         if (msg_type != 0) {
1462                 /*
1463                  * NetBIOS session request, keepalive, etc.
1464                  */
1465                 reply_special((char *)inbuf);
1466                 goto done;
1467         }
1468 
1469         show_msg((char *)inbuf);
1470 
1471         construct_reply((char *)inbuf,nread,unread_bytes,encrypted,deferred_pcd);
1472         trans_num++;
1473 
1474 done:
1475         conn->num_requests++;
1476 
1477         /* The timeout_processing function isn't run nearly
1478            often enough to implement 'max log size' without
1479            overrunning the size of the file by many megabytes.
1480            This is especially true if we are running at debug
1481            level 10.  Checking every 50 SMBs is a nice
1482            tradeoff of performance vs log file size overrun. */
1483 
1484         if ((conn->num_requests % 50) == 0 &&
1485             need_to_check_log_size()) {
1486                 change_to_root_user();
1487                 check_log_size();
1488         }
1489 }
1490 
1491 /****************************************************************************
1492  Return a string containing the function name of a SMB command.
1493 ****************************************************************************/
1494 
1495 const char *smb_fn_name(int type)
     /* [<][>][^][v][top][bottom][index][help] */
1496 {
1497         const char *unknown_name = "SMBunknown";
1498 
1499         if (smb_messages[type].name == NULL)
1500                 return(unknown_name);
1501 
1502         return(smb_messages[type].name);
1503 }
1504 
1505 /****************************************************************************
1506  Helper functions for contruct_reply.
1507 ****************************************************************************/
1508 
1509 void add_to_common_flags2(uint32 v)
     /* [<][>][^][v][top][bottom][index][help] */
1510 {
1511         common_flags2 |= v;
1512 }
1513 
1514 void remove_from_common_flags2(uint32 v)
     /* [<][>][^][v][top][bottom][index][help] */
1515 {
1516         common_flags2 &= ~v;
1517 }
1518 
1519 static void construct_reply_common(struct smb_request *req, const char *inbuf,
     /* [<][>][^][v][top][bottom][index][help] */
1520                                    char *outbuf)
1521 {
1522         srv_set_message(outbuf,0,0,false);
1523         
1524         SCVAL(outbuf, smb_com, req->cmd);
1525         SIVAL(outbuf,smb_rcls,0);
1526         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1527         SSVAL(outbuf,smb_flg2,
1528                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1529                 common_flags2);
1530         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1531 
1532         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1533         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1534         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1535         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1536 }
1537 
1538 void construct_reply_common_req(struct smb_request *req, char *outbuf)
     /* [<][>][^][v][top][bottom][index][help] */
1539 {
1540         construct_reply_common(req, (char *)req->inbuf, outbuf);
1541 }
1542 
1543 /*
1544  * How many bytes have we already accumulated up to the current wct field
1545  * offset?
1546  */
1547 
1548 size_t req_wct_ofs(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1549 {
1550         size_t buf_size;
1551 
1552         if (req->chain_outbuf == NULL) {
1553                 return smb_wct - 4;
1554         }
1555         buf_size = talloc_get_size(req->chain_outbuf);
1556         if ((buf_size % 4) != 0) {
1557                 buf_size += (4 - (buf_size % 4));
1558         }
1559         return buf_size - 4;
1560 }
1561 
1562 /*
1563  * Hack around reply_nterror & friends not being aware of chained requests,
1564  * generating illegal (i.e. wct==0) chain replies.
1565  */
1566 
1567 static void fixup_chain_error_packet(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1568 {
1569         uint8_t *outbuf = req->outbuf;
1570         req->outbuf = NULL;
1571         reply_outbuf(req, 2, 0);
1572         memcpy(req->outbuf, outbuf, smb_wct);
1573         TALLOC_FREE(outbuf);
1574         SCVAL(req->outbuf, smb_vwv0, 0xff);
1575 }
1576 
1577 /****************************************************************************
1578  Construct a chained reply and add it to the already made reply
1579 ****************************************************************************/
1580 
1581 void chain_reply(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1582 {
1583         size_t smblen = smb_len(req->inbuf);
1584         size_t already_used, length_needed;
1585         uint8_t chain_cmd;
1586         uint32_t chain_offset;  /* uint32_t to avoid overflow */
1587 
1588         uint8_t wct;
1589         uint16_t *vwv;
1590         uint16_t buflen;
1591         uint8_t *buf;
1592 
1593         if (IVAL(req->outbuf, smb_rcls) != 0) {
1594                 fixup_chain_error_packet(req);
1595         }
1596 
1597         /*
1598          * Any of the AndX requests and replies have at least a wct of
1599          * 2. vwv[0] is the next command, vwv[1] is the offset from the
1600          * beginning of the SMB header to the next wct field.
1601          *
1602          * None of the AndX requests put anything valuable in vwv[0] and [1],
1603          * so we can overwrite it here to form the chain.
1604          */
1605 
1606         if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1607                 goto error;
1608         }
1609 
1610         /*
1611          * Here we assume that this is the end of the chain. For that we need
1612          * to set "next command" to 0xff and the offset to 0. If we later find
1613          * more commands in the chain, this will be overwritten again.
1614          */
1615 
1616         SCVAL(req->outbuf, smb_vwv0, 0xff);
1617         SCVAL(req->outbuf, smb_vwv0+1, 0);
1618         SSVAL(req->outbuf, smb_vwv1, 0);
1619 
1620         if (req->chain_outbuf == NULL) {
1621                 /*
1622                  * In req->chain_outbuf we collect all the replies. Start the
1623                  * chain by copying in the first reply.
1624                  *
1625                  * We do the realloc because later on we depend on
1626                  * talloc_get_size to determine the length of
1627                  * chain_outbuf. The reply_xxx routines might have
1628                  * over-allocated (reply_pipe_read_and_X used to be such an
1629                  * example).
1630                  */
1631                 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
1632                         req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
1633                 if (req->chain_outbuf == NULL) {
1634                         goto error;
1635                 }
1636                 req->outbuf = NULL;
1637         } else {
1638                 /*
1639                  * Update smb headers where subsequent chained commands
1640                  * may have updated them.
1641                  */
1642                 SCVAL(req->chain_outbuf, smb_tid, CVAL(req->outbuf, smb_tid));
1643                 SCVAL(req->chain_outbuf, smb_uid, CVAL(req->outbuf, smb_uid));
1644 
1645                 if (!smb_splice_chain(&req->chain_outbuf,
1646                                       CVAL(req->outbuf, smb_com),
1647                                       CVAL(req->outbuf, smb_wct),
1648                                       (uint16_t *)(req->outbuf + smb_vwv),
1649                                       0, smb_buflen(req->outbuf),
1650                                       (uint8_t *)smb_buf(req->outbuf))) {
1651                         goto error;
1652                 }
1653                 TALLOC_FREE(req->outbuf);
1654         }
1655 
1656         /*
1657          * We use the old request's vwv field to grab the next chained command
1658          * and offset into the chained fields.
1659          */
1660 
1661         chain_cmd = CVAL(req->vwv+0, 0);
1662         chain_offset = SVAL(req->vwv+1, 0);
1663 
1664         if (chain_cmd == 0xff) {
1665                 /*
1666                  * End of chain, no more requests from the client. So ship the
1667                  * replies.
1668                  */
1669                 smb_setlen((char *)(req->chain_outbuf),
1670                            talloc_get_size(req->chain_outbuf) - 4);
1671 
1672                 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1673                                   IS_CONN_ENCRYPTED(req->conn)
1674                                   ||req->encrypted,
1675                                   &req->pcd)) {
1676                         exit_server_cleanly("chain_reply: srv_send_smb "
1677                                             "failed.");
1678                 }
1679                 TALLOC_FREE(req->chain_outbuf);
1680                 req->done = true;
1681                 return;
1682         }
1683 
1684         /* add a new perfcounter for this element of chain */
1685         SMB_PERFCOUNT_ADD(&req->pcd);
1686         SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
1687         SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
1688 
1689         /*
1690          * Check if the client tries to fool us. The request so far uses the
1691          * space to the end of the byte buffer in the request just
1692          * processed. The chain_offset can't point into that area. If that was
1693          * the case, we could end up with an endless processing of the chain,
1694          * we would always handle the same request.
1695          */
1696 
1697         already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1698         if (chain_offset < already_used) {
1699                 goto error;
1700         }
1701 
1702         /*
1703          * Next check: Make sure the chain offset does not point beyond the
1704          * overall smb request length.
1705          */
1706 
1707         length_needed = chain_offset+1; /* wct */
1708         if (length_needed > smblen) {
1709                 goto error;
1710         }
1711 
1712         /*
1713          * Now comes the pointer magic. Goal here is to set up req->vwv and
1714          * req->buf correctly again to be able to call the subsequent
1715          * switch_message(). The chain offset (the former vwv[1]) points at
1716          * the new wct field.
1717          */
1718 
1719         wct = CVAL(smb_base(req->inbuf), chain_offset);
1720 
1721         /*
1722          * Next consistency check: Make the new vwv array fits in the overall
1723          * smb request.
1724          */
1725 
1726         length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1727         if (length_needed > smblen) {
1728                 goto error;
1729         }
1730         vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1731 
1732         /*
1733          * Now grab the new byte buffer....
1734          */
1735 
1736         buflen = SVAL(vwv+wct, 0);
1737 
1738         /*
1739          * .. and check that it fits.
1740          */
1741 
1742         length_needed += buflen;
1743         if (length_needed > smblen) {
1744                 goto error;
1745         }
1746         buf = (uint8_t *)(vwv+wct+1);
1747 
1748         req->cmd = chain_cmd;
1749         req->wct = wct;
1750         req->vwv = vwv;
1751         req->buflen = buflen;
1752         req->buf = buf;
1753 
1754         switch_message(chain_cmd, req, smblen);
1755 
1756         if (req->outbuf == NULL) {
1757                 /*
1758                  * This happens if the chained command has suspended itself or
1759                  * if it has called srv_send_smb() itself.
1760                  */
1761                 return;
1762         }
1763 
1764         /*
1765          * We end up here if the chained command was not itself chained or
1766          * suspended, but for example a close() command. We now need to splice
1767          * the chained commands' outbuf into the already built up chain_outbuf
1768          * and ship the result.
1769          */
1770         goto done;
1771 
1772  error:
1773         /*
1774          * We end up here if there's any error in the chain syntax. Report a
1775          * DOS error, just like Windows does.
1776          */
1777         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1778         fixup_chain_error_packet(req);
1779 
1780  done:
1781         if (!smb_splice_chain(&req->chain_outbuf,
1782                               CVAL(req->outbuf, smb_com),
1783                               CVAL(req->outbuf, smb_wct),
1784                               (uint16_t *)(req->outbuf + smb_vwv),
1785                               0, smb_buflen(req->outbuf),
1786                               (uint8_t *)smb_buf(req->outbuf))) {
1787                 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1788         }
1789         TALLOC_FREE(req->outbuf);
1790 
1791         smb_setlen((char *)(req->chain_outbuf),
1792                    talloc_get_size(req->chain_outbuf) - 4);
1793 
1794         show_msg((char *)(req->chain_outbuf));
1795 
1796         if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1797                           IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
1798                           &req->pcd)) {
1799                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1800         }
1801         TALLOC_FREE(req->chain_outbuf);
1802         req->done = true;
1803 }
1804 
1805 /****************************************************************************
1806  Check if services need reloading.
1807 ****************************************************************************/
1808 
1809 void check_reload(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
1810 {
1811         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1812 
1813         if(last_smb_conf_reload_time == 0) {
1814                 last_smb_conf_reload_time = t;
1815                 /* Our printing subsystem might not be ready at smbd start up.
1816                    Then no printer is available till the first printers check
1817                    is performed.  A lower initial interval circumvents this. */
1818                 if ( printcap_cache_time > 60 )
1819                         last_printer_reload_time = t - printcap_cache_time + 60;
1820                 else
1821                         last_printer_reload_time = t;
1822         }
1823 
1824         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1825                 /* randomize over 60 second the printcap reload to avoid all
1826                  * process hitting cupsd at the same time */
1827                 int time_range = 60;
1828 
1829                 last_printer_reload_time += random() % time_range;
1830                 mypid = getpid();
1831         }
1832 
1833         if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
1834                 reload_services(True);
1835                 last_smb_conf_reload_time = t;
1836         }
1837 
1838         /* 'printcap cache time = 0' disable the feature */
1839         
1840         if ( printcap_cache_time != 0 )
1841         { 
1842                 /* see if it's time to reload or if the clock has been set back */
1843                 
1844                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1845                         || (t-last_printer_reload_time  < 0) ) 
1846                 {
1847                         DEBUG( 3,( "Printcap cache time expired.\n"));
1848                         reload_printers();
1849                         last_printer_reload_time = t;
1850                 }
1851         }
1852 }
1853 
1854 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
     /* [<][>][^][v][top][bottom][index][help] */
1855 {
1856         /* TODO: make write nonblocking */
1857 }
1858 
1859 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
     /* [<][>][^][v][top][bottom][index][help] */
1860 {
1861         uint8_t *inbuf = NULL;
1862         size_t inbuf_len = 0;
1863         size_t unread_bytes = 0;
1864         bool encrypted = false;
1865         TALLOC_CTX *mem_ctx = talloc_tos();
1866         NTSTATUS status;
1867 
1868         /* TODO: make this completely nonblocking */
1869 
1870         status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1871                                     (char **)(void *)&inbuf,
1872                                     0, /* timeout */
1873                                     &unread_bytes,
1874                                     &encrypted,
1875                                     &inbuf_len);
1876         if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1877                 goto process;
1878         }
1879         if (NT_STATUS_IS_ERR(status)) {
1880                 exit_server_cleanly("failed to receive smb request");
1881         }
1882         if (!NT_STATUS_IS_OK(status)) {
1883                 return;
1884         }
1885 
1886 process:
1887         process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted, NULL);
1888 }
1889 
1890 static void smbd_server_connection_handler(struct event_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
1891                                            struct fd_event *fde,
1892                                            uint16_t flags,
1893                                            void *private_data)
1894 {
1895         struct smbd_server_connection *conn = talloc_get_type(private_data,
1896                                               struct smbd_server_connection);
1897 
1898         if (flags & EVENT_FD_WRITE) {
1899                 smbd_server_connection_write_handler(conn);
1900         } else if (flags & EVENT_FD_READ) {
1901                 smbd_server_connection_read_handler(conn);
1902         }
1903 }
1904 
1905 
1906 /****************************************************************************
1907 received when we should release a specific IP
1908 ****************************************************************************/
1909 static void release_ip(const char *ip, void *priv)
     /* [<][>][^][v][top][bottom][index][help] */
1910 {
1911         char addr[INET6_ADDRSTRLEN];
1912         char *p = addr;
1913 
1914         client_socket_addr(get_client_fd(),addr,sizeof(addr));
1915 
1916         if (strncmp("::ffff:", addr, 7) == 0) {
1917                 p = addr + 7;
1918         }
1919 
1920         if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
1921                 /* we can't afford to do a clean exit - that involves
1922                    database writes, which would potentially mean we
1923                    are still running after the failover has finished -
1924                    we have to get rid of this process ID straight
1925                    away */
1926                 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
1927                         ip));
1928                 /* note we must exit with non-zero status so the unclean handler gets
1929                    called in the parent, so that the brl database is tickled */
1930                 _exit(1);
1931         }
1932 }
1933 
1934 static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
     /* [<][>][^][v][top][bottom][index][help] */
1935                            uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
1936 {
1937         release_ip((char *)data->data, NULL);
1938 }
1939 
1940 #ifdef CLUSTER_SUPPORT
1941 static int client_get_tcp_info(struct sockaddr_storage *server,
     /* [<][>][^][v][top][bottom][index][help] */
1942                                struct sockaddr_storage *client)
1943 {
1944         socklen_t length;
1945         if (server_fd == -1) {
1946                 return -1;
1947         }
1948         length = sizeof(*server);
1949         if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) {
1950                 return -1;
1951         }
1952         length = sizeof(*client);
1953         if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) {
1954                 return -1;
1955         }
1956         return 0;
1957 }
1958 #endif
1959 
1960 /*
1961  * Send keepalive packets to our client
1962  */
1963 static bool keepalive_fn(const struct timeval *now, void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
1964 {
1965         if (!send_keepalive(smbd_server_fd())) {
1966                 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1967                 return False;
1968         }
1969         return True;
1970 }
1971 
1972 /*
1973  * Do the recurring check if we're idle
1974  */
1975 static bool deadtime_fn(const struct timeval *now, void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
1976 {
1977         if ((conn_num_open() == 0)
1978             || (conn_idle_all(now->tv_sec))) {
1979                 DEBUG( 2, ( "Closing idle connection\n" ) );
1980                 messaging_send(smbd_messaging_context(), procid_self(),
1981                                MSG_SHUTDOWN, &data_blob_null);
1982                 return False;
1983         }
1984 
1985         return True;
1986 }
1987 
1988 /*
1989  * Do the recurring log file and smb.conf reload checks.
1990  */
1991 
1992 static bool housekeeping_fn(const struct timeval *now, void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
1993 {
1994         change_to_root_user();
1995 
1996         /* update printer queue caches if necessary */
1997         update_monitored_printq_cache();
1998 
1999         /* check if we need to reload services */
2000         check_reload(time(NULL));
2001 
2002         /* Change machine password if neccessary. */
2003         attempt_machine_password_change();
2004 
2005         /*
2006          * Force a log file check.
2007          */
2008         force_check_log_size();
2009         check_log_size();
2010         return true;
2011 }
2012 
2013 /****************************************************************************
2014  Process commands from the client
2015 ****************************************************************************/
2016 
2017 void smbd_process(void)
     /* [<][>][^][v][top][bottom][index][help] */
2018 {
2019         TALLOC_CTX *frame = talloc_stackframe();
2020         char remaddr[INET6_ADDRSTRLEN];
2021 
2022         smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
2023         if (!smbd_server_conn) {
2024                 exit_server("failed to create smbd_server_connection");
2025         }
2026 
2027         /* Ensure child is set to blocking mode */
2028         set_blocking(smbd_server_fd(),True);
2029 
2030         set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2031         set_socket_options(smbd_server_fd(), lp_socket_options());
2032 
2033         /* this is needed so that we get decent entries
2034            in smbstatus for port 445 connects */
2035         set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2036                                               remaddr,
2037                                               sizeof(remaddr)),
2038                                               false);
2039         reload_services(true);
2040 
2041         /*
2042          * Before the first packet, check the global hosts allow/ hosts deny
2043          * parameters before doing any parsing of packets passed to us by the
2044          * client. This prevents attacks on our parsing code from hosts not in
2045          * the hosts allow list.
2046          */
2047 
2048         if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2049                           lp_hostsdeny(-1))) {
2050                 char addr[INET6_ADDRSTRLEN];
2051 
2052                 /*
2053                  * send a negative session response "not listening on calling
2054                  * name"
2055                  */
2056                 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2057                 DEBUG( 1, ("Connection denied from %s\n",
2058                            client_addr(get_client_fd(),addr,sizeof(addr)) ) );
2059                 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false, NULL);
2060                 exit_server_cleanly("connection denied");
2061         }
2062 
2063         static_init_rpc;
2064 
2065         init_modules();
2066 
2067         smb_perfcount_init();
2068 
2069         if (!init_account_policy()) {
2070                 exit_server("Could not open account policy tdb.\n");
2071         }
2072 
2073         if (*lp_rootdir()) {
2074                 if (chroot(lp_rootdir()) != 0) {
2075                         DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2076                         exit_server("Failed to chroot()");
2077                 }
2078                 if (chdir("/") == -1) {
2079                         DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
2080                         exit_server("Failed to chroot()");
2081                 }
2082                 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2083         }
2084 
2085         /* Setup oplocks */
2086         if (!init_oplocks(smbd_messaging_context()))
2087                 exit_server("Failed to init oplocks");
2088 
2089         /* Setup aio signal handler. */
2090         initialize_async_io_handler();
2091 
2092         /* register our message handlers */
2093         messaging_register(smbd_messaging_context(), NULL,
2094                            MSG_SMB_FORCE_TDIS, msg_force_tdis);
2095         messaging_register(smbd_messaging_context(), NULL,
2096                            MSG_SMB_RELEASE_IP, msg_release_ip);
2097         messaging_register(smbd_messaging_context(), NULL,
2098                            MSG_SMB_CLOSE_FILE, msg_close_file);
2099 
2100         if ((lp_keepalive() != 0)
2101             && !(event_add_idle(smbd_event_context(), NULL,
2102                                 timeval_set(lp_keepalive(), 0),
2103                                 "keepalive", keepalive_fn,
2104                                 NULL))) {
2105                 DEBUG(0, ("Could not add keepalive event\n"));
2106                 exit(1);
2107         }
2108 
2109         if (!(event_add_idle(smbd_event_context(), NULL,
2110                              timeval_set(IDLE_CLOSED_TIMEOUT, 0),
2111                              "deadtime", deadtime_fn, NULL))) {
2112                 DEBUG(0, ("Could not add deadtime event\n"));
2113                 exit(1);
2114         }
2115 
2116         if (!(event_add_idle(smbd_event_context(), NULL,
2117                              timeval_set(SMBD_SELECT_TIMEOUT, 0),
2118                              "housekeeping", housekeeping_fn, NULL))) {
2119                 DEBUG(0, ("Could not add housekeeping event\n"));
2120                 exit(1);
2121         }
2122 
2123 #ifdef CLUSTER_SUPPORT
2124 
2125         if (lp_clustering()) {
2126                 /*
2127                  * We need to tell ctdb about our client's TCP
2128                  * connection, so that for failover ctdbd can send
2129                  * tickle acks, triggering a reconnection by the
2130                  * client.
2131                  */
2132 
2133                 struct sockaddr_storage srv, clnt;
2134 
2135                 if (client_get_tcp_info(&srv, &clnt) == 0) {
2136 
2137                         NTSTATUS status;
2138 
2139                         status = ctdbd_register_ips(
2140                                 messaging_ctdbd_connection(),
2141                                 &srv, &clnt, release_ip, NULL);
2142 
2143                         if (!NT_STATUS_IS_OK(status)) {
2144                                 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2145                                           nt_errstr(status)));
2146                         }
2147                 } else
2148                 {
2149                         DEBUG(0,("Unable to get tcp info for "
2150                                  "CTDB_CONTROL_TCP_CLIENT: %s\n",
2151                                  strerror(errno)));
2152                 }
2153         }
2154 
2155 #endif
2156 
2157         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
2158 
2159         smbd_server_conn->fde = event_add_fd(smbd_event_context(),
2160                                              smbd_server_conn,
2161                                              smbd_server_fd(),
2162                                              EVENT_FD_READ,
2163                                              smbd_server_connection_handler,
2164                                              smbd_server_conn);
2165         if (!smbd_server_conn->fde) {
2166                 exit_server("failed to create smbd_server_connection fde");
2167         }
2168 
2169         TALLOC_FREE(frame);
2170 
2171         while (True) {
2172                 NTSTATUS status;
2173 
2174                 frame = talloc_stackframe_pool(8192);
2175 
2176                 errno = 0;
2177 
2178                 status = smbd_server_connection_loop_once(smbd_server_conn);
2179                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2180                     !NT_STATUS_IS_OK(status)) {
2181                         DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2182                                   " exiting\n", nt_errstr(status)));
2183                         break;
2184                 }
2185 
2186                 TALLOC_FREE(frame);
2187         }
2188 
2189         exit_server_cleanly(NULL);
2190 }
2191 
2192 bool req_is_in_chain(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
2193 {
2194         if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
2195                 /*
2196                  * We're right now handling a subsequent request, so we must
2197                  * be in a chain
2198                  */
2199                 return true;
2200         }
2201 
2202         if (!is_andx_req(req->cmd)) {
2203                 return false;
2204         }
2205 
2206         if (req->wct < 2) {
2207                 /*
2208                  * Okay, an illegal request, but definitely not chained :-)
2209                  */
2210                 return false;
2211         }
2212 
2213         return (CVAL(req->vwv+0, 0) != 0xFF);
2214 }

/* [<][>][^][v][top][bottom][index][help] */