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
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.
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.
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/>.
22 #include "smbd/globals.h"
24 extern bool global_machine_password_needs_changing;
26 static void construct_reply_common(struct smb_request *req, const char *inbuf,
29 /* Accessor function for smb_read_error for smbd functions. */
31 /****************************************************************************
33 ****************************************************************************/
35 bool srv_send_smb(int fd, char *buffer,
36 bool do_signing, uint32_t seqnum,
38 struct smb_perfcount_data *pcd)
43 char *buf_out = buffer;
46 /* Sign the outgoing packet if required. */
47 srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum);
51 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
52 if (!NT_STATUS_IS_OK(status)) {
53 DEBUG(0, ("send_smb: SMB encryption failed "
54 "on outgoing packet! Error %s\n",
60 len = smb_len(buf_out) + 4;
62 while (nwritten < len) {
63 ret = write_data(fd,buf_out+nwritten,len - nwritten);
65 DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
66 (int)len,(int)ret, strerror(errno) ));
67 srv_free_enc_buffer(buf_out);
73 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
74 srv_free_enc_buffer(buf_out);
76 SMB_PERFCOUNT_END(pcd);
80 /*******************************************************************
81 Setup the word count and byte count for a smb message.
82 ********************************************************************/
84 int srv_set_message(char *buf,
89 if (zero && (num_words || num_bytes)) {
90 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
92 SCVAL(buf,smb_wct,num_words);
93 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
94 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
95 return (smb_size + num_words*2 + num_bytes);
98 static bool valid_smb_header(const uint8_t *inbuf)
100 if (is_encrypted_packet(inbuf)) {
104 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
105 * but it just looks weird to call strncmp for this one.
107 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
110 /* Socket functions for smbd packet processing. */
112 static bool valid_packet_size(size_t len)
115 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
116 * of header. Don't print the error if this fits.... JRA.
119 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
120 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
121 (unsigned long)len));
127 static NTSTATUS read_packet_remainder(int fd, char *buffer,
128 unsigned int timeout, ssize_t len)
134 return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL);
137 /****************************************************************************
138 Attempt a zerocopy writeX read. We know here that len > smb_size-4
139 ****************************************************************************/
142 * Unfortunately, earlier versions of smbclient/libsmbclient
143 * don't send this "standard" writeX header. I've fixed this
144 * for 3.2 but we'll use the old method with earlier versions.
145 * Windows and CIFSFS at least use this standard size. Not
149 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
150 (2*14) + /* word count (including bcc) */ \
153 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
154 const char lenbuf[4],
155 int fd, char **buffer,
156 unsigned int timeout,
160 /* Size of a WRITEX call (+4 byte len). */
161 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
162 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
166 memcpy(writeX_header, lenbuf, 4);
168 status = read_socket_with_timeout(
169 fd, writeX_header + 4,
170 STANDARD_WRITE_AND_X_HEADER_SIZE,
171 STANDARD_WRITE_AND_X_HEADER_SIZE,
174 if (!NT_STATUS_IS_OK(status)) {
179 * Ok - now try and see if this is a possible
183 if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
185 * If the data offset is beyond what
186 * we've read, drain the extra bytes.
188 uint16_t doff = SVAL(writeX_header,smb_vwv11);
191 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
192 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
193 if (drain_socket(smbd_server_fd(), drain) != drain) {
194 smb_panic("receive_smb_raw_talloc_partial_read:"
195 " failed to drain pending bytes");
198 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
201 /* Spoof down the length and null out the bcc. */
202 set_message_bcc(writeX_header, 0);
203 newlen = smb_len(writeX_header);
205 /* Copy the header we've written. */
207 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
209 sizeof(writeX_header));
211 if (*buffer == NULL) {
212 DEBUG(0, ("Could not allocate inbuf of length %d\n",
213 (int)sizeof(writeX_header)));
214 return NT_STATUS_NO_MEMORY;
217 /* Work out the remaining bytes. */
218 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
219 *len_ret = newlen + 4;
223 if (!valid_packet_size(len)) {
224 return NT_STATUS_INVALID_PARAMETER;
228 * Not a valid writeX call. Just do the standard
232 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
234 if (*buffer == NULL) {
235 DEBUG(0, ("Could not allocate inbuf of length %d\n",
237 return NT_STATUS_NO_MEMORY;
240 /* Copy in what we already read. */
243 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
244 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
247 status = read_packet_remainder(
248 fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
251 if (!NT_STATUS_IS_OK(status)) {
252 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
262 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
263 char **buffer, unsigned int timeout,
264 size_t *p_unread, size_t *plen)
268 int min_recv_size = lp_min_receive_file_size();
273 status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
274 if (!NT_STATUS_IS_OK(status)) {
275 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
279 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
280 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
281 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
282 !srv_is_signing_active(smbd_server_conn)) {
284 return receive_smb_raw_talloc_partial_read(
285 mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
288 if (!valid_packet_size(len)) {
289 return NT_STATUS_INVALID_PARAMETER;
293 * The +4 here can't wrap, we've checked the length above already.
296 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
298 if (*buffer == NULL) {
299 DEBUG(0, ("Could not allocate inbuf of length %d\n",
301 return NT_STATUS_NO_MEMORY;
304 memcpy(*buffer, lenbuf, sizeof(lenbuf));
306 status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
307 if (!NT_STATUS_IS_OK(status)) {
315 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
316 char **buffer, unsigned int timeout,
317 size_t *p_unread, bool *p_encrypted,
324 *p_encrypted = false;
326 status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
328 if (!NT_STATUS_IS_OK(status)) {
332 if (is_encrypted_packet((uint8_t *)*buffer)) {
333 status = srv_decrypt_buffer(*buffer);
334 if (!NT_STATUS_IS_OK(status)) {
335 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
336 "incoming packet! Error %s\n",
337 nt_errstr(status) ));
343 /* Check the incoming SMB signature. */
344 if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) {
345 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
346 "incoming packet!\n"));
347 return NT_STATUS_INVALID_NETWORK_RESPONSE;
355 * Initialize a struct smb_request from an inbuf
358 void init_smb_request(struct smb_request *req,
363 size_t req_size = smb_len(inbuf) + 4;
364 /* Ensure we have at least smb_size bytes. */
365 if (req_size < smb_size) {
366 DEBUG(0,("init_smb_request: invalid request size %u\n",
367 (unsigned int)req_size ));
368 exit_server_cleanly("Invalid SMB request");
370 req->cmd = CVAL(inbuf, smb_com);
371 req->flags2 = SVAL(inbuf, smb_flg2);
372 req->smbpid = SVAL(inbuf, smb_pid);
373 req->mid = SVAL(inbuf, smb_mid);
375 req->vuid = SVAL(inbuf, smb_uid);
376 req->tid = SVAL(inbuf, smb_tid);
377 req->wct = CVAL(inbuf, smb_wct);
378 req->vwv = (uint16_t *)(inbuf+smb_vwv);
379 req->buflen = smb_buflen(inbuf);
380 req->buf = (const uint8_t *)smb_buf(inbuf);
381 req->unread_bytes = unread_bytes;
382 req->encrypted = encrypted;
383 req->conn = conn_find(req->tid);
384 req->chain_fsp = NULL;
385 req->chain_outbuf = NULL;
386 smb_init_perfcount_data(&req->pcd);
388 /* Ensure we have at least wct words and 2 bytes of bcc. */
389 if (smb_size + req->wct*2 > req_size) {
390 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
391 (unsigned int)req->wct,
392 (unsigned int)req_size));
393 exit_server_cleanly("Invalid SMB request");
395 /* Ensure bcc is correct. */
396 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
397 DEBUG(0,("init_smb_request: invalid bcc number %u "
398 "(wct = %u, size %u)\n",
399 (unsigned int)req->buflen,
400 (unsigned int)req->wct,
401 (unsigned int)req_size));
402 exit_server_cleanly("Invalid SMB request");
408 static void process_smb(struct smbd_server_connection *conn,
409 uint8_t *inbuf, size_t nread, size_t unread_bytes,
410 uint32_t seqnum, bool encrypted,
411 struct smb_perfcount_data *deferred_pcd);
413 static void smbd_deferred_open_timer(struct event_context *ev,
414 struct timed_event *te,
415 struct timeval _tval,
418 struct pending_message_list *msg = talloc_get_type(private_data,
419 struct pending_message_list);
420 TALLOC_CTX *mem_ctx = talloc_tos();
423 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
426 exit_server("smbd_deferred_open_timer: talloc failed\n");
430 /* We leave this message on the queue so the open code can
431 know this is a retry. */
432 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
433 (unsigned int)SVAL(msg->buf.data,smb_mid)));
435 process_smb(smbd_server_conn, inbuf,
437 msg->seqnum, msg->encrypted, &msg->pcd);
440 /****************************************************************************
441 Function to push a message onto the tail of a linked list of smb messages ready
443 ****************************************************************************/
445 static bool push_queued_message(struct smb_request *req,
446 struct timeval request_time,
447 struct timeval end_time,
448 char *private_data, size_t private_len)
450 int msg_len = smb_len(req->inbuf) + 4;
451 struct pending_message_list *msg;
453 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
456 DEBUG(0,("push_message: malloc fail (1)\n"));
460 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
461 if(msg->buf.data == NULL) {
462 DEBUG(0,("push_message: malloc fail (2)\n"));
467 msg->request_time = request_time;
468 msg->seqnum = req->seqnum;
469 msg->encrypted = req->encrypted;
470 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
473 msg->private_data = data_blob_talloc(msg, private_data,
475 if (msg->private_data.data == NULL) {
476 DEBUG(0,("push_message: malloc fail (3)\n"));
482 msg->te = event_add_timed(smbd_event_context(),
485 smbd_deferred_open_timer,
488 DEBUG(0,("push_message: event_add_timed failed\n"));
493 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
495 DEBUG(10,("push_message: pushed message length %u on "
496 "deferred_open_queue\n", (unsigned int)msg_len));
501 /****************************************************************************
502 Function to delete a sharing violation open message by mid.
503 ****************************************************************************/
505 void remove_deferred_open_smb_message(uint16 mid)
507 struct pending_message_list *pml;
509 for (pml = deferred_open_queue; pml; pml = pml->next) {
510 if (mid == SVAL(pml->buf.data,smb_mid)) {
511 DEBUG(10,("remove_sharing_violation_open_smb_message: "
512 "deleting mid %u len %u\n",
514 (unsigned int)pml->buf.length ));
515 DLIST_REMOVE(deferred_open_queue, pml);
522 /****************************************************************************
523 Move a sharing violation open retry message to the front of the list and
524 schedule it for immediate processing.
525 ****************************************************************************/
527 void schedule_deferred_open_smb_message(uint16 mid)
529 struct pending_message_list *pml;
532 for (pml = deferred_open_queue; pml; pml = pml->next) {
533 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
535 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
536 (unsigned int)msg_mid ));
538 if (mid == msg_mid) {
539 struct timed_event *te;
541 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
544 te = event_add_timed(smbd_event_context(),
547 smbd_deferred_open_timer,
550 DEBUG(10,("schedule_deferred_open_smb_message: "
551 "event_add_timed() failed, skipping mid %u\n",
555 TALLOC_FREE(pml->te);
557 DLIST_PROMOTE(deferred_open_queue, pml);
562 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
566 /****************************************************************************
567 Return true if this mid is on the deferred queue.
568 ****************************************************************************/
570 bool open_was_deferred(uint16 mid)
572 struct pending_message_list *pml;
574 for (pml = deferred_open_queue; pml; pml = pml->next) {
575 if (SVAL(pml->buf.data,smb_mid) == mid) {
582 /****************************************************************************
583 Return the message queued by this mid.
584 ****************************************************************************/
586 struct pending_message_list *get_open_deferred_message(uint16 mid)
588 struct pending_message_list *pml;
590 for (pml = deferred_open_queue; pml; pml = pml->next) {
591 if (SVAL(pml->buf.data,smb_mid) == mid) {
598 /****************************************************************************
599 Function to push a deferred open smb message onto a linked list of local smb
600 messages ready for processing.
601 ****************************************************************************/
603 bool push_deferred_smb_message(struct smb_request *req,
604 struct timeval request_time,
605 struct timeval timeout,
606 char *private_data, size_t priv_len)
608 struct timeval end_time;
610 if (req->unread_bytes) {
611 DEBUG(0,("push_deferred_smb_message: logic error ! "
612 "unread_bytes = %u\n",
613 (unsigned int)req->unread_bytes ));
614 smb_panic("push_deferred_smb_message: "
615 "logic error unread_bytes != 0" );
618 end_time = timeval_sum(&request_time, &timeout);
620 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
621 "timeout time [%u.%06u]\n",
622 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
623 (unsigned int)end_time.tv_sec,
624 (unsigned int)end_time.tv_usec));
626 return push_queued_message(req, request_time, end_time,
627 private_data, priv_len);
631 struct timed_event *te;
632 struct timeval interval;
634 bool (*handler)(const struct timeval *now, void *private_data);
638 static void smbd_idle_event_handler(struct event_context *ctx,
639 struct timed_event *te,
643 struct idle_event *event =
644 talloc_get_type_abort(private_data, struct idle_event);
646 TALLOC_FREE(event->te);
648 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
649 event->name, event->te));
651 if (!event->handler(&now, event->private_data)) {
652 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
653 event->name, event->te));
654 /* Don't repeat, delete ourselves */
659 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
660 event->name, event->te));
662 event->te = event_add_timed(ctx, event,
663 timeval_sum(&now, &event->interval),
664 smbd_idle_event_handler, event);
666 /* We can't do much but fail here. */
667 SMB_ASSERT(event->te != NULL);
670 struct idle_event *event_add_idle(struct event_context *event_ctx,
672 struct timeval interval,
674 bool (*handler)(const struct timeval *now,
678 struct idle_event *result;
679 struct timeval now = timeval_current();
681 result = TALLOC_P(mem_ctx, struct idle_event);
682 if (result == NULL) {
683 DEBUG(0, ("talloc failed\n"));
687 result->interval = interval;
688 result->handler = handler;
689 result->private_data = private_data;
691 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
692 DEBUG(0, ("talloc failed\n"));
697 result->te = event_add_timed(event_ctx, result,
698 timeval_sum(&now, &interval),
699 smbd_idle_event_handler, result);
700 if (result->te == NULL) {
701 DEBUG(0, ("event_add_timed failed\n"));
706 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
710 static void smbd_sig_term_handler(struct tevent_context *ev,
711 struct tevent_signal *se,
717 exit_server_cleanly("termination signal");
720 void smbd_setup_sig_term_handler(void)
722 struct tevent_signal *se;
724 se = tevent_add_signal(smbd_event_context(),
725 smbd_event_context(),
727 smbd_sig_term_handler,
730 exit_server("failed to setup SIGTERM handler");
734 static void smbd_sig_hup_handler(struct tevent_context *ev,
735 struct tevent_signal *se,
741 change_to_root_user();
742 DEBUG(1,("Reloading services after SIGHUP\n"));
743 reload_services(False);
746 void smbd_setup_sig_hup_handler(void)
748 struct tevent_signal *se;
750 se = tevent_add_signal(smbd_event_context(),
751 smbd_event_context(),
753 smbd_sig_hup_handler,
756 exit_server("failed to setup SIGHUP handler");
760 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
767 to.tv_sec = SMBD_SELECT_TIMEOUT;
771 * Setup the select fd sets.
778 * Are there any timed events waiting ? If so, ensure we don't
779 * select for longer than it would take to wait for them.
786 event_add_to_select_args(smbd_event_context(), &now,
787 &r_fds, &w_fds, &to, &maxfd);
790 /* Process a signal and timed events now... */
791 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
792 return NT_STATUS_RETRY;
797 START_PROFILE(smbd_idle);
799 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
802 END_PROFILE(smbd_idle);
806 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
807 return NT_STATUS_RETRY;
812 /* something is wrong. Maybe the socket is dead? */
813 return map_nt_error_from_unix(errno);
816 /* Did we timeout ? */
818 return NT_STATUS_RETRY;
821 /* should not be reached */
822 return NT_STATUS_INTERNAL_ERROR;
826 * Only allow 5 outstanding trans requests. We're allocating memory, so
830 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
833 for (; list != NULL; list = list->next) {
835 if (list->mid == mid) {
836 return NT_STATUS_INVALID_PARAMETER;
842 return NT_STATUS_INSUFFICIENT_RESOURCES;
849 These flags determine some of the permissions required to do an operation
851 Note that I don't set NEED_WRITE on some write operations because they
852 are used by some brain-dead clients when printing, and I don't want to
853 force write permissions on print services.
855 #define AS_USER (1<<0)
856 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
857 #define TIME_INIT (1<<2)
858 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
859 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
860 #define DO_CHDIR (1<<6)
863 define a list of possible SMB messages and their corresponding
864 functions. Any message that has a NULL function is unimplemented -
865 please feel free to contribute implementations!
867 static const struct smb_message_struct {
869 void (*fn)(struct smb_request *req);
871 } smb_messages[256] = {
873 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
874 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
875 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
876 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
877 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
878 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
879 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
880 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
881 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
882 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
883 /* 0x0a */ { "SMBread",reply_read,AS_USER},
884 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
885 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
886 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
887 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
888 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
889 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
890 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
891 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
892 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
893 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
894 /* 0x15 */ { NULL, NULL, 0 },
895 /* 0x16 */ { NULL, NULL, 0 },
896 /* 0x17 */ { NULL, NULL, 0 },
897 /* 0x18 */ { NULL, NULL, 0 },
898 /* 0x19 */ { NULL, NULL, 0 },
899 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
900 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
901 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
902 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
903 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
904 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
905 /* 0x20 */ { "SMBwritec", NULL,0},
906 /* 0x21 */ { NULL, NULL, 0 },
907 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
908 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
909 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
910 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
911 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
912 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
913 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
914 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
915 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
916 /* 0x2b */ { "SMBecho",reply_echo,0},
917 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
918 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
919 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
920 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
921 /* 0x30 */ { NULL, NULL, 0 },
922 /* 0x31 */ { NULL, NULL, 0 },
923 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
924 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
925 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
926 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
927 /* 0x36 */ { NULL, NULL, 0 },
928 /* 0x37 */ { NULL, NULL, 0 },
929 /* 0x38 */ { NULL, NULL, 0 },
930 /* 0x39 */ { NULL, NULL, 0 },
931 /* 0x3a */ { NULL, NULL, 0 },
932 /* 0x3b */ { NULL, NULL, 0 },
933 /* 0x3c */ { NULL, NULL, 0 },
934 /* 0x3d */ { NULL, NULL, 0 },
935 /* 0x3e */ { NULL, NULL, 0 },
936 /* 0x3f */ { NULL, NULL, 0 },
937 /* 0x40 */ { NULL, NULL, 0 },
938 /* 0x41 */ { NULL, NULL, 0 },
939 /* 0x42 */ { NULL, NULL, 0 },
940 /* 0x43 */ { NULL, NULL, 0 },
941 /* 0x44 */ { NULL, NULL, 0 },
942 /* 0x45 */ { NULL, NULL, 0 },
943 /* 0x46 */ { NULL, NULL, 0 },
944 /* 0x47 */ { NULL, NULL, 0 },
945 /* 0x48 */ { NULL, NULL, 0 },
946 /* 0x49 */ { NULL, NULL, 0 },
947 /* 0x4a */ { NULL, NULL, 0 },
948 /* 0x4b */ { NULL, NULL, 0 },
949 /* 0x4c */ { NULL, NULL, 0 },
950 /* 0x4d */ { NULL, NULL, 0 },
951 /* 0x4e */ { NULL, NULL, 0 },
952 /* 0x4f */ { NULL, NULL, 0 },
953 /* 0x50 */ { NULL, NULL, 0 },
954 /* 0x51 */ { NULL, NULL, 0 },
955 /* 0x52 */ { NULL, NULL, 0 },
956 /* 0x53 */ { NULL, NULL, 0 },
957 /* 0x54 */ { NULL, NULL, 0 },
958 /* 0x55 */ { NULL, NULL, 0 },
959 /* 0x56 */ { NULL, NULL, 0 },
960 /* 0x57 */ { NULL, NULL, 0 },
961 /* 0x58 */ { NULL, NULL, 0 },
962 /* 0x59 */ { NULL, NULL, 0 },
963 /* 0x5a */ { NULL, NULL, 0 },
964 /* 0x5b */ { NULL, NULL, 0 },
965 /* 0x5c */ { NULL, NULL, 0 },
966 /* 0x5d */ { NULL, NULL, 0 },
967 /* 0x5e */ { NULL, NULL, 0 },
968 /* 0x5f */ { NULL, NULL, 0 },
969 /* 0x60 */ { NULL, NULL, 0 },
970 /* 0x61 */ { NULL, NULL, 0 },
971 /* 0x62 */ { NULL, NULL, 0 },
972 /* 0x63 */ { NULL, NULL, 0 },
973 /* 0x64 */ { NULL, NULL, 0 },
974 /* 0x65 */ { NULL, NULL, 0 },
975 /* 0x66 */ { NULL, NULL, 0 },
976 /* 0x67 */ { NULL, NULL, 0 },
977 /* 0x68 */ { NULL, NULL, 0 },
978 /* 0x69 */ { NULL, NULL, 0 },
979 /* 0x6a */ { NULL, NULL, 0 },
980 /* 0x6b */ { NULL, NULL, 0 },
981 /* 0x6c */ { NULL, NULL, 0 },
982 /* 0x6d */ { NULL, NULL, 0 },
983 /* 0x6e */ { NULL, NULL, 0 },
984 /* 0x6f */ { NULL, NULL, 0 },
985 /* 0x70 */ { "SMBtcon",reply_tcon,0},
986 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
987 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
988 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
989 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
990 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
991 /* 0x76 */ { NULL, NULL, 0 },
992 /* 0x77 */ { NULL, NULL, 0 },
993 /* 0x78 */ { NULL, NULL, 0 },
994 /* 0x79 */ { NULL, NULL, 0 },
995 /* 0x7a */ { NULL, NULL, 0 },
996 /* 0x7b */ { NULL, NULL, 0 },
997 /* 0x7c */ { NULL, NULL, 0 },
998 /* 0x7d */ { NULL, NULL, 0 },
999 /* 0x7e */ { NULL, NULL, 0 },
1000 /* 0x7f */ { NULL, NULL, 0 },
1001 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1002 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1003 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1004 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1005 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1006 /* 0x85 */ { NULL, NULL, 0 },
1007 /* 0x86 */ { NULL, NULL, 0 },
1008 /* 0x87 */ { NULL, NULL, 0 },
1009 /* 0x88 */ { NULL, NULL, 0 },
1010 /* 0x89 */ { NULL, NULL, 0 },
1011 /* 0x8a */ { NULL, NULL, 0 },
1012 /* 0x8b */ { NULL, NULL, 0 },
1013 /* 0x8c */ { NULL, NULL, 0 },
1014 /* 0x8d */ { NULL, NULL, 0 },
1015 /* 0x8e */ { NULL, NULL, 0 },
1016 /* 0x8f */ { NULL, NULL, 0 },
1017 /* 0x90 */ { NULL, NULL, 0 },
1018 /* 0x91 */ { NULL, NULL, 0 },
1019 /* 0x92 */ { NULL, NULL, 0 },
1020 /* 0x93 */ { NULL, NULL, 0 },
1021 /* 0x94 */ { NULL, NULL, 0 },
1022 /* 0x95 */ { NULL, NULL, 0 },
1023 /* 0x96 */ { NULL, NULL, 0 },
1024 /* 0x97 */ { NULL, NULL, 0 },
1025 /* 0x98 */ { NULL, NULL, 0 },
1026 /* 0x99 */ { NULL, NULL, 0 },
1027 /* 0x9a */ { NULL, NULL, 0 },
1028 /* 0x9b */ { NULL, NULL, 0 },
1029 /* 0x9c */ { NULL, NULL, 0 },
1030 /* 0x9d */ { NULL, NULL, 0 },
1031 /* 0x9e */ { NULL, NULL, 0 },
1032 /* 0x9f */ { NULL, NULL, 0 },
1033 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1034 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1035 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1036 /* 0xa3 */ { NULL, NULL, 0 },
1037 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1038 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1039 /* 0xa6 */ { NULL, NULL, 0 },
1040 /* 0xa7 */ { NULL, NULL, 0 },
1041 /* 0xa8 */ { NULL, NULL, 0 },
1042 /* 0xa9 */ { NULL, NULL, 0 },
1043 /* 0xaa */ { NULL, NULL, 0 },
1044 /* 0xab */ { NULL, NULL, 0 },
1045 /* 0xac */ { NULL, NULL, 0 },
1046 /* 0xad */ { NULL, NULL, 0 },
1047 /* 0xae */ { NULL, NULL, 0 },
1048 /* 0xaf */ { NULL, NULL, 0 },
1049 /* 0xb0 */ { NULL, NULL, 0 },
1050 /* 0xb1 */ { NULL, NULL, 0 },
1051 /* 0xb2 */ { NULL, NULL, 0 },
1052 /* 0xb3 */ { NULL, NULL, 0 },
1053 /* 0xb4 */ { NULL, NULL, 0 },
1054 /* 0xb5 */ { NULL, NULL, 0 },
1055 /* 0xb6 */ { NULL, NULL, 0 },
1056 /* 0xb7 */ { NULL, NULL, 0 },
1057 /* 0xb8 */ { NULL, NULL, 0 },
1058 /* 0xb9 */ { NULL, NULL, 0 },
1059 /* 0xba */ { NULL, NULL, 0 },
1060 /* 0xbb */ { NULL, NULL, 0 },
1061 /* 0xbc */ { NULL, NULL, 0 },
1062 /* 0xbd */ { NULL, NULL, 0 },
1063 /* 0xbe */ { NULL, NULL, 0 },
1064 /* 0xbf */ { NULL, NULL, 0 },
1065 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1066 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1067 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1068 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1069 /* 0xc4 */ { NULL, NULL, 0 },
1070 /* 0xc5 */ { NULL, NULL, 0 },
1071 /* 0xc6 */ { NULL, NULL, 0 },
1072 /* 0xc7 */ { NULL, NULL, 0 },
1073 /* 0xc8 */ { NULL, NULL, 0 },
1074 /* 0xc9 */ { NULL, NULL, 0 },
1075 /* 0xca */ { NULL, NULL, 0 },
1076 /* 0xcb */ { NULL, NULL, 0 },
1077 /* 0xcc */ { NULL, NULL, 0 },
1078 /* 0xcd */ { NULL, NULL, 0 },
1079 /* 0xce */ { NULL, NULL, 0 },
1080 /* 0xcf */ { NULL, NULL, 0 },
1081 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1082 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1083 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1084 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1085 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1086 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1087 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1088 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1089 /* 0xd8 */ { NULL, NULL, 0 },
1090 /* 0xd9 */ { NULL, NULL, 0 },
1091 /* 0xda */ { NULL, NULL, 0 },
1092 /* 0xdb */ { NULL, NULL, 0 },
1093 /* 0xdc */ { NULL, NULL, 0 },
1094 /* 0xdd */ { NULL, NULL, 0 },
1095 /* 0xde */ { NULL, NULL, 0 },
1096 /* 0xdf */ { NULL, NULL, 0 },
1097 /* 0xe0 */ { NULL, NULL, 0 },
1098 /* 0xe1 */ { NULL, NULL, 0 },
1099 /* 0xe2 */ { NULL, NULL, 0 },
1100 /* 0xe3 */ { NULL, NULL, 0 },
1101 /* 0xe4 */ { NULL, NULL, 0 },
1102 /* 0xe5 */ { NULL, NULL, 0 },
1103 /* 0xe6 */ { NULL, NULL, 0 },
1104 /* 0xe7 */ { NULL, NULL, 0 },
1105 /* 0xe8 */ { NULL, NULL, 0 },
1106 /* 0xe9 */ { NULL, NULL, 0 },
1107 /* 0xea */ { NULL, NULL, 0 },
1108 /* 0xeb */ { NULL, NULL, 0 },
1109 /* 0xec */ { NULL, NULL, 0 },
1110 /* 0xed */ { NULL, NULL, 0 },
1111 /* 0xee */ { NULL, NULL, 0 },
1112 /* 0xef */ { NULL, NULL, 0 },
1113 /* 0xf0 */ { NULL, NULL, 0 },
1114 /* 0xf1 */ { NULL, NULL, 0 },
1115 /* 0xf2 */ { NULL, NULL, 0 },
1116 /* 0xf3 */ { NULL, NULL, 0 },
1117 /* 0xf4 */ { NULL, NULL, 0 },
1118 /* 0xf5 */ { NULL, NULL, 0 },
1119 /* 0xf6 */ { NULL, NULL, 0 },
1120 /* 0xf7 */ { NULL, NULL, 0 },
1121 /* 0xf8 */ { NULL, NULL, 0 },
1122 /* 0xf9 */ { NULL, NULL, 0 },
1123 /* 0xfa */ { NULL, NULL, 0 },
1124 /* 0xfb */ { NULL, NULL, 0 },
1125 /* 0xfc */ { NULL, NULL, 0 },
1126 /* 0xfd */ { NULL, NULL, 0 },
1127 /* 0xfe */ { NULL, NULL, 0 },
1128 /* 0xff */ { NULL, NULL, 0 }
1132 /*******************************************************************
1133 allocate and initialize a reply packet
1134 ********************************************************************/
1136 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1137 const char *inbuf, char **outbuf, uint8_t num_words,
1141 * Protect against integer wrap
1143 if ((num_bytes > 0xffffff)
1144 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1146 if (asprintf(&msg, "num_bytes too large: %u",
1147 (unsigned)num_bytes) == -1) {
1148 msg = CONST_DISCARD(char *, "num_bytes too large");
1153 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1154 smb_size + num_words*2 + num_bytes);
1155 if (*outbuf == NULL) {
1159 construct_reply_common(req, inbuf, *outbuf);
1160 srv_set_message(*outbuf, num_words, num_bytes, false);
1162 * Zero out the word area, the caller has to take care of the bcc area
1165 if (num_words != 0) {
1166 memset(*outbuf + smb_vwv0, 0, num_words*2);
1172 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1175 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1177 smb_panic("could not allocate output buffer\n");
1179 req->outbuf = (uint8_t *)outbuf;
1183 /*******************************************************************
1184 Dump a packet to a file.
1185 ********************************************************************/
1187 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1191 if (DEBUGLEVEL < 50) {
1195 if (len < 4) len = smb_len(data)+4;
1196 for (i=1;i<100;i++) {
1197 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1198 type ? "req" : "resp") == -1) {
1201 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1202 if (fd != -1 || errno != EEXIST) break;
1205 ssize_t ret = write(fd, data, len);
1207 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1209 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1214 /****************************************************************************
1215 Prepare everything for calling the actual request function, and potentially
1216 call the request function via the "new" interface.
1218 Return False if the "legacy" function needs to be called, everything is
1221 Return True if we're done.
1223 I know this API sucks, but it is the one with the least code change I could
1225 ****************************************************************************/
1227 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1231 connection_struct *conn = NULL;
1235 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1236 * so subtract 4 from it. */
1237 if (!valid_smb_header(req->inbuf)
1238 || (size < (smb_size - 4))) {
1239 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1240 smb_len(req->inbuf)));
1241 exit_server_cleanly("Non-SMB packet");
1244 if (smb_messages[type].fn == NULL) {
1245 DEBUG(0,("Unknown message type %d!\n",type));
1246 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1247 reply_unknown_new(req, type);
1251 flags = smb_messages[type].flags;
1253 /* In share mode security we must ignore the vuid. */
1254 session_tag = (lp_security() == SEC_SHARE)
1255 ? UID_FIELD_INVALID : req->vuid;
1258 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1259 (int)sys_getpid(), (unsigned long)conn));
1261 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1263 /* Ensure this value is replaced in the incoming packet. */
1264 SSVAL(req->inbuf,smb_uid,session_tag);
1267 * Ensure the correct username is in current_user_info. This is a
1268 * really ugly bugfix for problems with multiple session_setup_and_X's
1269 * being done and allowing %U and %G substitutions to work correctly.
1270 * There is a reason this code is done here, don't move it unless you
1271 * know what you're doing... :-).
1275 if (session_tag != last_session_tag) {
1276 user_struct *vuser = NULL;
1278 last_session_tag = session_tag;
1279 if(session_tag != UID_FIELD_INVALID) {
1280 vuser = get_valid_user_struct(session_tag);
1282 set_current_user_info(
1283 vuser->server_info->sanitized_username,
1284 vuser->server_info->unix_name,
1285 pdb_get_domain(vuser->server_info
1291 /* Does this call need to be run as the connected user? */
1292 if (flags & AS_USER) {
1294 /* Does this call need a valid tree connection? */
1297 * Amazingly, the error code depends on the command
1300 if (type == SMBntcreateX) {
1301 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1303 reply_doserror(req, ERRSRV, ERRinvnid);
1308 if (!change_to_user(conn,session_tag)) {
1309 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1310 remove_deferred_open_smb_message(req->mid);
1314 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1316 /* Does it need write permission? */
1317 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1318 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1322 /* IPC services are limited */
1323 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1324 reply_doserror(req, ERRSRV,ERRaccess);
1328 /* This call needs to be run as root */
1329 change_to_root_user();
1332 /* load service specific parameters */
1334 if (req->encrypted) {
1335 conn->encrypted_tid = true;
1336 /* encrypted required from now on. */
1337 conn->encrypt_level = Required;
1338 } else if (ENCRYPTION_REQUIRED(conn)) {
1339 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1340 exit_server_cleanly("encryption required "
1346 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1347 (flags & (AS_USER|DO_CHDIR)
1349 reply_doserror(req, ERRSRV, ERRaccess);
1352 conn->num_smb_operations++;
1355 /* does this protocol need to be run as guest? */
1356 if ((flags & AS_GUEST)
1357 && (!change_to_guest() ||
1358 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1359 lp_hostsdeny(-1)))) {
1360 reply_doserror(req, ERRSRV, ERRaccess);
1364 smb_messages[type].fn(req);
1368 /****************************************************************************
1369 Construct a reply to the incoming packet.
1370 ****************************************************************************/
1372 static void construct_reply(char *inbuf, int size, size_t unread_bytes,
1373 uint32_t seqnum, bool encrypted,
1374 struct smb_perfcount_data *deferred_pcd)
1376 connection_struct *conn;
1377 struct smb_request *req;
1379 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1380 smb_panic("could not allocate smb_request");
1383 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1384 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1385 req->seqnum = seqnum;
1387 /* we popped this message off the queue - keep original perf data */
1389 req->pcd = *deferred_pcd;
1391 SMB_PERFCOUNT_START(&req->pcd);
1392 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1393 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1396 conn = switch_message(req->cmd, req, size);
1398 if (req->unread_bytes) {
1399 /* writeX failed. drain socket. */
1400 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1401 req->unread_bytes) {
1402 smb_panic("failed to drain pending bytes");
1404 req->unread_bytes = 0;
1407 if (req->outbuf == NULL) {
1411 if (CVAL(req->outbuf,0) == 0) {
1412 show_msg((char *)req->outbuf);
1415 if (!srv_send_smb(smbd_server_fd(),
1416 (char *)req->outbuf,
1417 true, req->seqnum+1,
1418 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1420 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1428 /****************************************************************************
1429 Process an smb from the client
1430 ****************************************************************************/
1431 static void process_smb(struct smbd_server_connection *conn,
1432 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1433 uint32_t seqnum, bool encrypted,
1434 struct smb_perfcount_data *deferred_pcd)
1436 int msg_type = CVAL(inbuf,0);
1438 DO_PROFILE_INC(smb_count);
1440 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1442 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1444 (unsigned int)unread_bytes ));
1446 if (msg_type != 0) {
1448 * NetBIOS session request, keepalive, etc.
1450 reply_special((char *)inbuf);
1454 show_msg((char *)inbuf);
1456 construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
1460 conn->num_requests++;
1462 /* The timeout_processing function isn't run nearly
1463 often enough to implement 'max log size' without
1464 overrunning the size of the file by many megabytes.
1465 This is especially true if we are running at debug
1466 level 10. Checking every 50 SMBs is a nice
1467 tradeoff of performance vs log file size overrun. */
1469 if ((conn->num_requests % 50) == 0 &&
1470 need_to_check_log_size()) {
1471 change_to_root_user();
1476 /****************************************************************************
1477 Return a string containing the function name of a SMB command.
1478 ****************************************************************************/
1480 const char *smb_fn_name(int type)
1482 const char *unknown_name = "SMBunknown";
1484 if (smb_messages[type].name == NULL)
1485 return(unknown_name);
1487 return(smb_messages[type].name);
1490 /****************************************************************************
1491 Helper functions for contruct_reply.
1492 ****************************************************************************/
1494 void add_to_common_flags2(uint32 v)
1499 void remove_from_common_flags2(uint32 v)
1501 common_flags2 &= ~v;
1504 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1507 srv_set_message(outbuf,0,0,false);
1509 SCVAL(outbuf, smb_com, req->cmd);
1510 SIVAL(outbuf,smb_rcls,0);
1511 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1512 SSVAL(outbuf,smb_flg2,
1513 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1515 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1517 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1518 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1519 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1520 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1523 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1525 construct_reply_common(req, (char *)req->inbuf, outbuf);
1529 * How many bytes have we already accumulated up to the current wct field
1533 size_t req_wct_ofs(struct smb_request *req)
1537 if (req->chain_outbuf == NULL) {
1540 buf_size = talloc_get_size(req->chain_outbuf);
1541 if ((buf_size % 4) != 0) {
1542 buf_size += (4 - (buf_size % 4));
1544 return buf_size - 4;
1548 * Hack around reply_nterror & friends not being aware of chained requests,
1549 * generating illegal (i.e. wct==0) chain replies.
1552 static void fixup_chain_error_packet(struct smb_request *req)
1554 uint8_t *outbuf = req->outbuf;
1556 reply_outbuf(req, 2, 0);
1557 memcpy(req->outbuf, outbuf, smb_wct);
1558 TALLOC_FREE(outbuf);
1559 SCVAL(req->outbuf, smb_vwv0, 0xff);
1562 /****************************************************************************
1563 Construct a chained reply and add it to the already made reply
1564 ****************************************************************************/
1566 void chain_reply(struct smb_request *req)
1568 size_t smblen = smb_len(req->inbuf);
1569 size_t already_used, length_needed;
1571 uint32_t chain_offset; /* uint32_t to avoid overflow */
1578 if (IVAL(req->outbuf, smb_rcls) != 0) {
1579 fixup_chain_error_packet(req);
1583 * Any of the AndX requests and replies have at least a wct of
1584 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1585 * beginning of the SMB header to the next wct field.
1587 * None of the AndX requests put anything valuable in vwv[0] and [1],
1588 * so we can overwrite it here to form the chain.
1591 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1596 * Here we assume that this is the end of the chain. For that we need
1597 * to set "next command" to 0xff and the offset to 0. If we later find
1598 * more commands in the chain, this will be overwritten again.
1601 SCVAL(req->outbuf, smb_vwv0, 0xff);
1602 SCVAL(req->outbuf, smb_vwv0+1, 0);
1603 SSVAL(req->outbuf, smb_vwv1, 0);
1605 if (req->chain_outbuf == NULL) {
1607 * In req->chain_outbuf we collect all the replies. Start the
1608 * chain by copying in the first reply.
1610 * We do the realloc because later on we depend on
1611 * talloc_get_size to determine the length of
1612 * chain_outbuf. The reply_xxx routines might have
1613 * over-allocated (reply_pipe_read_and_X used to be such an
1616 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
1617 req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
1618 if (req->chain_outbuf == NULL) {
1623 if (!smb_splice_chain(&req->chain_outbuf,
1624 CVAL(req->outbuf, smb_com),
1625 CVAL(req->outbuf, smb_wct),
1626 (uint16_t *)(req->outbuf + smb_vwv),
1627 0, smb_buflen(req->outbuf),
1628 (uint8_t *)smb_buf(req->outbuf))) {
1631 TALLOC_FREE(req->outbuf);
1635 * We use the old request's vwv field to grab the next chained command
1636 * and offset into the chained fields.
1639 chain_cmd = CVAL(req->vwv+0, 0);
1640 chain_offset = SVAL(req->vwv+1, 0);
1642 if (chain_cmd == 0xff) {
1644 * End of chain, no more requests from the client. So ship the
1647 smb_setlen((char *)(req->chain_outbuf),
1648 talloc_get_size(req->chain_outbuf) - 4);
1650 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1651 true, req->seqnum+1,
1652 IS_CONN_ENCRYPTED(req->conn)
1655 exit_server_cleanly("chain_reply: srv_send_smb "
1663 /* add a new perfcounter for this element of chain */
1664 SMB_PERFCOUNT_ADD(&req->pcd);
1665 SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
1666 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
1669 * Check if the client tries to fool us. The request so far uses the
1670 * space to the end of the byte buffer in the request just
1671 * processed. The chain_offset can't point into that area. If that was
1672 * the case, we could end up with an endless processing of the chain,
1673 * we would always handle the same request.
1676 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1677 if (chain_offset < already_used) {
1682 * Next check: Make sure the chain offset does not point beyond the
1683 * overall smb request length.
1686 length_needed = chain_offset+1; /* wct */
1687 if (length_needed > smblen) {
1692 * Now comes the pointer magic. Goal here is to set up req->vwv and
1693 * req->buf correctly again to be able to call the subsequent
1694 * switch_message(). The chain offset (the former vwv[1]) points at
1695 * the new wct field.
1698 wct = CVAL(smb_base(req->inbuf), chain_offset);
1701 * Next consistency check: Make the new vwv array fits in the overall
1705 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1706 if (length_needed > smblen) {
1709 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1712 * Now grab the new byte buffer....
1715 buflen = SVAL(vwv+wct, 0);
1718 * .. and check that it fits.
1721 length_needed += buflen;
1722 if (length_needed > smblen) {
1725 buf = (uint8_t *)(vwv+wct+1);
1727 req->cmd = chain_cmd;
1730 req->buflen = buflen;
1733 switch_message(chain_cmd, req, smblen);
1735 if (req->outbuf == NULL) {
1737 * This happens if the chained command has suspended itself or
1738 * if it has called srv_send_smb() itself.
1744 * We end up here if the chained command was not itself chained or
1745 * suspended, but for example a close() command. We now need to splice
1746 * the chained commands' outbuf into the already built up chain_outbuf
1747 * and ship the result.
1753 * We end up here if there's any error in the chain syntax. Report a
1754 * DOS error, just like Windows does.
1756 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1757 fixup_chain_error_packet(req);
1760 if (!smb_splice_chain(&req->chain_outbuf,
1761 CVAL(req->outbuf, smb_com),
1762 CVAL(req->outbuf, smb_wct),
1763 (uint16_t *)(req->outbuf + smb_vwv),
1764 0, smb_buflen(req->outbuf),
1765 (uint8_t *)smb_buf(req->outbuf))) {
1766 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1768 TALLOC_FREE(req->outbuf);
1770 smb_setlen((char *)(req->chain_outbuf),
1771 talloc_get_size(req->chain_outbuf) - 4);
1773 show_msg((char *)(req->chain_outbuf));
1775 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1776 true, req->seqnum+1,
1777 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
1779 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1784 /****************************************************************************
1785 Check if services need reloading.
1786 ****************************************************************************/
1788 void check_reload(time_t t)
1790 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1792 if(last_smb_conf_reload_time == 0) {
1793 last_smb_conf_reload_time = t;
1794 /* Our printing subsystem might not be ready at smbd start up.
1795 Then no printer is available till the first printers check
1796 is performed. A lower initial interval circumvents this. */
1797 if ( printcap_cache_time > 60 )
1798 last_printer_reload_time = t - printcap_cache_time + 60;
1800 last_printer_reload_time = t;
1803 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1804 /* randomize over 60 second the printcap reload to avoid all
1805 * process hitting cupsd at the same time */
1806 int time_range = 60;
1808 last_printer_reload_time += random() % time_range;
1812 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
1813 reload_services(True);
1814 last_smb_conf_reload_time = t;
1817 /* 'printcap cache time = 0' disable the feature */
1819 if ( printcap_cache_time != 0 )
1821 /* see if it's time to reload or if the clock has been set back */
1823 if ( (t >= last_printer_reload_time+printcap_cache_time)
1824 || (t-last_printer_reload_time < 0) )
1826 DEBUG( 3,( "Printcap cache time expired.\n"));
1828 last_printer_reload_time = t;
1833 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1835 /* TODO: make write nonblocking */
1838 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1840 uint8_t *inbuf = NULL;
1841 size_t inbuf_len = 0;
1842 size_t unread_bytes = 0;
1843 bool encrypted = false;
1844 TALLOC_CTX *mem_ctx = talloc_tos();
1848 /* TODO: make this completely nonblocking */
1850 status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1851 (char **)(void *)&inbuf,
1855 &inbuf_len, &seqnum);
1856 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1859 if (NT_STATUS_IS_ERR(status)) {
1860 exit_server_cleanly("failed to receive smb request");
1862 if (!NT_STATUS_IS_OK(status)) {
1867 process_smb(conn, inbuf, inbuf_len, unread_bytes,
1868 seqnum, encrypted, NULL);
1871 static void smbd_server_connection_handler(struct event_context *ev,
1872 struct fd_event *fde,
1876 struct smbd_server_connection *conn = talloc_get_type(private_data,
1877 struct smbd_server_connection);
1879 if (flags & EVENT_FD_WRITE) {
1880 smbd_server_connection_write_handler(conn);
1881 } else if (flags & EVENT_FD_READ) {
1882 smbd_server_connection_read_handler(conn);
1887 /****************************************************************************
1888 received when we should release a specific IP
1889 ****************************************************************************/
1890 static void release_ip(const char *ip, void *priv)
1892 char addr[INET6_ADDRSTRLEN];
1894 if (strcmp(client_socket_addr(get_client_fd(),addr,sizeof(addr)), ip) == 0) {
1895 /* we can't afford to do a clean exit - that involves
1896 database writes, which would potentially mean we
1897 are still running after the failover has finished -
1898 we have to get rid of this process ID straight
1900 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
1902 /* note we must exit with non-zero status so the unclean handler gets
1903 called in the parent, so that the brl database is tickled */
1908 static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
1909 uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
1911 release_ip((char *)data->data, NULL);
1914 #ifdef CLUSTER_SUPPORT
1915 static int client_get_tcp_info(struct sockaddr_storage *server,
1916 struct sockaddr_storage *client)
1919 if (server_fd == -1) {
1922 length = sizeof(*server);
1923 if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) {
1926 length = sizeof(*client);
1927 if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) {
1935 * Send keepalive packets to our client
1937 static bool keepalive_fn(const struct timeval *now, void *private_data)
1939 if (!send_keepalive(smbd_server_fd())) {
1940 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1947 * Do the recurring check if we're idle
1949 static bool deadtime_fn(const struct timeval *now, void *private_data)
1951 if ((conn_num_open() == 0)
1952 || (conn_idle_all(now->tv_sec))) {
1953 DEBUG( 2, ( "Closing idle connection\n" ) );
1954 messaging_send(smbd_messaging_context(), procid_self(),
1955 MSG_SHUTDOWN, &data_blob_null);
1963 * Do the recurring log file and smb.conf reload checks.
1966 static bool housekeeping_fn(const struct timeval *now, void *private_data)
1968 change_to_root_user();
1970 /* update printer queue caches if necessary */
1971 update_monitored_printq_cache();
1973 /* check if we need to reload services */
1974 check_reload(time(NULL));
1976 /* Change machine password if neccessary. */
1977 attempt_machine_password_change();
1980 * Force a log file check.
1982 force_check_log_size();
1987 /****************************************************************************
1988 Process commands from the client
1989 ****************************************************************************/
1991 void smbd_process(void)
1993 TALLOC_CTX *frame = talloc_stackframe();
1994 char remaddr[INET6_ADDRSTRLEN];
1996 smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
1997 if (!smbd_server_conn) {
1998 exit_server("failed to create smbd_server_connection");
2001 /* Ensure child is set to blocking mode */
2002 set_blocking(smbd_server_fd(),True);
2004 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2005 set_socket_options(smbd_server_fd(), lp_socket_options());
2007 /* this is needed so that we get decent entries
2008 in smbstatus for port 445 connects */
2009 set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2013 reload_services(true);
2016 * Before the first packet, check the global hosts allow/ hosts deny
2017 * parameters before doing any parsing of packets passed to us by the
2018 * client. This prevents attacks on our parsing code from hosts not in
2019 * the hosts allow list.
2022 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2023 lp_hostsdeny(-1))) {
2024 char addr[INET6_ADDRSTRLEN];
2027 * send a negative session response "not listening on calling
2030 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2031 DEBUG( 1, ("Connection denied from %s\n",
2032 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
2033 (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
2035 exit_server_cleanly("connection denied");
2042 smb_perfcount_init();
2044 if (!init_account_policy()) {
2045 exit_server("Could not open account policy tdb.\n");
2048 if (*lp_rootdir()) {
2049 if (chroot(lp_rootdir()) != 0) {
2050 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2051 exit_server("Failed to chroot()");
2053 if (chdir("/") == -1) {
2054 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
2055 exit_server("Failed to chroot()");
2057 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2060 if (!srv_init_signing(smbd_server_conn)) {
2061 exit_server("Failed to init smb_signing");
2065 if (!init_oplocks(smbd_messaging_context()))
2066 exit_server("Failed to init oplocks");
2068 /* Setup aio signal handler. */
2069 initialize_async_io_handler();
2071 /* register our message handlers */
2072 messaging_register(smbd_messaging_context(), NULL,
2073 MSG_SMB_FORCE_TDIS, msg_force_tdis);
2074 messaging_register(smbd_messaging_context(), NULL,
2075 MSG_SMB_RELEASE_IP, msg_release_ip);
2076 messaging_register(smbd_messaging_context(), NULL,
2077 MSG_SMB_CLOSE_FILE, msg_close_file);
2079 if ((lp_keepalive() != 0)
2080 && !(event_add_idle(smbd_event_context(), NULL,
2081 timeval_set(lp_keepalive(), 0),
2082 "keepalive", keepalive_fn,
2084 DEBUG(0, ("Could not add keepalive event\n"));
2088 if (!(event_add_idle(smbd_event_context(), NULL,
2089 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
2090 "deadtime", deadtime_fn, NULL))) {
2091 DEBUG(0, ("Could not add deadtime event\n"));
2095 if (!(event_add_idle(smbd_event_context(), NULL,
2096 timeval_set(SMBD_SELECT_TIMEOUT, 0),
2097 "housekeeping", housekeeping_fn, NULL))) {
2098 DEBUG(0, ("Could not add housekeeping event\n"));
2102 #ifdef CLUSTER_SUPPORT
2104 if (lp_clustering()) {
2106 * We need to tell ctdb about our client's TCP
2107 * connection, so that for failover ctdbd can send
2108 * tickle acks, triggering a reconnection by the
2112 struct sockaddr_storage srv, clnt;
2114 if (client_get_tcp_info(&srv, &clnt) == 0) {
2118 status = ctdbd_register_ips(
2119 messaging_ctdbd_connection(),
2120 &srv, &clnt, release_ip, NULL);
2122 if (!NT_STATUS_IS_OK(status)) {
2123 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2124 nt_errstr(status)));
2128 DEBUG(0,("Unable to get tcp info for "
2129 "CTDB_CONTROL_TCP_CLIENT: %s\n",
2136 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
2138 smbd_server_conn->fde = event_add_fd(smbd_event_context(),
2142 smbd_server_connection_handler,
2144 if (!smbd_server_conn->fde) {
2145 exit_server("failed to create smbd_server_connection fde");
2153 frame = talloc_stackframe_pool(8192);
2157 status = smbd_server_connection_loop_once(smbd_server_conn);
2158 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2159 !NT_STATUS_IS_OK(status)) {
2160 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2161 " exiting\n", nt_errstr(status)));
2168 exit_server_cleanly(NULL);
2171 bool req_is_in_chain(struct smb_request *req)
2173 if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
2175 * We're right now handling a subsequent request, so we must
2181 if (!is_andx_req(req->cmd)) {
2187 * Okay, an illegal request, but definitely not chained :-)
2192 return (CVAL(req->vwv+0, 0) != 0xFF);