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 "../lib/tsocket/tsocket.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "librpc/gen_ndr/netlogon.h"
27 #include "../lib/async_req/async_sock.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/select.h"
30 #include "printing/queue_process.h"
31 #include "system/select.h"
35 #include "smbprofile.h"
36 #include "rpc_server/spoolss/srv_spoolss_nt.h"
37 #include "libsmb/libsmb.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "../libcli/security/dom_sid.h"
40 #include "../libcli/security/security_token.h"
41 #include "lib/id_cache.h"
44 /* Internal message queue for deferred opens. */
45 struct pending_message_list
{
46 struct pending_message_list
*next
, *prev
;
47 struct timeval request_time
; /* When was this first issued? */
48 struct smbd_server_connection
*sconn
;
49 struct tevent_timer
*te
;
50 struct smb_perfcount_data pcd
;
55 DATA_BLOB private_data
;
58 static void construct_reply_common(struct smb_request
*req
, const char *inbuf
,
60 static struct pending_message_list
*get_deferred_open_message_smb(
61 struct smbd_server_connection
*sconn
, uint64_t mid
);
62 static bool smb_splice_chain(uint8_t **poutbuf
, const uint8_t *andx_buf
);
64 static bool smbd_lock_socket_internal(struct smbd_server_connection
*sconn
)
68 if (sconn
->smb1
.echo_handler
.socket_lock_fd
== -1) {
72 sconn
->smb1
.echo_handler
.ref_count
++;
74 if (sconn
->smb1
.echo_handler
.ref_count
> 1) {
78 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
82 sconn
->smb1
.echo_handler
.socket_lock_fd
,
83 F_SETLKW
, 0, 0, F_WRLCK
);
84 } while (!ok
&& (errno
== EINTR
));
87 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno
)));
91 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
96 void smbd_lock_socket(struct smbd_server_connection
*sconn
)
98 if (!smbd_lock_socket_internal(sconn
)) {
99 exit_server_cleanly("failed to lock socket");
103 static bool smbd_unlock_socket_internal(struct smbd_server_connection
*sconn
)
107 if (sconn
->smb1
.echo_handler
.socket_lock_fd
== -1) {
111 sconn
->smb1
.echo_handler
.ref_count
--;
113 if (sconn
->smb1
.echo_handler
.ref_count
> 0) {
119 sconn
->smb1
.echo_handler
.socket_lock_fd
,
120 F_SETLKW
, 0, 0, F_UNLCK
);
121 } while (!ok
&& (errno
== EINTR
));
124 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno
)));
128 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
133 void smbd_unlock_socket(struct smbd_server_connection
*sconn
)
135 if (!smbd_unlock_socket_internal(sconn
)) {
136 exit_server_cleanly("failed to unlock socket");
140 /* Accessor function for smb_read_error for smbd functions. */
142 /****************************************************************************
144 ****************************************************************************/
146 bool srv_send_smb(struct smbd_server_connection
*sconn
, char *buffer
,
147 bool do_signing
, uint32_t seqnum
,
149 struct smb_perfcount_data
*pcd
)
153 char *buf_out
= buffer
;
155 if (!NT_STATUS_IS_OK(sconn
->status
)) {
157 * we're not supposed to do any io
162 smbd_lock_socket(sconn
);
165 /* Sign the outgoing packet if required. */
166 srv_calculate_sign_mac(sconn
, buf_out
, seqnum
);
170 NTSTATUS status
= srv_encrypt_buffer(sconn
, buffer
, &buf_out
);
171 if (!NT_STATUS_IS_OK(status
)) {
172 DEBUG(0, ("send_smb: SMB encryption failed "
173 "on outgoing packet! Error %s\n",
174 nt_errstr(status
) ));
179 len
= smb_len_large(buf_out
) + 4;
181 ret
= write_data(sconn
->sock
, buf_out
, len
);
184 char addr
[INET6_ADDRSTRLEN
];
186 * Try and give an error message saying what
189 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
190 (int)getpid(), (int)len
,
191 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
192 (int)ret
, strerror(errno
) ));
194 srv_free_enc_buffer(sconn
, buf_out
);
198 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd
, len
);
199 srv_free_enc_buffer(sconn
, buf_out
);
201 SMB_PERFCOUNT_END(pcd
);
203 smbd_unlock_socket(sconn
);
207 /*******************************************************************
208 Setup the word count and byte count for a smb message.
209 ********************************************************************/
211 int srv_set_message(char *buf
,
216 if (zero
&& (num_words
|| num_bytes
)) {
217 memset(buf
+ smb_size
,'\0',num_words
*2 + num_bytes
);
219 SCVAL(buf
,smb_wct
,num_words
);
220 SSVAL(buf
,smb_vwv
+ num_words
*SIZEOFWORD
,num_bytes
);
221 smb_setlen(buf
,(smb_size
+ num_words
*2 + num_bytes
- 4));
222 return (smb_size
+ num_words
*2 + num_bytes
);
225 static bool valid_smb_header(struct smbd_server_connection
*sconn
,
226 const uint8_t *inbuf
)
228 if (is_encrypted_packet(sconn
, inbuf
)) {
232 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
233 * but it just looks weird to call strncmp for this one.
235 return (IVAL(smb_base(inbuf
), 0) == 0x424D53FF);
238 /* Socket functions for smbd packet processing. */
240 static bool valid_packet_size(size_t len
)
243 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
244 * of header. Don't print the error if this fits.... JRA.
247 if (len
> (LARGE_WRITEX_BUFFER_SIZE
+ LARGE_WRITEX_HDR_SIZE
)) {
248 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
249 (unsigned long)len
));
255 static NTSTATUS
read_packet_remainder(int fd
, char *buffer
,
256 unsigned int timeout
, ssize_t len
)
264 status
= read_fd_with_timeout(fd
, buffer
, len
, len
, timeout
, NULL
);
265 if (!NT_STATUS_IS_OK(status
)) {
266 char addr
[INET6_ADDRSTRLEN
];
267 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
269 get_peer_addr(fd
, addr
, sizeof(addr
)),
275 /****************************************************************************
276 Attempt a zerocopy writeX read. We know here that len > smb_size-4
277 ****************************************************************************/
280 * Unfortunately, earlier versions of smbclient/libsmbclient
281 * don't send this "standard" writeX header. I've fixed this
282 * for 3.2 but we'll use the old method with earlier versions.
283 * Windows and CIFSFS at least use this standard size. Not
287 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
288 (2*14) + /* word count (including bcc) */ \
291 static NTSTATUS
receive_smb_raw_talloc_partial_read(TALLOC_CTX
*mem_ctx
,
292 const char lenbuf
[4],
293 struct smbd_server_connection
*sconn
,
296 unsigned int timeout
,
300 /* Size of a WRITEX call (+4 byte len). */
301 char writeX_header
[4 + STANDARD_WRITE_AND_X_HEADER_SIZE
];
302 ssize_t len
= smb_len_large(lenbuf
); /* Could be a UNIX large writeX. */
306 memcpy(writeX_header
, lenbuf
, 4);
308 status
= read_fd_with_timeout(
309 sock
, writeX_header
+ 4,
310 STANDARD_WRITE_AND_X_HEADER_SIZE
,
311 STANDARD_WRITE_AND_X_HEADER_SIZE
,
314 if (!NT_STATUS_IS_OK(status
)) {
315 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
317 tsocket_address_string(sconn
->remote_address
,
324 * Ok - now try and see if this is a possible
328 if (is_valid_writeX_buffer(sconn
, (uint8_t *)writeX_header
)) {
330 * If the data offset is beyond what
331 * we've read, drain the extra bytes.
333 uint16_t doff
= SVAL(writeX_header
,smb_vwv11
);
336 if (doff
> STANDARD_WRITE_AND_X_HEADER_SIZE
) {
337 size_t drain
= doff
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
338 if (drain_socket(sock
, drain
) != drain
) {
339 smb_panic("receive_smb_raw_talloc_partial_read:"
340 " failed to drain pending bytes");
343 doff
= STANDARD_WRITE_AND_X_HEADER_SIZE
;
346 /* Spoof down the length and null out the bcc. */
347 set_message_bcc(writeX_header
, 0);
348 newlen
= smb_len(writeX_header
);
350 /* Copy the header we've written. */
352 *buffer
= (char *)talloc_memdup(mem_ctx
,
354 sizeof(writeX_header
));
356 if (*buffer
== NULL
) {
357 DEBUG(0, ("Could not allocate inbuf of length %d\n",
358 (int)sizeof(writeX_header
)));
359 return NT_STATUS_NO_MEMORY
;
362 /* Work out the remaining bytes. */
363 *p_unread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
364 *len_ret
= newlen
+ 4;
368 if (!valid_packet_size(len
)) {
369 return NT_STATUS_INVALID_PARAMETER
;
373 * Not a valid writeX call. Just do the standard
377 *buffer
= talloc_array(mem_ctx
, char, len
+4);
379 if (*buffer
== NULL
) {
380 DEBUG(0, ("Could not allocate inbuf of length %d\n",
382 return NT_STATUS_NO_MEMORY
;
385 /* Copy in what we already read. */
388 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
);
389 toread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
392 status
= read_packet_remainder(
394 (*buffer
) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
,
397 if (!NT_STATUS_IS_OK(status
)) {
398 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
408 static NTSTATUS
receive_smb_raw_talloc(TALLOC_CTX
*mem_ctx
,
409 struct smbd_server_connection
*sconn
,
411 char **buffer
, unsigned int timeout
,
412 size_t *p_unread
, size_t *plen
)
416 int min_recv_size
= lp_min_receive_file_size();
421 status
= read_smb_length_return_keepalive(sock
, lenbuf
, timeout
,
423 if (!NT_STATUS_IS_OK(status
)) {
427 if (CVAL(lenbuf
,0) == 0 && min_recv_size
&&
428 (smb_len_large(lenbuf
) > /* Could be a UNIX large writeX. */
429 (min_recv_size
+ STANDARD_WRITE_AND_X_HEADER_SIZE
)) &&
430 !srv_is_signing_active(sconn
) &&
431 sconn
->smb1
.echo_handler
.trusted_fde
== NULL
) {
433 return receive_smb_raw_talloc_partial_read(
434 mem_ctx
, lenbuf
, sconn
, sock
, buffer
, timeout
,
438 if (!valid_packet_size(len
)) {
439 return NT_STATUS_INVALID_PARAMETER
;
443 * The +4 here can't wrap, we've checked the length above already.
446 *buffer
= talloc_array(mem_ctx
, char, len
+4);
448 if (*buffer
== NULL
) {
449 DEBUG(0, ("Could not allocate inbuf of length %d\n",
451 return NT_STATUS_NO_MEMORY
;
454 memcpy(*buffer
, lenbuf
, sizeof(lenbuf
));
456 status
= read_packet_remainder(sock
, (*buffer
)+4, timeout
, len
);
457 if (!NT_STATUS_IS_OK(status
)) {
465 static NTSTATUS
receive_smb_talloc(TALLOC_CTX
*mem_ctx
,
466 struct smbd_server_connection
*sconn
,
468 char **buffer
, unsigned int timeout
,
469 size_t *p_unread
, bool *p_encrypted
,
472 bool trusted_channel
)
477 *p_encrypted
= false;
479 status
= receive_smb_raw_talloc(mem_ctx
, sconn
, sock
, buffer
, timeout
,
481 if (!NT_STATUS_IS_OK(status
)) {
482 DEBUG(NT_STATUS_EQUAL(status
, NT_STATUS_END_OF_FILE
)?5:1,
483 ("receive_smb_raw_talloc failed for client %s "
484 "read error = %s.\n",
485 tsocket_address_string(sconn
->remote_address
,
487 nt_errstr(status
)) );
491 if (is_encrypted_packet(sconn
, (uint8_t *)*buffer
)) {
492 status
= srv_decrypt_buffer(sconn
, *buffer
);
493 if (!NT_STATUS_IS_OK(status
)) {
494 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
495 "incoming packet! Error %s\n",
496 nt_errstr(status
) ));
502 /* Check the incoming SMB signature. */
503 if (!srv_check_sign_mac(sconn
, *buffer
, seqnum
, trusted_channel
)) {
504 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
505 "incoming packet!\n"));
506 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
514 * Initialize a struct smb_request from an inbuf
517 static bool init_smb_request(struct smb_request
*req
,
518 struct smbd_server_connection
*sconn
,
520 size_t unread_bytes
, bool encrypted
,
523 struct smbXsrv_tcon
*tcon
;
526 size_t req_size
= smb_len(inbuf
) + 4;
528 /* Ensure we have at least smb_size bytes. */
529 if (req_size
< smb_size
) {
530 DEBUG(0,("init_smb_request: invalid request size %u\n",
531 (unsigned int)req_size
));
535 req
->request_time
= timeval_current();
536 now
= timeval_to_nttime(&req
->request_time
);
538 req
->cmd
= CVAL(inbuf
, smb_com
);
539 req
->flags2
= SVAL(inbuf
, smb_flg2
);
540 req
->smbpid
= SVAL(inbuf
, smb_pid
);
541 req
->mid
= (uint64_t)SVAL(inbuf
, smb_mid
);
542 req
->seqnum
= seqnum
;
543 req
->vuid
= SVAL(inbuf
, smb_uid
);
544 req
->tid
= SVAL(inbuf
, smb_tid
);
545 req
->wct
= CVAL(inbuf
, smb_wct
);
546 req
->vwv
= (const uint16_t *)(inbuf
+smb_vwv
);
547 req
->buflen
= smb_buflen(inbuf
);
548 req
->buf
= (const uint8_t *)smb_buf_const(inbuf
);
549 req
->unread_bytes
= unread_bytes
;
550 req
->encrypted
= encrypted
;
552 status
= smb1srv_tcon_lookup(sconn
->conn
, req
->tid
, now
, &tcon
);
553 if (NT_STATUS_IS_OK(status
)) {
554 req
->conn
= tcon
->compat
;
558 req
->chain_fsp
= NULL
;
560 req
->priv_paths
= NULL
;
562 smb_init_perfcount_data(&req
->pcd
);
564 /* Ensure we have at least wct words and 2 bytes of bcc. */
565 if (smb_size
+ req
->wct
*2 > req_size
) {
566 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
567 (unsigned int)req
->wct
,
568 (unsigned int)req_size
));
571 /* Ensure bcc is correct. */
572 if (((const uint8_t *)smb_buf_const(inbuf
)) + req
->buflen
> inbuf
+ req_size
) {
573 DEBUG(0,("init_smb_request: invalid bcc number %u "
574 "(wct = %u, size %u)\n",
575 (unsigned int)req
->buflen
,
576 (unsigned int)req
->wct
,
577 (unsigned int)req_size
));
585 static void process_smb(struct smbd_server_connection
*conn
,
586 uint8_t *inbuf
, size_t nread
, size_t unread_bytes
,
587 uint32_t seqnum
, bool encrypted
,
588 struct smb_perfcount_data
*deferred_pcd
);
590 static void smbd_deferred_open_timer(struct tevent_context
*ev
,
591 struct tevent_timer
*te
,
592 struct timeval _tval
,
595 struct pending_message_list
*msg
= talloc_get_type(private_data
,
596 struct pending_message_list
);
597 struct smbd_server_connection
*sconn
= msg
->sconn
;
598 TALLOC_CTX
*mem_ctx
= talloc_tos();
599 uint64_t mid
= (uint64_t)SVAL(msg
->buf
.data
,smb_mid
);
602 inbuf
= (uint8_t *)talloc_memdup(mem_ctx
, msg
->buf
.data
,
605 exit_server("smbd_deferred_open_timer: talloc failed\n");
609 /* We leave this message on the queue so the open code can
610 know this is a retry. */
611 DEBUG(5,("smbd_deferred_open_timer: trigger mid %llu.\n",
612 (unsigned long long)mid
));
614 /* Mark the message as processed so this is not
615 * re-processed in error. */
616 msg
->processed
= true;
618 process_smb(sconn
, inbuf
,
620 msg
->seqnum
, msg
->encrypted
, &msg
->pcd
);
622 /* If it's still there and was processed, remove it. */
623 msg
= get_deferred_open_message_smb(sconn
, mid
);
624 if (msg
&& msg
->processed
) {
625 remove_deferred_open_message_smb(sconn
, mid
);
629 /****************************************************************************
630 Function to push a message onto the tail of a linked list of smb messages ready
632 ****************************************************************************/
634 static bool push_queued_message(struct smb_request
*req
,
635 struct timeval request_time
,
636 struct timeval end_time
,
637 char *private_data
, size_t private_len
)
639 int msg_len
= smb_len(req
->inbuf
) + 4;
640 struct pending_message_list
*msg
;
642 msg
= talloc_zero(NULL
, struct pending_message_list
);
645 DEBUG(0,("push_message: malloc fail (1)\n"));
648 msg
->sconn
= req
->sconn
;
650 msg
->buf
= data_blob_talloc(msg
, req
->inbuf
, msg_len
);
651 if(msg
->buf
.data
== NULL
) {
652 DEBUG(0,("push_message: malloc fail (2)\n"));
657 msg
->request_time
= request_time
;
658 msg
->seqnum
= req
->seqnum
;
659 msg
->encrypted
= req
->encrypted
;
660 msg
->processed
= false;
661 SMB_PERFCOUNT_DEFER_OP(&req
->pcd
, &msg
->pcd
);
664 msg
->private_data
= data_blob_talloc(msg
, private_data
,
666 if (msg
->private_data
.data
== NULL
) {
667 DEBUG(0,("push_message: malloc fail (3)\n"));
674 msg
->te
= tevent_add_timer(msg
->sconn
->ev_ctx
,
677 smbd_deferred_open_timer
,
680 DEBUG(0,("push_message: event_add_timed failed\n"));
686 DLIST_ADD_END(req
->sconn
->deferred_open_queue
, msg
,
687 struct pending_message_list
*);
689 DEBUG(10,("push_message: pushed message length %u on "
690 "deferred_open_queue\n", (unsigned int)msg_len
));
695 /****************************************************************************
696 Function to delete a sharing violation open message by mid.
697 ****************************************************************************/
699 void remove_deferred_open_message_smb(struct smbd_server_connection
*sconn
,
702 struct pending_message_list
*pml
;
704 if (sconn
->using_smb2
) {
705 remove_deferred_open_message_smb2(sconn
, mid
);
709 for (pml
= sconn
->deferred_open_queue
; pml
; pml
= pml
->next
) {
710 if (mid
== (uint64_t)SVAL(pml
->buf
.data
,smb_mid
)) {
711 DEBUG(10,("remove_deferred_open_message_smb: "
712 "deleting mid %llu len %u\n",
713 (unsigned long long)mid
,
714 (unsigned int)pml
->buf
.length
));
715 DLIST_REMOVE(sconn
->deferred_open_queue
, pml
);
722 /****************************************************************************
723 Move a sharing violation open retry message to the front of the list and
724 schedule it for immediate processing.
725 ****************************************************************************/
727 bool schedule_deferred_open_message_smb(struct smbd_server_connection
*sconn
,
730 struct pending_message_list
*pml
;
733 if (sconn
->using_smb2
) {
734 return schedule_deferred_open_message_smb2(sconn
, mid
);
737 for (pml
= sconn
->deferred_open_queue
; pml
; pml
= pml
->next
) {
738 uint64_t msg_mid
= (uint64_t)SVAL(pml
->buf
.data
,smb_mid
);
740 DEBUG(10,("schedule_deferred_open_message_smb: [%d] "
743 (unsigned long long)msg_mid
));
745 if (mid
== msg_mid
) {
746 struct tevent_timer
*te
;
748 if (pml
->processed
) {
749 /* A processed message should not be
751 DEBUG(0,("schedule_deferred_open_message_smb: LOGIC ERROR "
752 "message mid %llu was already processed\n",
753 (unsigned long long)msg_mid
));
757 DEBUG(10,("schedule_deferred_open_message_smb: "
758 "scheduling mid %llu\n",
759 (unsigned long long)mid
));
761 te
= tevent_add_timer(pml
->sconn
->ev_ctx
,
764 smbd_deferred_open_timer
,
767 DEBUG(10,("schedule_deferred_open_message_smb: "
768 "event_add_timed() failed, "
769 "skipping mid %llu\n",
770 (unsigned long long)msg_mid
));
773 TALLOC_FREE(pml
->te
);
775 DLIST_PROMOTE(sconn
->deferred_open_queue
, pml
);
780 DEBUG(10,("schedule_deferred_open_message_smb: failed to "
781 "find message mid %llu\n",
782 (unsigned long long)mid
));
787 /****************************************************************************
788 Return true if this mid is on the deferred queue and was not yet processed.
789 ****************************************************************************/
791 bool open_was_deferred(struct smbd_server_connection
*sconn
, uint64_t mid
)
793 struct pending_message_list
*pml
;
795 if (sconn
->using_smb2
) {
796 return open_was_deferred_smb2(sconn
, mid
);
799 for (pml
= sconn
->deferred_open_queue
; pml
; pml
= pml
->next
) {
800 if (((uint64_t)SVAL(pml
->buf
.data
,smb_mid
)) == mid
&& !pml
->processed
) {
807 /****************************************************************************
808 Return the message queued by this mid.
809 ****************************************************************************/
811 static struct pending_message_list
*get_deferred_open_message_smb(
812 struct smbd_server_connection
*sconn
, uint64_t mid
)
814 struct pending_message_list
*pml
;
816 for (pml
= sconn
->deferred_open_queue
; pml
; pml
= pml
->next
) {
817 if (((uint64_t)SVAL(pml
->buf
.data
,smb_mid
)) == mid
) {
824 /****************************************************************************
825 Get the state data queued by this mid.
826 ****************************************************************************/
828 bool get_deferred_open_message_state(struct smb_request
*smbreq
,
829 struct timeval
*p_request_time
,
832 struct pending_message_list
*pml
;
834 if (smbreq
->sconn
->using_smb2
) {
835 return get_deferred_open_message_state_smb2(smbreq
->smb2req
,
840 pml
= get_deferred_open_message_smb(smbreq
->sconn
, smbreq
->mid
);
844 if (p_request_time
) {
845 *p_request_time
= pml
->request_time
;
848 *pp_state
= (void *)pml
->private_data
.data
;
853 /****************************************************************************
854 Function to push a deferred open smb message onto a linked list of local smb
855 messages ready for processing.
856 ****************************************************************************/
858 bool push_deferred_open_message_smb(struct smb_request
*req
,
859 struct timeval request_time
,
860 struct timeval timeout
,
862 char *private_data
, size_t priv_len
)
864 struct timeval end_time
;
867 return push_deferred_open_message_smb2(req
->smb2req
,
875 if (req
->unread_bytes
) {
876 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
877 "unread_bytes = %u\n",
878 (unsigned int)req
->unread_bytes
));
879 smb_panic("push_deferred_open_message_smb: "
880 "logic error unread_bytes != 0" );
883 end_time
= timeval_sum(&request_time
, &timeout
);
885 DEBUG(10,("push_deferred_open_message_smb: pushing message "
886 "len %u mid %llu timeout time [%u.%06u]\n",
887 (unsigned int) smb_len(req
->inbuf
)+4,
888 (unsigned long long)req
->mid
,
889 (unsigned int)end_time
.tv_sec
,
890 (unsigned int)end_time
.tv_usec
));
892 return push_queued_message(req
, request_time
, end_time
,
893 private_data
, priv_len
);
896 static void smbd_sig_term_handler(struct tevent_context
*ev
,
897 struct tevent_signal
*se
,
903 exit_server_cleanly("termination signal");
906 void smbd_setup_sig_term_handler(struct smbd_server_connection
*sconn
)
908 struct tevent_signal
*se
;
910 se
= tevent_add_signal(sconn
->ev_ctx
,
913 smbd_sig_term_handler
,
916 exit_server("failed to setup SIGTERM handler");
920 static void smbd_sig_hup_handler(struct tevent_context
*ev
,
921 struct tevent_signal
*se
,
927 struct smbd_server_connection
*sconn
=
928 talloc_get_type_abort(private_data
,
929 struct smbd_server_connection
);
931 change_to_root_user();
932 DEBUG(1,("Reloading services after SIGHUP\n"));
933 reload_services(sconn
, conn_snum_used
, false);
936 void smbd_setup_sig_hup_handler(struct smbd_server_connection
*sconn
)
938 struct tevent_signal
*se
;
940 se
= tevent_add_signal(sconn
->ev_ctx
,
943 smbd_sig_hup_handler
,
946 exit_server("failed to setup SIGHUP handler");
950 static void smbd_conf_updated(struct messaging_context
*msg
,
953 struct server_id server_id
,
956 struct smbd_server_connection
*sconn
=
957 talloc_get_type_abort(private_data
,
958 struct smbd_server_connection
);
960 DEBUG(10,("smbd_conf_updated: Got message saying smb.conf was "
961 "updated. Reloading.\n"));
962 change_to_root_user();
963 reload_services(sconn
, conn_snum_used
, false);
967 * Only allow 5 outstanding trans requests. We're allocating memory, so
971 NTSTATUS
allow_new_trans(struct trans_state
*list
, uint64_t mid
)
974 for (; list
!= NULL
; list
= list
->next
) {
976 if (list
->mid
== mid
) {
977 return NT_STATUS_INVALID_PARAMETER
;
983 return NT_STATUS_INSUFFICIENT_RESOURCES
;
990 These flags determine some of the permissions required to do an operation
992 Note that I don't set NEED_WRITE on some write operations because they
993 are used by some brain-dead clients when printing, and I don't want to
994 force write permissions on print services.
996 #define AS_USER (1<<0)
997 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
998 #define TIME_INIT (1<<2)
999 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
1000 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
1001 #define DO_CHDIR (1<<6)
1004 define a list of possible SMB messages and their corresponding
1005 functions. Any message that has a NULL function is unimplemented -
1006 please feel free to contribute implementations!
1008 static const struct smb_message_struct
{
1010 void (*fn
)(struct smb_request
*req
);
1012 } smb_messages
[256] = {
1014 /* 0x00 */ { "SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
1015 /* 0x01 */ { "SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
1016 /* 0x02 */ { "SMBopen",reply_open
,AS_USER
},
1017 /* 0x03 */ { "SMBcreate",reply_mknew
,AS_USER
},
1018 /* 0x04 */ { "SMBclose",reply_close
,AS_USER
| CAN_IPC
},
1019 /* 0x05 */ { "SMBflush",reply_flush
,AS_USER
},
1020 /* 0x06 */ { "SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
1021 /* 0x07 */ { "SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
1022 /* 0x08 */ { "SMBgetatr",reply_getatr
,AS_USER
},
1023 /* 0x09 */ { "SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
1024 /* 0x0a */ { "SMBread",reply_read
,AS_USER
},
1025 /* 0x0b */ { "SMBwrite",reply_write
,AS_USER
| CAN_IPC
},
1026 /* 0x0c */ { "SMBlock",reply_lock
,AS_USER
},
1027 /* 0x0d */ { "SMBunlock",reply_unlock
,AS_USER
},
1028 /* 0x0e */ { "SMBctemp",reply_ctemp
,AS_USER
},
1029 /* 0x0f */ { "SMBmknew",reply_mknew
,AS_USER
},
1030 /* 0x10 */ { "SMBcheckpath",reply_checkpath
,AS_USER
},
1031 /* 0x11 */ { "SMBexit",reply_exit
,DO_CHDIR
},
1032 /* 0x12 */ { "SMBlseek",reply_lseek
,AS_USER
},
1033 /* 0x13 */ { "SMBlockread",reply_lockread
,AS_USER
},
1034 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock
,AS_USER
},
1035 /* 0x15 */ { NULL
, NULL
, 0 },
1036 /* 0x16 */ { NULL
, NULL
, 0 },
1037 /* 0x17 */ { NULL
, NULL
, 0 },
1038 /* 0x18 */ { NULL
, NULL
, 0 },
1039 /* 0x19 */ { NULL
, NULL
, 0 },
1040 /* 0x1a */ { "SMBreadbraw",reply_readbraw
,AS_USER
},
1041 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx
,AS_USER
},
1042 /* 0x1c */ { "SMBreadBs",reply_readbs
,AS_USER
},
1043 /* 0x1d */ { "SMBwritebraw",reply_writebraw
,AS_USER
},
1044 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx
,AS_USER
},
1045 /* 0x1f */ { "SMBwriteBs",reply_writebs
,AS_USER
},
1046 /* 0x20 */ { "SMBwritec", NULL
,0},
1047 /* 0x21 */ { NULL
, NULL
, 0 },
1048 /* 0x22 */ { "SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
1049 /* 0x23 */ { "SMBgetattrE",reply_getattrE
,AS_USER
},
1050 /* 0x24 */ { "SMBlockingX",reply_lockingX
,AS_USER
},
1051 /* 0x25 */ { "SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
1052 /* 0x26 */ { "SMBtranss",reply_transs
,AS_USER
| CAN_IPC
},
1053 /* 0x27 */ { "SMBioctl",reply_ioctl
,0},
1054 /* 0x28 */ { "SMBioctls", NULL
,AS_USER
},
1055 /* 0x29 */ { "SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
1056 /* 0x2a */ { "SMBmove", NULL
,AS_USER
| NEED_WRITE
},
1057 /* 0x2b */ { "SMBecho",reply_echo
,0},
1058 /* 0x2c */ { "SMBwriteclose",reply_writeclose
,AS_USER
},
1059 /* 0x2d */ { "SMBopenX",reply_open_and_X
,AS_USER
| CAN_IPC
},
1060 /* 0x2e */ { "SMBreadX",reply_read_and_X
,AS_USER
| CAN_IPC
},
1061 /* 0x2f */ { "SMBwriteX",reply_write_and_X
,AS_USER
| CAN_IPC
},
1062 /* 0x30 */ { NULL
, NULL
, 0 },
1063 /* 0x31 */ { NULL
, NULL
, 0 },
1064 /* 0x32 */ { "SMBtrans2",reply_trans2
, AS_USER
| CAN_IPC
},
1065 /* 0x33 */ { "SMBtranss2",reply_transs2
, AS_USER
| CAN_IPC
},
1066 /* 0x34 */ { "SMBfindclose",reply_findclose
,AS_USER
},
1067 /* 0x35 */ { "SMBfindnclose",reply_findnclose
,AS_USER
},
1068 /* 0x36 */ { NULL
, NULL
, 0 },
1069 /* 0x37 */ { NULL
, NULL
, 0 },
1070 /* 0x38 */ { NULL
, NULL
, 0 },
1071 /* 0x39 */ { NULL
, NULL
, 0 },
1072 /* 0x3a */ { NULL
, NULL
, 0 },
1073 /* 0x3b */ { NULL
, NULL
, 0 },
1074 /* 0x3c */ { NULL
, NULL
, 0 },
1075 /* 0x3d */ { NULL
, NULL
, 0 },
1076 /* 0x3e */ { NULL
, NULL
, 0 },
1077 /* 0x3f */ { NULL
, NULL
, 0 },
1078 /* 0x40 */ { NULL
, NULL
, 0 },
1079 /* 0x41 */ { NULL
, NULL
, 0 },
1080 /* 0x42 */ { NULL
, NULL
, 0 },
1081 /* 0x43 */ { NULL
, NULL
, 0 },
1082 /* 0x44 */ { NULL
, NULL
, 0 },
1083 /* 0x45 */ { NULL
, NULL
, 0 },
1084 /* 0x46 */ { NULL
, NULL
, 0 },
1085 /* 0x47 */ { NULL
, NULL
, 0 },
1086 /* 0x48 */ { NULL
, NULL
, 0 },
1087 /* 0x49 */ { NULL
, NULL
, 0 },
1088 /* 0x4a */ { NULL
, NULL
, 0 },
1089 /* 0x4b */ { NULL
, NULL
, 0 },
1090 /* 0x4c */ { NULL
, NULL
, 0 },
1091 /* 0x4d */ { NULL
, NULL
, 0 },
1092 /* 0x4e */ { NULL
, NULL
, 0 },
1093 /* 0x4f */ { NULL
, NULL
, 0 },
1094 /* 0x50 */ { NULL
, NULL
, 0 },
1095 /* 0x51 */ { NULL
, NULL
, 0 },
1096 /* 0x52 */ { NULL
, NULL
, 0 },
1097 /* 0x53 */ { NULL
, NULL
, 0 },
1098 /* 0x54 */ { NULL
, NULL
, 0 },
1099 /* 0x55 */ { NULL
, NULL
, 0 },
1100 /* 0x56 */ { NULL
, NULL
, 0 },
1101 /* 0x57 */ { NULL
, NULL
, 0 },
1102 /* 0x58 */ { NULL
, NULL
, 0 },
1103 /* 0x59 */ { NULL
, NULL
, 0 },
1104 /* 0x5a */ { NULL
, NULL
, 0 },
1105 /* 0x5b */ { NULL
, NULL
, 0 },
1106 /* 0x5c */ { NULL
, NULL
, 0 },
1107 /* 0x5d */ { NULL
, NULL
, 0 },
1108 /* 0x5e */ { NULL
, NULL
, 0 },
1109 /* 0x5f */ { NULL
, NULL
, 0 },
1110 /* 0x60 */ { NULL
, NULL
, 0 },
1111 /* 0x61 */ { NULL
, NULL
, 0 },
1112 /* 0x62 */ { NULL
, NULL
, 0 },
1113 /* 0x63 */ { NULL
, NULL
, 0 },
1114 /* 0x64 */ { NULL
, NULL
, 0 },
1115 /* 0x65 */ { NULL
, NULL
, 0 },
1116 /* 0x66 */ { NULL
, NULL
, 0 },
1117 /* 0x67 */ { NULL
, NULL
, 0 },
1118 /* 0x68 */ { NULL
, NULL
, 0 },
1119 /* 0x69 */ { NULL
, NULL
, 0 },
1120 /* 0x6a */ { NULL
, NULL
, 0 },
1121 /* 0x6b */ { NULL
, NULL
, 0 },
1122 /* 0x6c */ { NULL
, NULL
, 0 },
1123 /* 0x6d */ { NULL
, NULL
, 0 },
1124 /* 0x6e */ { NULL
, NULL
, 0 },
1125 /* 0x6f */ { NULL
, NULL
, 0 },
1126 /* 0x70 */ { "SMBtcon",reply_tcon
,0},
1127 /* 0x71 */ { "SMBtdis",reply_tdis
,DO_CHDIR
},
1128 /* 0x72 */ { "SMBnegprot",reply_negprot
,0},
1129 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X
,0},
1130 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX
, 0}, /* ulogoff doesn't give a valid TID */
1131 /* 0x75 */ { "SMBtconX",reply_tcon_and_X
,0},
1132 /* 0x76 */ { NULL
, NULL
, 0 },
1133 /* 0x77 */ { NULL
, NULL
, 0 },
1134 /* 0x78 */ { NULL
, NULL
, 0 },
1135 /* 0x79 */ { NULL
, NULL
, 0 },
1136 /* 0x7a */ { NULL
, NULL
, 0 },
1137 /* 0x7b */ { NULL
, NULL
, 0 },
1138 /* 0x7c */ { NULL
, NULL
, 0 },
1139 /* 0x7d */ { NULL
, NULL
, 0 },
1140 /* 0x7e */ { NULL
, NULL
, 0 },
1141 /* 0x7f */ { NULL
, NULL
, 0 },
1142 /* 0x80 */ { "SMBdskattr",reply_dskattr
,AS_USER
},
1143 /* 0x81 */ { "SMBsearch",reply_search
,AS_USER
},
1144 /* 0x82 */ { "SMBffirst",reply_search
,AS_USER
},
1145 /* 0x83 */ { "SMBfunique",reply_search
,AS_USER
},
1146 /* 0x84 */ { "SMBfclose",reply_fclose
,AS_USER
},
1147 /* 0x85 */ { NULL
, NULL
, 0 },
1148 /* 0x86 */ { NULL
, NULL
, 0 },
1149 /* 0x87 */ { NULL
, NULL
, 0 },
1150 /* 0x88 */ { NULL
, NULL
, 0 },
1151 /* 0x89 */ { NULL
, NULL
, 0 },
1152 /* 0x8a */ { NULL
, NULL
, 0 },
1153 /* 0x8b */ { NULL
, NULL
, 0 },
1154 /* 0x8c */ { NULL
, NULL
, 0 },
1155 /* 0x8d */ { NULL
, NULL
, 0 },
1156 /* 0x8e */ { NULL
, NULL
, 0 },
1157 /* 0x8f */ { NULL
, NULL
, 0 },
1158 /* 0x90 */ { NULL
, NULL
, 0 },
1159 /* 0x91 */ { NULL
, NULL
, 0 },
1160 /* 0x92 */ { NULL
, NULL
, 0 },
1161 /* 0x93 */ { NULL
, NULL
, 0 },
1162 /* 0x94 */ { NULL
, NULL
, 0 },
1163 /* 0x95 */ { NULL
, NULL
, 0 },
1164 /* 0x96 */ { NULL
, NULL
, 0 },
1165 /* 0x97 */ { NULL
, NULL
, 0 },
1166 /* 0x98 */ { NULL
, NULL
, 0 },
1167 /* 0x99 */ { NULL
, NULL
, 0 },
1168 /* 0x9a */ { NULL
, NULL
, 0 },
1169 /* 0x9b */ { NULL
, NULL
, 0 },
1170 /* 0x9c */ { NULL
, NULL
, 0 },
1171 /* 0x9d */ { NULL
, NULL
, 0 },
1172 /* 0x9e */ { NULL
, NULL
, 0 },
1173 /* 0x9f */ { NULL
, NULL
, 0 },
1174 /* 0xa0 */ { "SMBnttrans",reply_nttrans
, AS_USER
| CAN_IPC
},
1175 /* 0xa1 */ { "SMBnttranss",reply_nttranss
, AS_USER
| CAN_IPC
},
1176 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X
, AS_USER
| CAN_IPC
},
1177 /* 0xa3 */ { NULL
, NULL
, 0 },
1178 /* 0xa4 */ { "SMBntcancel",reply_ntcancel
, 0 },
1179 /* 0xa5 */ { "SMBntrename",reply_ntrename
, AS_USER
| NEED_WRITE
},
1180 /* 0xa6 */ { NULL
, NULL
, 0 },
1181 /* 0xa7 */ { NULL
, NULL
, 0 },
1182 /* 0xa8 */ { NULL
, NULL
, 0 },
1183 /* 0xa9 */ { NULL
, NULL
, 0 },
1184 /* 0xaa */ { NULL
, NULL
, 0 },
1185 /* 0xab */ { NULL
, NULL
, 0 },
1186 /* 0xac */ { NULL
, NULL
, 0 },
1187 /* 0xad */ { NULL
, NULL
, 0 },
1188 /* 0xae */ { NULL
, NULL
, 0 },
1189 /* 0xaf */ { NULL
, NULL
, 0 },
1190 /* 0xb0 */ { NULL
, NULL
, 0 },
1191 /* 0xb1 */ { NULL
, NULL
, 0 },
1192 /* 0xb2 */ { NULL
, NULL
, 0 },
1193 /* 0xb3 */ { NULL
, NULL
, 0 },
1194 /* 0xb4 */ { NULL
, NULL
, 0 },
1195 /* 0xb5 */ { NULL
, NULL
, 0 },
1196 /* 0xb6 */ { NULL
, NULL
, 0 },
1197 /* 0xb7 */ { NULL
, NULL
, 0 },
1198 /* 0xb8 */ { NULL
, NULL
, 0 },
1199 /* 0xb9 */ { NULL
, NULL
, 0 },
1200 /* 0xba */ { NULL
, NULL
, 0 },
1201 /* 0xbb */ { NULL
, NULL
, 0 },
1202 /* 0xbc */ { NULL
, NULL
, 0 },
1203 /* 0xbd */ { NULL
, NULL
, 0 },
1204 /* 0xbe */ { NULL
, NULL
, 0 },
1205 /* 0xbf */ { NULL
, NULL
, 0 },
1206 /* 0xc0 */ { "SMBsplopen",reply_printopen
,AS_USER
},
1207 /* 0xc1 */ { "SMBsplwr",reply_printwrite
,AS_USER
},
1208 /* 0xc2 */ { "SMBsplclose",reply_printclose
,AS_USER
},
1209 /* 0xc3 */ { "SMBsplretq",reply_printqueue
,AS_USER
},
1210 /* 0xc4 */ { NULL
, NULL
, 0 },
1211 /* 0xc5 */ { NULL
, NULL
, 0 },
1212 /* 0xc6 */ { NULL
, NULL
, 0 },
1213 /* 0xc7 */ { NULL
, NULL
, 0 },
1214 /* 0xc8 */ { NULL
, NULL
, 0 },
1215 /* 0xc9 */ { NULL
, NULL
, 0 },
1216 /* 0xca */ { NULL
, NULL
, 0 },
1217 /* 0xcb */ { NULL
, NULL
, 0 },
1218 /* 0xcc */ { NULL
, NULL
, 0 },
1219 /* 0xcd */ { NULL
, NULL
, 0 },
1220 /* 0xce */ { NULL
, NULL
, 0 },
1221 /* 0xcf */ { NULL
, NULL
, 0 },
1222 /* 0xd0 */ { "SMBsends",reply_sends
,AS_GUEST
},
1223 /* 0xd1 */ { "SMBsendb", NULL
,AS_GUEST
},
1224 /* 0xd2 */ { "SMBfwdname", NULL
,AS_GUEST
},
1225 /* 0xd3 */ { "SMBcancelf", NULL
,AS_GUEST
},
1226 /* 0xd4 */ { "SMBgetmac", NULL
,AS_GUEST
},
1227 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt
,AS_GUEST
},
1228 /* 0xd6 */ { "SMBsendend",reply_sendend
,AS_GUEST
},
1229 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt
,AS_GUEST
},
1230 /* 0xd8 */ { NULL
, NULL
, 0 },
1231 /* 0xd9 */ { NULL
, NULL
, 0 },
1232 /* 0xda */ { NULL
, NULL
, 0 },
1233 /* 0xdb */ { NULL
, NULL
, 0 },
1234 /* 0xdc */ { NULL
, NULL
, 0 },
1235 /* 0xdd */ { NULL
, NULL
, 0 },
1236 /* 0xde */ { NULL
, NULL
, 0 },
1237 /* 0xdf */ { NULL
, NULL
, 0 },
1238 /* 0xe0 */ { NULL
, NULL
, 0 },
1239 /* 0xe1 */ { NULL
, NULL
, 0 },
1240 /* 0xe2 */ { NULL
, NULL
, 0 },
1241 /* 0xe3 */ { NULL
, NULL
, 0 },
1242 /* 0xe4 */ { NULL
, NULL
, 0 },
1243 /* 0xe5 */ { NULL
, NULL
, 0 },
1244 /* 0xe6 */ { NULL
, NULL
, 0 },
1245 /* 0xe7 */ { NULL
, NULL
, 0 },
1246 /* 0xe8 */ { NULL
, NULL
, 0 },
1247 /* 0xe9 */ { NULL
, NULL
, 0 },
1248 /* 0xea */ { NULL
, NULL
, 0 },
1249 /* 0xeb */ { NULL
, NULL
, 0 },
1250 /* 0xec */ { NULL
, NULL
, 0 },
1251 /* 0xed */ { NULL
, NULL
, 0 },
1252 /* 0xee */ { NULL
, NULL
, 0 },
1253 /* 0xef */ { NULL
, NULL
, 0 },
1254 /* 0xf0 */ { NULL
, NULL
, 0 },
1255 /* 0xf1 */ { NULL
, NULL
, 0 },
1256 /* 0xf2 */ { NULL
, NULL
, 0 },
1257 /* 0xf3 */ { NULL
, NULL
, 0 },
1258 /* 0xf4 */ { NULL
, NULL
, 0 },
1259 /* 0xf5 */ { NULL
, NULL
, 0 },
1260 /* 0xf6 */ { NULL
, NULL
, 0 },
1261 /* 0xf7 */ { NULL
, NULL
, 0 },
1262 /* 0xf8 */ { NULL
, NULL
, 0 },
1263 /* 0xf9 */ { NULL
, NULL
, 0 },
1264 /* 0xfa */ { NULL
, NULL
, 0 },
1265 /* 0xfb */ { NULL
, NULL
, 0 },
1266 /* 0xfc */ { NULL
, NULL
, 0 },
1267 /* 0xfd */ { NULL
, NULL
, 0 },
1268 /* 0xfe */ { NULL
, NULL
, 0 },
1269 /* 0xff */ { NULL
, NULL
, 0 }
1273 /*******************************************************************
1274 allocate and initialize a reply packet
1275 ********************************************************************/
1277 static bool create_outbuf(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
1278 const char *inbuf
, char **outbuf
, uint8_t num_words
,
1281 size_t smb_len
= MIN_SMB_SIZE
+ VWV(num_words
) + num_bytes
;
1284 * Protect against integer wrap.
1285 * The SMB layer reply can be up to 0xFFFFFF bytes.
1287 if ((num_bytes
> 0xffffff) || (smb_len
> 0xffffff)) {
1289 if (asprintf(&msg
, "num_bytes too large: %u",
1290 (unsigned)num_bytes
) == -1) {
1291 msg
= discard_const_p(char, "num_bytes too large");
1297 * Here we include the NBT header for now.
1299 *outbuf
= talloc_array(mem_ctx
, char,
1300 NBT_HDR_SIZE
+ smb_len
);
1301 if (*outbuf
== NULL
) {
1305 construct_reply_common(req
, inbuf
, *outbuf
);
1306 srv_set_message(*outbuf
, num_words
, num_bytes
, false);
1308 * Zero out the word area, the caller has to take care of the bcc area
1311 if (num_words
!= 0) {
1312 memset(*outbuf
+ (NBT_HDR_SIZE
+ HDR_VWV
), 0, VWV(num_words
));
1318 void reply_outbuf(struct smb_request
*req
, uint8 num_words
, uint32 num_bytes
)
1321 if (!create_outbuf(req
, req
, (const char *)req
->inbuf
, &outbuf
, num_words
,
1323 smb_panic("could not allocate output buffer\n");
1325 req
->outbuf
= (uint8_t *)outbuf
;
1329 /*******************************************************************
1330 Dump a packet to a file.
1331 ********************************************************************/
1333 static void smb_dump(const char *name
, int type
, const char *data
)
1338 if (DEBUGLEVEL
< 50) {
1342 len
= smb_len_tcp(data
)+4;
1343 for (i
=1;i
<100;i
++) {
1344 fname
= talloc_asprintf(talloc_tos(),
1348 type
? "req" : "resp");
1349 if (fname
== NULL
) {
1352 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644);
1353 if (fd
!= -1 || errno
!= EEXIST
) break;
1357 ssize_t ret
= write(fd
, data
, len
);
1359 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret
));
1361 DEBUG(0,("created %s len %lu\n", fname
, (unsigned long)len
));
1366 /****************************************************************************
1367 Prepare everything for calling the actual request function, and potentially
1368 call the request function via the "new" interface.
1370 Return False if the "legacy" function needs to be called, everything is
1373 Return True if we're done.
1375 I know this API sucks, but it is the one with the least code change I could
1377 ****************************************************************************/
1379 static connection_struct
*switch_message(uint8 type
, struct smb_request
*req
)
1382 uint64_t session_tag
;
1383 connection_struct
*conn
= NULL
;
1384 struct smbd_server_connection
*sconn
= req
->sconn
;
1385 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1386 struct smbXsrv_session
*session
= NULL
;
1391 if (smb_messages
[type
].fn
== NULL
) {
1392 DEBUG(0,("Unknown message type %d!\n",type
));
1393 smb_dump("Unknown", 1, (const char *)req
->inbuf
);
1394 reply_unknown_new(req
, type
);
1398 flags
= smb_messages
[type
].flags
;
1400 /* In share mode security we must ignore the vuid. */
1401 session_tag
= req
->vuid
;
1404 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type
),
1405 (int)getpid(), (unsigned long)conn
));
1407 smb_dump(smb_fn_name(type
), 1, (const char *)req
->inbuf
);
1409 /* Ensure this value is replaced in the incoming packet. */
1410 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_uid
,session_tag
);
1413 * Ensure the correct username is in current_user_info. This is a
1414 * really ugly bugfix for problems with multiple session_setup_and_X's
1415 * being done and allowing %U and %G substitutions to work correctly.
1416 * There is a reason this code is done here, don't move it unless you
1417 * know what you're doing... :-).
1422 * lookup an existing session
1424 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1425 * here, the main check is still in change_to_user()
1427 status
= smb1srv_session_lookup(sconn
->conn
,
1431 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1434 status
= NT_STATUS_OK
;
1437 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1438 (unsigned long long)session_tag
,
1439 (unsigned long long)req
->mid
));
1440 reply_nterror(req
, NT_STATUS_NETWORK_SESSION_EXPIRED
);
1445 if (session_tag
!= sconn
->conn
->last_session_id
) {
1446 struct user_struct
*vuser
= NULL
;
1448 sconn
->conn
->last_session_id
= session_tag
;
1450 vuser
= session
->compat
;
1453 set_current_user_info(
1454 vuser
->session_info
->unix_info
->sanitized_username
,
1455 vuser
->session_info
->unix_info
->unix_name
,
1456 vuser
->session_info
->info
->domain_name
);
1460 /* Does this call need to be run as the connected user? */
1461 if (flags
& AS_USER
) {
1463 /* Does this call need a valid tree connection? */
1466 * Amazingly, the error code depends on the command
1469 if (type
== SMBntcreateX
) {
1470 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1472 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
1477 if (!change_to_user(conn
,session_tag
)) {
1478 DEBUG(0, ("Error: Could not change to user. Removing "
1479 "deferred open, mid=%llu.\n",
1480 (unsigned long long)req
->mid
));
1481 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
1485 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1487 /* Does it need write permission? */
1488 if ((flags
& NEED_WRITE
) && !CAN_WRITE(conn
)) {
1489 reply_nterror(req
, NT_STATUS_MEDIA_WRITE_PROTECTED
);
1493 /* IPC services are limited */
1494 if (IS_IPC(conn
) && !(flags
& CAN_IPC
)) {
1495 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1499 /* This call needs to be run as root */
1500 change_to_root_user();
1503 /* load service specific parameters */
1505 if (req
->encrypted
) {
1506 conn
->encrypted_tid
= true;
1507 /* encrypted required from now on. */
1508 conn
->encrypt_level
= SMB_SIGNING_REQUIRED
;
1509 } else if (ENCRYPTION_REQUIRED(conn
)) {
1510 if (req
->cmd
!= SMBtrans2
&& req
->cmd
!= SMBtranss2
) {
1511 DEBUG(1,("service[%s] requires encryption"
1512 "%s ACCESS_DENIED. mid=%llu\n",
1513 lp_servicename(talloc_tos(), SNUM(conn
)),
1515 (unsigned long long)req
->mid
));
1516 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1521 if (!set_current_service(conn
,SVAL(req
->inbuf
,smb_flg
),
1522 (flags
& (AS_USER
|DO_CHDIR
)
1524 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1527 conn
->num_smb_operations
++;
1531 * Does this protocol need to be run as guest? (Only archane
1532 * messenger service requests have this...)
1534 if (flags
& AS_GUEST
) {
1538 if (!change_to_guest()) {
1539 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1543 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
1545 if (raddr
== NULL
) {
1546 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1551 * Haven't we checked this in smbd_process already???
1554 ok
= allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
1555 sconn
->remote_hostname
, raddr
);
1559 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1564 smb_messages
[type
].fn(req
);
1568 /****************************************************************************
1569 Construct a reply to the incoming packet.
1570 ****************************************************************************/
1572 static void construct_reply(struct smbd_server_connection
*sconn
,
1573 char *inbuf
, int size
, size_t unread_bytes
,
1574 uint32_t seqnum
, bool encrypted
,
1575 struct smb_perfcount_data
*deferred_pcd
)
1577 connection_struct
*conn
;
1578 struct smb_request
*req
;
1580 if (!(req
= talloc(talloc_tos(), struct smb_request
))) {
1581 smb_panic("could not allocate smb_request");
1584 if (!init_smb_request(req
, sconn
, (uint8
*)inbuf
, unread_bytes
,
1585 encrypted
, seqnum
)) {
1586 exit_server_cleanly("Invalid SMB request");
1589 req
->inbuf
= (uint8_t *)talloc_move(req
, &inbuf
);
1591 /* we popped this message off the queue - keep original perf data */
1593 req
->pcd
= *deferred_pcd
;
1595 SMB_PERFCOUNT_START(&req
->pcd
);
1596 SMB_PERFCOUNT_SET_OP(&req
->pcd
, req
->cmd
);
1597 SMB_PERFCOUNT_SET_MSGLEN_IN(&req
->pcd
, size
);
1600 conn
= switch_message(req
->cmd
, req
);
1602 if (req
->outbuf
== NULL
) {
1606 if (CVAL(req
->outbuf
,0) == 0) {
1607 show_msg((char *)req
->outbuf
);
1610 if (!srv_send_smb(req
->sconn
,
1611 (char *)req
->outbuf
,
1612 true, req
->seqnum
+1,
1613 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
1615 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1623 static void construct_reply_chain(struct smbd_server_connection
*sconn
,
1624 char *inbuf
, int size
, uint32_t seqnum
,
1626 struct smb_perfcount_data
*deferred_pcd
)
1628 struct smb_request
**reqs
= NULL
;
1629 struct smb_request
*req
;
1633 ok
= smb1_parse_chain(talloc_tos(), (uint8_t *)inbuf
, sconn
, encrypted
,
1634 seqnum
, &reqs
, &num_reqs
);
1636 char errbuf
[smb_size
];
1637 error_packet(errbuf
, 0, 0, NT_STATUS_INVALID_PARAMETER
,
1638 __LINE__
, __FILE__
);
1639 if (!srv_send_smb(sconn
, errbuf
, true, seqnum
, encrypted
,
1641 exit_server_cleanly("construct_reply_chain: "
1642 "srv_send_smb failed.");
1648 req
->inbuf
= (uint8_t *)talloc_move(reqs
, &inbuf
);
1650 req
->conn
= switch_message(req
->cmd
, req
);
1652 if (req
->outbuf
== NULL
) {
1654 * Request has suspended itself, will come
1659 smb_request_done(req
);
1663 * To be called from an async SMB handler that is potentially chained
1664 * when it is finished for shipping.
1667 void smb_request_done(struct smb_request
*req
)
1669 struct smb_request
**reqs
= NULL
;
1670 struct smb_request
*first_req
;
1671 size_t i
, num_reqs
, next_index
;
1674 if (req
->chain
== NULL
) {
1680 num_reqs
= talloc_array_length(reqs
);
1682 for (i
=0; i
<num_reqs
; i
++) {
1683 if (reqs
[i
] == req
) {
1687 if (i
== num_reqs
) {
1689 * Invalid chain, should not happen
1691 status
= NT_STATUS_INTERNAL_ERROR
;
1696 while ((next_index
< num_reqs
) && (IVAL(req
->outbuf
, smb_rcls
) == 0)) {
1697 struct smb_request
*next
= reqs
[next_index
];
1698 struct smbXsrv_tcon
*tcon
;
1699 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1701 next
->vuid
= SVAL(req
->outbuf
, smb_uid
);
1702 next
->tid
= SVAL(req
->outbuf
, smb_tid
);
1703 status
= smb1srv_tcon_lookup(req
->sconn
->conn
, req
->tid
,
1705 if (NT_STATUS_IS_OK(status
)) {
1706 req
->conn
= tcon
->compat
;
1710 next
->chain_fsp
= req
->chain_fsp
;
1711 next
->inbuf
= req
->inbuf
;
1714 req
->conn
= switch_message(req
->cmd
, req
);
1716 if (req
->outbuf
== NULL
) {
1718 * Request has suspended itself, will come
1726 first_req
= reqs
[0];
1728 for (i
=1; i
<next_index
; i
++) {
1731 ok
= smb_splice_chain(&first_req
->outbuf
, reqs
[i
]->outbuf
);
1733 status
= NT_STATUS_INTERNAL_ERROR
;
1738 SSVAL(first_req
->outbuf
, smb_uid
, SVAL(req
->outbuf
, smb_uid
));
1739 SSVAL(first_req
->outbuf
, smb_tid
, SVAL(req
->outbuf
, smb_tid
));
1742 * This scary statement intends to set the
1743 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1744 * to the value last_req->outbuf carries
1746 SSVAL(first_req
->outbuf
, smb_flg2
,
1747 (SVAL(first_req
->outbuf
, smb_flg2
) & ~FLAGS2_32_BIT_ERROR_CODES
)
1748 |(SVAL(req
->outbuf
, smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
));
1751 * Transfer the error codes from the subrequest to the main one
1753 SSVAL(first_req
->outbuf
, smb_rcls
, SVAL(req
->outbuf
, smb_rcls
));
1754 SSVAL(first_req
->outbuf
, smb_err
, SVAL(req
->outbuf
, smb_err
));
1757 first_req
->outbuf
, talloc_get_size(first_req
->outbuf
) - 4);
1760 if (!srv_send_smb(first_req
->sconn
,
1761 (char *)first_req
->outbuf
,
1762 true, first_req
->seqnum
+1,
1763 IS_CONN_ENCRYPTED(req
->conn
)||first_req
->encrypted
,
1765 exit_server_cleanly("construct_reply_chain: srv_send_smb "
1768 TALLOC_FREE(req
); /* non-chained case */
1769 TALLOC_FREE(reqs
); /* chained case */
1774 char errbuf
[smb_size
];
1775 error_packet(errbuf
, 0, 0, status
, __LINE__
, __FILE__
);
1776 if (!srv_send_smb(req
->sconn
, errbuf
, true,
1777 req
->seqnum
+1, req
->encrypted
,
1779 exit_server_cleanly("construct_reply_chain: "
1780 "srv_send_smb failed.");
1783 TALLOC_FREE(req
); /* non-chained case */
1784 TALLOC_FREE(reqs
); /* chained case */
1787 /****************************************************************************
1788 Process an smb from the client
1789 ****************************************************************************/
1790 static void process_smb(struct smbd_server_connection
*sconn
,
1791 uint8_t *inbuf
, size_t nread
, size_t unread_bytes
,
1792 uint32_t seqnum
, bool encrypted
,
1793 struct smb_perfcount_data
*deferred_pcd
)
1795 int msg_type
= CVAL(inbuf
,0);
1797 DO_PROFILE_INC(smb_count
);
1799 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type
,
1801 DEBUG(3, ("Transaction %d of length %d (%u toread)\n",
1802 sconn
->trans_num
, (int)nread
, (unsigned int)unread_bytes
));
1804 if (msg_type
!= NBSSmessage
) {
1806 * NetBIOS session request, keepalive, etc.
1808 reply_special(sconn
, (char *)inbuf
, nread
);
1812 if (sconn
->using_smb2
) {
1813 /* At this point we're not really using smb2,
1814 * we make the decision here.. */
1815 if (smbd_is_smb2_header(inbuf
, nread
)) {
1816 smbd_smb2_first_negprot(sconn
, inbuf
, nread
);
1818 } else if (nread
>= smb_size
&& valid_smb_header(sconn
, inbuf
)
1819 && CVAL(inbuf
, smb_com
) != 0x72) {
1820 /* This is a non-negprot SMB1 packet.
1821 Disable SMB2 from now on. */
1822 sconn
->using_smb2
= false;
1826 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1827 * so subtract 4 from it. */
1828 if ((nread
< (smb_size
- 4)) || !valid_smb_header(sconn
, inbuf
)) {
1829 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1832 /* special magic for immediate exit */
1834 (IVAL(inbuf
, 4) == 0x74697865) &&
1835 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1836 uint8_t exitcode
= CVAL(inbuf
, 8);
1837 DEBUG(1, ("Exiting immediately with code %d\n",
1842 exit_server_cleanly("Non-SMB packet");
1845 show_msg((char *)inbuf
);
1847 if ((unread_bytes
== 0) && smb1_is_chain(inbuf
)) {
1848 construct_reply_chain(sconn
, (char *)inbuf
, nread
,
1849 seqnum
, encrypted
, deferred_pcd
);
1851 construct_reply(sconn
, (char *)inbuf
, nread
, unread_bytes
,
1852 seqnum
, encrypted
, deferred_pcd
);
1858 sconn
->num_requests
++;
1860 /* The timeout_processing function isn't run nearly
1861 often enough to implement 'max log size' without
1862 overrunning the size of the file by many megabytes.
1863 This is especially true if we are running at debug
1864 level 10. Checking every 50 SMBs is a nice
1865 tradeoff of performance vs log file size overrun. */
1867 if ((sconn
->num_requests
% 50) == 0 &&
1868 need_to_check_log_size()) {
1869 change_to_root_user();
1874 /****************************************************************************
1875 Return a string containing the function name of a SMB command.
1876 ****************************************************************************/
1878 const char *smb_fn_name(int type
)
1880 const char *unknown_name
= "SMBunknown";
1882 if (smb_messages
[type
].name
== NULL
)
1883 return(unknown_name
);
1885 return(smb_messages
[type
].name
);
1888 /****************************************************************************
1889 Helper functions for contruct_reply.
1890 ****************************************************************************/
1892 void add_to_common_flags2(uint32 v
)
1897 void remove_from_common_flags2(uint32 v
)
1899 common_flags2
&= ~v
;
1902 static void construct_reply_common(struct smb_request
*req
, const char *inbuf
,
1905 uint16_t in_flags2
= SVAL(inbuf
,smb_flg2
);
1906 uint16_t out_flags2
= common_flags2
;
1908 out_flags2
|= in_flags2
& FLAGS2_UNICODE_STRINGS
;
1909 out_flags2
|= in_flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
;
1910 out_flags2
|= in_flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
;
1912 srv_set_message(outbuf
,0,0,false);
1914 SCVAL(outbuf
, smb_com
, req
->cmd
);
1915 SIVAL(outbuf
,smb_rcls
,0);
1916 SCVAL(outbuf
,smb_flg
, FLAG_REPLY
| (CVAL(inbuf
,smb_flg
) & FLAG_CASELESS_PATHNAMES
));
1917 SSVAL(outbuf
,smb_flg2
, out_flags2
);
1918 memset(outbuf
+smb_pidhigh
,'\0',(smb_tid
-smb_pidhigh
));
1919 memcpy(outbuf
+smb_ss_field
, inbuf
+smb_ss_field
, 8);
1921 SSVAL(outbuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
1922 SSVAL(outbuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
1923 SSVAL(outbuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
1924 SSVAL(outbuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
1927 void construct_reply_common_req(struct smb_request
*req
, char *outbuf
)
1929 construct_reply_common(req
, (const char *)req
->inbuf
, outbuf
);
1933 * @brief Find the smb_cmd offset of the last command pushed
1934 * @param[in] buf The buffer we're building up
1935 * @retval Where can we put our next andx cmd?
1937 * While chaining requests, the "next" request we're looking at needs to put
1938 * its SMB_Command before the data the previous request already built up added
1939 * to the chain. Find the offset to the place where we have to put our cmd.
1942 static bool find_andx_cmd_ofs(uint8_t *buf
, size_t *pofs
)
1947 cmd
= CVAL(buf
, smb_com
);
1949 if (!is_andx_req(cmd
)) {
1955 while (CVAL(buf
, ofs
) != 0xff) {
1957 if (!is_andx_req(CVAL(buf
, ofs
))) {
1962 * ofs is from start of smb header, so add the 4 length
1963 * bytes. The next cmd is right after the wct field.
1965 ofs
= SVAL(buf
, ofs
+2) + 4 + 1;
1967 if (ofs
+4 >= talloc_get_size(buf
)) {
1977 * @brief Do the smb chaining at a buffer level
1978 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1979 * @param[in] andx_buf Buffer to be appended
1982 static bool smb_splice_chain(uint8_t **poutbuf
, const uint8_t *andx_buf
)
1984 uint8_t smb_command
= CVAL(andx_buf
, smb_com
);
1985 uint8_t wct
= CVAL(andx_buf
, smb_wct
);
1986 const uint16_t *vwv
= (const uint16_t *)(andx_buf
+ smb_vwv
);
1987 uint32_t num_bytes
= smb_buflen(andx_buf
);
1988 const uint8_t *bytes
= (const uint8_t *)smb_buf_const(andx_buf
);
1991 size_t old_size
, new_size
;
1993 size_t chain_padding
= 0;
1994 size_t andx_cmd_ofs
;
1997 old_size
= talloc_get_size(*poutbuf
);
1999 if ((old_size
% 4) != 0) {
2001 * Align the wct field of subsequent requests to a 4-byte
2004 chain_padding
= 4 - (old_size
% 4);
2008 * After the old request comes the new wct field (1 byte), the vwv's
2009 * and the num_bytes field.
2012 new_size
= old_size
+ chain_padding
+ 1 + wct
* sizeof(uint16_t) + 2;
2013 new_size
+= num_bytes
;
2015 if ((smb_command
!= SMBwriteX
) && (new_size
> 0xffff)) {
2016 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
2017 (unsigned)new_size
));
2021 outbuf
= talloc_realloc(NULL
, *poutbuf
, uint8_t, new_size
);
2022 if (outbuf
== NULL
) {
2023 DEBUG(0, ("talloc failed\n"));
2028 if (!find_andx_cmd_ofs(outbuf
, &andx_cmd_ofs
)) {
2029 DEBUG(1, ("invalid command chain\n"));
2030 *poutbuf
= talloc_realloc(NULL
, *poutbuf
, uint8_t, old_size
);
2034 if (chain_padding
!= 0) {
2035 memset(outbuf
+ old_size
, 0, chain_padding
);
2036 old_size
+= chain_padding
;
2039 SCVAL(outbuf
, andx_cmd_ofs
, smb_command
);
2040 SSVAL(outbuf
, andx_cmd_ofs
+ 2, old_size
- 4);
2045 * Push the chained request:
2050 SCVAL(outbuf
, ofs
, wct
);
2057 memcpy(outbuf
+ ofs
, vwv
, sizeof(uint16_t) * wct
);
2062 * Read&X has an offset into its data buffer at
2063 * vwv[6]. reply_read_andx has no idea anymore that it's
2064 * running from within a chain, so we have to fix up the
2067 * Although it looks disgusting at this place, I want to keep
2068 * it here. The alternative would be to push knowledge about
2069 * the andx chain down into read&x again.
2072 if (smb_command
== SMBreadX
) {
2073 uint8_t *bytes_addr
;
2077 * Invalid read&x response
2082 bytes_addr
= outbuf
+ ofs
/* vwv start */
2083 + sizeof(uint16_t) * wct
/* vwv array */
2084 + sizeof(uint16_t); /* bcc */
2086 SSVAL(outbuf
+ ofs
, 6 * sizeof(uint16_t),
2087 bytes_addr
- outbuf
- 4);
2090 ofs
+= sizeof(uint16_t) * wct
;
2096 SSVAL(outbuf
, ofs
, num_bytes
);
2097 ofs
+= sizeof(uint16_t);
2103 memcpy(outbuf
+ ofs
, bytes
, num_bytes
);
2108 bool smb1_is_chain(const uint8_t *buf
)
2110 uint8_t cmd
, wct
, andx_cmd
;
2112 cmd
= CVAL(buf
, smb_com
);
2113 if (!is_andx_req(cmd
)) {
2116 wct
= CVAL(buf
, smb_wct
);
2120 andx_cmd
= CVAL(buf
, smb_vwv
);
2121 return (andx_cmd
!= 0xFF);
2124 bool smb1_walk_chain(const uint8_t *buf
,
2125 bool (*fn
)(uint8_t cmd
,
2126 uint8_t wct
, const uint16_t *vwv
,
2127 uint16_t num_bytes
, const uint8_t *bytes
,
2128 void *private_data
),
2131 size_t smblen
= smb_len(buf
);
2132 const char *smb_buf
= smb_base(buf
);
2133 uint8_t cmd
, chain_cmd
;
2135 const uint16_t *vwv
;
2137 const uint8_t *bytes
;
2139 cmd
= CVAL(buf
, smb_com
);
2140 wct
= CVAL(buf
, smb_wct
);
2141 vwv
= (const uint16_t *)(buf
+ smb_vwv
);
2142 num_bytes
= smb_buflen(buf
);
2143 bytes
= (const uint8_t *)smb_buf_const(buf
);
2145 if (!fn(cmd
, wct
, vwv
, num_bytes
, bytes
, private_data
)) {
2149 if (!is_andx_req(cmd
)) {
2156 chain_cmd
= CVAL(vwv
, 0);
2158 while (chain_cmd
!= 0xff) {
2159 uint32_t chain_offset
; /* uint32_t to avoid overflow */
2160 size_t length_needed
;
2161 ptrdiff_t vwv_offset
;
2163 chain_offset
= SVAL(vwv
+1, 0);
2166 * Check if the client tries to fool us. The chain
2167 * offset needs to point beyond the current request in
2168 * the chain, it needs to strictly grow. Otherwise we
2169 * might be tricked into an endless loop always
2170 * processing the same request over and over again. We
2171 * used to assume that vwv and the byte buffer array
2172 * in a chain are always attached, but OS/2 the
2173 * Write&X/Read&X chain puts the Read&X vwv array
2174 * right behind the Write&X vwv chain. The Write&X bcc
2175 * array is put behind the Read&X vwv array. So now we
2176 * check whether the chain offset points strictly
2177 * behind the previous vwv array. req->buf points
2178 * right after the vwv array of the previous
2180 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
2184 vwv_offset
= ((const char *)vwv
- smb_buf
);
2185 if (chain_offset
<= vwv_offset
) {
2190 * Next check: Make sure the chain offset does not
2191 * point beyond the overall smb request length.
2194 length_needed
= chain_offset
+1; /* wct */
2195 if (length_needed
> smblen
) {
2200 * Now comes the pointer magic. Goal here is to set up
2201 * vwv and buf correctly again. The chain offset (the
2202 * former vwv[1]) points at the new wct field.
2205 wct
= CVAL(smb_buf
, chain_offset
);
2207 if (is_andx_req(chain_cmd
) && (wct
< 2)) {
2212 * Next consistency check: Make the new vwv array fits
2213 * in the overall smb request.
2216 length_needed
+= (wct
+1)*sizeof(uint16_t); /* vwv+buflen */
2217 if (length_needed
> smblen
) {
2220 vwv
= (const uint16_t *)(smb_buf
+ chain_offset
+ 1);
2223 * Now grab the new byte buffer....
2226 num_bytes
= SVAL(vwv
+wct
, 0);
2229 * .. and check that it fits.
2232 length_needed
+= num_bytes
;
2233 if (length_needed
> smblen
) {
2236 bytes
= (const uint8_t *)(vwv
+wct
+1);
2238 if (!fn(chain_cmd
, wct
, vwv
, num_bytes
, bytes
, private_data
)) {
2242 if (!is_andx_req(chain_cmd
)) {
2245 chain_cmd
= CVAL(vwv
, 0);
2250 static bool smb1_chain_length_cb(uint8_t cmd
,
2251 uint8_t wct
, const uint16_t *vwv
,
2252 uint16_t num_bytes
, const uint8_t *bytes
,
2255 unsigned *count
= (unsigned *)private_data
;
2260 unsigned smb1_chain_length(const uint8_t *buf
)
2264 if (!smb1_walk_chain(buf
, smb1_chain_length_cb
, &count
)) {
2270 struct smb1_parse_chain_state
{
2271 TALLOC_CTX
*mem_ctx
;
2273 struct smbd_server_connection
*sconn
;
2277 struct smb_request
**reqs
;
2281 static bool smb1_parse_chain_cb(uint8_t cmd
,
2282 uint8_t wct
, const uint16_t *vwv
,
2283 uint16_t num_bytes
, const uint8_t *bytes
,
2286 struct smb1_parse_chain_state
*state
=
2287 (struct smb1_parse_chain_state
*)private_data
;
2288 struct smb_request
**reqs
;
2289 struct smb_request
*req
;
2292 reqs
= talloc_realloc(state
->mem_ctx
, state
->reqs
,
2293 struct smb_request
*, state
->num_reqs
+1);
2299 req
= talloc(reqs
, struct smb_request
);
2304 ok
= init_smb_request(req
, state
->sconn
, state
->buf
, 0,
2305 state
->encrypted
, state
->seqnum
);
2312 req
->buflen
= num_bytes
;
2315 reqs
[state
->num_reqs
] = req
;
2316 state
->num_reqs
+= 1;
2320 bool smb1_parse_chain(TALLOC_CTX
*mem_ctx
, const uint8_t *buf
,
2321 struct smbd_server_connection
*sconn
,
2322 bool encrypted
, uint32_t seqnum
,
2323 struct smb_request
***reqs
, unsigned *num_reqs
)
2325 struct smb1_parse_chain_state state
;
2328 state
.mem_ctx
= mem_ctx
;
2330 state
.sconn
= sconn
;
2331 state
.encrypted
= encrypted
;
2332 state
.seqnum
= seqnum
;
2336 if (!smb1_walk_chain(buf
, smb1_parse_chain_cb
, &state
)) {
2337 TALLOC_FREE(state
.reqs
);
2340 for (i
=0; i
<state
.num_reqs
; i
++) {
2341 state
.reqs
[i
]->chain
= state
.reqs
;
2344 *num_reqs
= state
.num_reqs
;
2348 /****************************************************************************
2349 Check if services need reloading.
2350 ****************************************************************************/
2352 static void check_reload(struct smbd_server_connection
*sconn
, time_t t
)
2355 if (last_smb_conf_reload_time
== 0) {
2356 last_smb_conf_reload_time
= t
;
2359 if (t
>= last_smb_conf_reload_time
+SMBD_RELOAD_CHECK
) {
2360 reload_services(sconn
, conn_snum_used
, true);
2361 last_smb_conf_reload_time
= t
;
2365 static bool fd_is_readable(int fd
)
2369 ret
= poll_one_fd(fd
, POLLIN
|POLLHUP
, 0, &revents
);
2371 return ((ret
> 0) && ((revents
& (POLLIN
|POLLHUP
|POLLERR
)) != 0));
2375 static void smbd_server_connection_write_handler(
2376 struct smbd_server_connection
*sconn
)
2378 /* TODO: make write nonblocking */
2381 static void smbd_server_connection_read_handler(
2382 struct smbd_server_connection
*sconn
, int fd
)
2384 uint8_t *inbuf
= NULL
;
2385 size_t inbuf_len
= 0;
2386 size_t unread_bytes
= 0;
2387 bool encrypted
= false;
2388 TALLOC_CTX
*mem_ctx
= talloc_tos();
2394 if (lp_async_smb_echo_handler()
2395 && fd_is_readable(sconn
->smb1
.echo_handler
.trusted_fd
)) {
2397 * This is the super-ugly hack to prefer the packets
2398 * forwarded by the echo handler over the ones by the
2401 fd
= sconn
->smb1
.echo_handler
.trusted_fd
;
2404 from_client
= (sconn
->sock
== fd
);
2407 smbd_lock_socket(sconn
);
2409 if (!fd_is_readable(fd
)) {
2410 DEBUG(10,("the echo listener was faster\n"));
2411 smbd_unlock_socket(sconn
);
2416 /* TODO: make this completely nonblocking */
2417 status
= receive_smb_talloc(mem_ctx
, sconn
, fd
,
2418 (char **)(void *)&inbuf
,
2422 &inbuf_len
, &seqnum
,
2423 !from_client
/* trusted channel */);
2426 smbd_unlock_socket(sconn
);
2429 if (NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
2432 if (NT_STATUS_IS_ERR(status
)) {
2433 exit_server_cleanly("failed to receive smb request");
2435 if (!NT_STATUS_IS_OK(status
)) {
2440 process_smb(sconn
, inbuf
, inbuf_len
, unread_bytes
,
2441 seqnum
, encrypted
, NULL
);
2444 static void smbd_server_connection_handler(struct tevent_context
*ev
,
2445 struct tevent_fd
*fde
,
2449 struct smbd_server_connection
*conn
= talloc_get_type(private_data
,
2450 struct smbd_server_connection
);
2452 if (!NT_STATUS_IS_OK(conn
->status
)) {
2454 * we're not supposed to do any io
2456 TEVENT_FD_NOT_READABLE(conn
->smb1
.fde
);
2457 TEVENT_FD_NOT_WRITEABLE(conn
->smb1
.fde
);
2461 if (flags
& TEVENT_FD_WRITE
) {
2462 smbd_server_connection_write_handler(conn
);
2465 if (flags
& TEVENT_FD_READ
) {
2466 smbd_server_connection_read_handler(conn
, conn
->sock
);
2471 static void smbd_server_echo_handler(struct tevent_context
*ev
,
2472 struct tevent_fd
*fde
,
2476 struct smbd_server_connection
*conn
= talloc_get_type(private_data
,
2477 struct smbd_server_connection
);
2479 if (!NT_STATUS_IS_OK(conn
->status
)) {
2481 * we're not supposed to do any io
2483 TEVENT_FD_NOT_READABLE(conn
->smb1
.echo_handler
.trusted_fde
);
2484 TEVENT_FD_NOT_WRITEABLE(conn
->smb1
.echo_handler
.trusted_fde
);
2488 if (flags
& TEVENT_FD_WRITE
) {
2489 smbd_server_connection_write_handler(conn
);
2492 if (flags
& TEVENT_FD_READ
) {
2493 smbd_server_connection_read_handler(
2494 conn
, conn
->smb1
.echo_handler
.trusted_fd
);
2499 #ifdef CLUSTER_SUPPORT
2501 struct smbd_release_ip_state
{
2502 struct smbd_server_connection
*sconn
;
2503 struct tevent_immediate
*im
;
2504 char addr
[INET6_ADDRSTRLEN
];
2507 static void smbd_release_ip_immediate(struct tevent_context
*ctx
,
2508 struct tevent_immediate
*im
,
2511 struct smbd_release_ip_state
*state
=
2512 talloc_get_type_abort(private_data
,
2513 struct smbd_release_ip_state
);
2515 if (!NT_STATUS_EQUAL(state
->sconn
->status
, NT_STATUS_ADDRESS_CLOSED
)) {
2517 * smbd_server_connection_terminate() already triggered ?
2522 smbd_server_connection_terminate(state
->sconn
, "CTDB_SRVID_RELEASE_IP");
2525 /****************************************************************************
2526 received when we should release a specific IP
2527 ****************************************************************************/
2528 static bool release_ip(const char *ip
, void *priv
)
2530 struct smbd_release_ip_state
*state
=
2531 talloc_get_type_abort(priv
,
2532 struct smbd_release_ip_state
);
2533 const char *addr
= state
->addr
;
2534 const char *p
= addr
;
2536 if (!NT_STATUS_IS_OK(state
->sconn
->status
)) {
2537 /* avoid recursion */
2541 if (strncmp("::ffff:", addr
, 7) == 0) {
2545 DEBUG(10, ("Got release IP message for %s, "
2546 "our address is %s\n", ip
, p
));
2548 if ((strcmp(p
, ip
) == 0) || ((p
!= addr
) && strcmp(addr
, ip
) == 0)) {
2549 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
2552 * With SMB2 we should do a clean disconnect,
2553 * the previous_session_id in the session setup
2554 * will cleanup the old session, tcons and opens.
2556 * A clean disconnect is needed in order to support
2559 * Note: typically this is never triggered
2560 * as we got a TCP RST (triggered by ctdb event scripts)
2561 * before we get CTDB_SRVID_RELEASE_IP.
2563 * We used to call _exit(1) here, but as this was mostly never
2564 * triggered and has implication on our process model,
2565 * we can just use smbd_server_connection_terminate()
2568 * We don't call smbd_server_connection_terminate() directly
2569 * as we might be called from within ctdbd_migrate(),
2570 * we need to defer our action to the next event loop
2572 tevent_schedule_immediate(state
->im
, state
->sconn
->ev_ctx
,
2573 smbd_release_ip_immediate
, state
);
2576 * Make sure we don't get any io on the connection.
2578 state
->sconn
->status
= NT_STATUS_ADDRESS_CLOSED
;
2585 static NTSTATUS
smbd_register_ips(struct smbd_server_connection
*sconn
,
2586 struct sockaddr_storage
*srv
,
2587 struct sockaddr_storage
*clnt
)
2589 struct smbd_release_ip_state
*state
;
2590 struct ctdbd_connection
*cconn
;
2592 cconn
= messaging_ctdbd_connection();
2593 if (cconn
== NULL
) {
2594 return NT_STATUS_NO_MEMORY
;
2597 state
= talloc_zero(sconn
, struct smbd_release_ip_state
);
2598 if (state
== NULL
) {
2599 return NT_STATUS_NO_MEMORY
;
2601 state
->sconn
= sconn
;
2602 state
->im
= tevent_create_immediate(state
);
2603 if (state
->im
== NULL
) {
2604 return NT_STATUS_NO_MEMORY
;
2606 if (print_sockaddr(state
->addr
, sizeof(state
->addr
), srv
) == NULL
) {
2607 return NT_STATUS_NO_MEMORY
;
2610 return ctdbd_register_ips(cconn
, srv
, clnt
, release_ip
, state
);
2613 static int client_get_tcp_info(int sock
, struct sockaddr_storage
*server
,
2614 struct sockaddr_storage
*client
)
2617 length
= sizeof(*server
);
2618 if (getsockname(sock
, (struct sockaddr
*)server
, &length
) != 0) {
2621 length
= sizeof(*client
);
2622 if (getpeername(sock
, (struct sockaddr
*)client
, &length
) != 0) {
2630 * Send keepalive packets to our client
2632 static bool keepalive_fn(const struct timeval
*now
, void *private_data
)
2634 struct smbd_server_connection
*sconn
= talloc_get_type_abort(
2635 private_data
, struct smbd_server_connection
);
2638 if (sconn
->using_smb2
) {
2639 /* Don't do keepalives on an SMB2 connection. */
2643 smbd_lock_socket(sconn
);
2644 ret
= send_keepalive(sconn
->sock
);
2645 smbd_unlock_socket(sconn
);
2648 char addr
[INET6_ADDRSTRLEN
];
2650 * Try and give an error message saying what
2653 DEBUG(0, ("send_keepalive failed for client %s. "
2654 "Error %s - exiting\n",
2655 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2663 * Do the recurring check if we're idle
2665 static bool deadtime_fn(const struct timeval
*now
, void *private_data
)
2667 struct smbd_server_connection
*sconn
=
2668 (struct smbd_server_connection
*)private_data
;
2670 if ((conn_num_open(sconn
) == 0)
2671 || (conn_idle_all(sconn
, now
->tv_sec
))) {
2672 DEBUG( 2, ( "Closing idle connection\n" ) );
2673 messaging_send(sconn
->msg_ctx
,
2674 messaging_server_id(sconn
->msg_ctx
),
2675 MSG_SHUTDOWN
, &data_blob_null
);
2683 * Do the recurring log file and smb.conf reload checks.
2686 static bool housekeeping_fn(const struct timeval
*now
, void *private_data
)
2688 struct smbd_server_connection
*sconn
= talloc_get_type_abort(
2689 private_data
, struct smbd_server_connection
);
2691 DEBUG(5, ("housekeeping\n"));
2693 change_to_root_user();
2695 /* update printer queue caches if necessary */
2696 update_monitored_printq_cache(sconn
->msg_ctx
);
2698 /* check if we need to reload services */
2699 check_reload(sconn
, time_mono(NULL
));
2702 * Force a log file check.
2704 force_check_log_size();
2710 * Read an smb packet in the echo handler child, giving the parent
2711 * smbd one second to react once the socket becomes readable.
2714 struct smbd_echo_read_state
{
2715 struct tevent_context
*ev
;
2716 struct smbd_server_connection
*sconn
;
2723 static void smbd_echo_read_readable(struct tevent_req
*subreq
);
2724 static void smbd_echo_read_waited(struct tevent_req
*subreq
);
2726 static struct tevent_req
*smbd_echo_read_send(
2727 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2728 struct smbd_server_connection
*sconn
)
2730 struct tevent_req
*req
, *subreq
;
2731 struct smbd_echo_read_state
*state
;
2733 req
= tevent_req_create(mem_ctx
, &state
,
2734 struct smbd_echo_read_state
);
2739 state
->sconn
= sconn
;
2741 subreq
= wait_for_read_send(state
, ev
, sconn
->sock
);
2742 if (tevent_req_nomem(subreq
, req
)) {
2743 return tevent_req_post(req
, ev
);
2745 tevent_req_set_callback(subreq
, smbd_echo_read_readable
, req
);
2749 static void smbd_echo_read_readable(struct tevent_req
*subreq
)
2751 struct tevent_req
*req
= tevent_req_callback_data(
2752 subreq
, struct tevent_req
);
2753 struct smbd_echo_read_state
*state
= tevent_req_data(
2754 req
, struct smbd_echo_read_state
);
2758 ok
= wait_for_read_recv(subreq
, &err
);
2759 TALLOC_FREE(subreq
);
2761 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
2766 * Give the parent smbd one second to step in
2769 subreq
= tevent_wakeup_send(
2770 state
, state
->ev
, timeval_current_ofs(1, 0));
2771 if (tevent_req_nomem(subreq
, req
)) {
2774 tevent_req_set_callback(subreq
, smbd_echo_read_waited
, req
);
2777 static void smbd_echo_read_waited(struct tevent_req
*subreq
)
2779 struct tevent_req
*req
= tevent_req_callback_data(
2780 subreq
, struct tevent_req
);
2781 struct smbd_echo_read_state
*state
= tevent_req_data(
2782 req
, struct smbd_echo_read_state
);
2783 struct smbd_server_connection
*sconn
= state
->sconn
;
2789 ok
= tevent_wakeup_recv(subreq
);
2790 TALLOC_FREE(subreq
);
2792 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2796 ok
= smbd_lock_socket_internal(sconn
);
2798 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2799 DEBUG(0, ("%s: failed to lock socket\n", __location__
));
2803 if (!fd_is_readable(sconn
->sock
)) {
2804 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2807 ok
= smbd_unlock_socket_internal(sconn
);
2809 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2810 DEBUG(1, ("%s: failed to unlock socket\n",
2815 subreq
= wait_for_read_send(state
, state
->ev
, sconn
->sock
);
2816 if (tevent_req_nomem(subreq
, req
)) {
2819 tevent_req_set_callback(subreq
, smbd_echo_read_readable
, req
);
2823 status
= receive_smb_talloc(state
, sconn
, sconn
->sock
, &state
->buf
,
2829 false /* trusted_channel*/);
2831 if (tevent_req_nterror(req
, status
)) {
2832 tevent_req_nterror(req
, status
);
2833 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2834 (int)getpid(), nt_errstr(status
)));
2838 ok
= smbd_unlock_socket_internal(sconn
);
2840 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
2841 DEBUG(1, ("%s: failed to unlock socket\n", __location__
));
2844 tevent_req_done(req
);
2847 static NTSTATUS
smbd_echo_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
2848 char **pbuf
, size_t *pbuflen
, uint32_t *pseqnum
)
2850 struct smbd_echo_read_state
*state
= tevent_req_data(
2851 req
, struct smbd_echo_read_state
);
2854 if (tevent_req_is_nterror(req
, &status
)) {
2857 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
2858 *pbuflen
= state
->buflen
;
2859 *pseqnum
= state
->seqnum
;
2860 return NT_STATUS_OK
;
2863 struct smbd_echo_state
{
2864 struct tevent_context
*ev
;
2865 struct iovec
*pending
;
2866 struct smbd_server_connection
*sconn
;
2869 struct tevent_fd
*parent_fde
;
2871 struct tevent_req
*write_req
;
2874 static void smbd_echo_writer_done(struct tevent_req
*req
);
2876 static void smbd_echo_activate_writer(struct smbd_echo_state
*state
)
2880 if (state
->write_req
!= NULL
) {
2884 num_pending
= talloc_array_length(state
->pending
);
2885 if (num_pending
== 0) {
2889 state
->write_req
= writev_send(state
, state
->ev
, NULL
,
2890 state
->parent_pipe
, false,
2891 state
->pending
, num_pending
);
2892 if (state
->write_req
== NULL
) {
2893 DEBUG(1, ("writev_send failed\n"));
2897 talloc_steal(state
->write_req
, state
->pending
);
2898 state
->pending
= NULL
;
2900 tevent_req_set_callback(state
->write_req
, smbd_echo_writer_done
,
2904 static void smbd_echo_writer_done(struct tevent_req
*req
)
2906 struct smbd_echo_state
*state
= tevent_req_callback_data(
2907 req
, struct smbd_echo_state
);
2911 written
= writev_recv(req
, &err
);
2913 state
->write_req
= NULL
;
2914 if (written
== -1) {
2915 DEBUG(1, ("writev to parent failed: %s\n", strerror(err
)));
2918 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2919 smbd_echo_activate_writer(state
);
2922 static bool smbd_echo_reply(struct smbd_echo_state
*state
,
2923 uint8_t *inbuf
, size_t inbuf_len
,
2926 struct smb_request req
;
2927 uint16_t num_replies
;
2931 if ((inbuf_len
== 4) && (CVAL(inbuf
, 0) == NBSSkeepalive
)) {
2932 DEBUG(10, ("Got netbios keepalive\n"));
2939 if (inbuf_len
< smb_size
) {
2940 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len
));
2943 if (!valid_smb_header(state
->sconn
, inbuf
)) {
2944 DEBUG(10, ("Got invalid SMB header\n"));
2948 if (!init_smb_request(&req
, state
->sconn
, inbuf
, 0, false,
2954 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req
.cmd
,
2955 smb_messages
[req
.cmd
].name
2956 ? smb_messages
[req
.cmd
].name
: "unknown"));
2958 if (req
.cmd
!= SMBecho
) {
2965 num_replies
= SVAL(req
.vwv
+0, 0);
2966 if (num_replies
!= 1) {
2967 /* Not a Windows "Hey, you're still there?" request */
2971 if (!create_outbuf(talloc_tos(), &req
, (const char *)req
.inbuf
, &outbuf
,
2973 DEBUG(10, ("create_outbuf failed\n"));
2976 req
.outbuf
= (uint8_t *)outbuf
;
2978 SSVAL(req
.outbuf
, smb_vwv0
, num_replies
);
2980 if (req
.buflen
> 0) {
2981 memcpy(smb_buf(req
.outbuf
), req
.buf
, req
.buflen
);
2984 ok
= srv_send_smb(req
.sconn
,
2988 TALLOC_FREE(outbuf
);
2996 static void smbd_echo_exit(struct tevent_context
*ev
,
2997 struct tevent_fd
*fde
, uint16_t flags
,
3000 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
3004 static void smbd_echo_got_packet(struct tevent_req
*req
);
3006 static void smbd_echo_loop(struct smbd_server_connection
*sconn
,
3009 struct smbd_echo_state
*state
;
3010 struct tevent_req
*read_req
;
3012 state
= talloc_zero(sconn
, struct smbd_echo_state
);
3013 if (state
== NULL
) {
3014 DEBUG(1, ("talloc failed\n"));
3017 state
->sconn
= sconn
;
3018 state
->parent_pipe
= parent_pipe
;
3019 state
->ev
= s3_tevent_context_init(state
);
3020 if (state
->ev
== NULL
) {
3021 DEBUG(1, ("tevent_context_init failed\n"));
3025 state
->parent_fde
= tevent_add_fd(state
->ev
, state
, parent_pipe
,
3026 TEVENT_FD_READ
, smbd_echo_exit
,
3028 if (state
->parent_fde
== NULL
) {
3029 DEBUG(1, ("tevent_add_fd failed\n"));
3034 read_req
= smbd_echo_read_send(state
, state
->ev
, sconn
);
3035 if (read_req
== NULL
) {
3036 DEBUG(1, ("smbd_echo_read_send failed\n"));
3040 tevent_req_set_callback(read_req
, smbd_echo_got_packet
, state
);
3043 if (tevent_loop_once(state
->ev
) == -1) {
3044 DEBUG(1, ("tevent_loop_once failed: %s\n",
3052 static void smbd_echo_got_packet(struct tevent_req
*req
)
3054 struct smbd_echo_state
*state
= tevent_req_callback_data(
3055 req
, struct smbd_echo_state
);
3059 uint32_t seqnum
= 0;
3062 status
= smbd_echo_read_recv(req
, state
, &buf
, &buflen
, &seqnum
);
3064 if (!NT_STATUS_IS_OK(status
)) {
3065 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
3066 nt_errstr(status
)));
3070 reply
= smbd_echo_reply(state
, (uint8_t *)buf
, buflen
, seqnum
);
3076 num_pending
= talloc_array_length(state
->pending
);
3077 tmp
= talloc_realloc(state
, state
->pending
, struct iovec
,
3080 DEBUG(1, ("talloc_realloc failed\n"));
3083 state
->pending
= tmp
;
3085 if (buflen
>= smb_size
) {
3087 * place the seqnum in the packet so that the main process
3088 * can reply with signing
3090 SIVAL(buf
, smb_ss_field
, seqnum
);
3091 SIVAL(buf
, smb_ss_field
+4, NT_STATUS_V(NT_STATUS_OK
));
3094 iov
= &state
->pending
[num_pending
];
3095 iov
->iov_base
= talloc_move(state
->pending
, &buf
);
3096 iov
->iov_len
= buflen
;
3098 DEBUG(10,("echo_handler[%d]: forward to main\n",
3100 smbd_echo_activate_writer(state
);
3103 req
= smbd_echo_read_send(state
, state
->ev
, state
->sconn
);
3105 DEBUG(1, ("smbd_echo_read_send failed\n"));
3108 tevent_req_set_callback(req
, smbd_echo_got_packet
, state
);
3113 * Handle SMBecho requests in a forked child process
3115 bool fork_echo_handler(struct smbd_server_connection
*sconn
)
3117 int listener_pipe
[2];
3121 res
= pipe(listener_pipe
);
3123 DEBUG(1, ("pipe() failed: %s\n", strerror(errno
)));
3126 sconn
->smb1
.echo_handler
.socket_lock_fd
= create_unlink_tmp(lp_lockdir());
3127 if (sconn
->smb1
.echo_handler
.socket_lock_fd
== -1) {
3128 DEBUG(1, ("Could not create lock fd: %s\n", strerror(errno
)));
3136 close(listener_pipe
[0]);
3137 set_blocking(listener_pipe
[1], false);
3139 status
= reinit_after_fork(sconn
->msg_ctx
,
3142 if (!NT_STATUS_IS_OK(status
)) {
3143 DEBUG(1, ("reinit_after_fork failed: %s\n",
3144 nt_errstr(status
)));
3147 smbd_echo_loop(sconn
, listener_pipe
[1]);
3150 close(listener_pipe
[1]);
3151 listener_pipe
[1] = -1;
3152 sconn
->smb1
.echo_handler
.trusted_fd
= listener_pipe
[0];
3154 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child
));
3157 * Without smb signing this is the same as the normal smbd
3158 * listener. This needs to change once signing comes in.
3160 sconn
->smb1
.echo_handler
.trusted_fde
= tevent_add_fd(sconn
->ev_ctx
,
3162 sconn
->smb1
.echo_handler
.trusted_fd
,
3164 smbd_server_echo_handler
,
3166 if (sconn
->smb1
.echo_handler
.trusted_fde
== NULL
) {
3167 DEBUG(1, ("event_add_fd failed\n"));
3174 if (listener_pipe
[0] != -1) {
3175 close(listener_pipe
[0]);
3177 if (listener_pipe
[1] != -1) {
3178 close(listener_pipe
[1]);
3180 sconn
->smb1
.echo_handler
.trusted_fd
= -1;
3181 if (sconn
->smb1
.echo_handler
.socket_lock_fd
!= -1) {
3182 close(sconn
->smb1
.echo_handler
.socket_lock_fd
);
3184 sconn
->smb1
.echo_handler
.trusted_fd
= -1;
3185 sconn
->smb1
.echo_handler
.socket_lock_fd
= -1;
3189 static bool uid_in_use(const struct user_struct
*user
, uid_t uid
)
3192 if (user
->session_info
&&
3193 (user
->session_info
->unix_token
->uid
== uid
)) {
3201 static bool gid_in_use(const struct user_struct
*user
, gid_t gid
)
3204 if (user
->session_info
!= NULL
) {
3206 struct security_unix_token
*utok
;
3208 utok
= user
->session_info
->unix_token
;
3209 if (utok
->gid
== gid
) {
3212 for(i
=0; i
<utok
->ngroups
; i
++) {
3213 if (utok
->groups
[i
] == gid
) {
3223 static bool sid_in_use(const struct user_struct
*user
,
3224 const struct dom_sid
*psid
)
3227 struct security_token
*tok
;
3229 if (user
->session_info
== NULL
) {
3232 tok
= user
->session_info
->security_token
;
3235 * Not sure session_info->security_token can
3236 * ever be NULL. This check might be not
3241 if (security_token_has_sid(tok
, psid
)) {
3249 static bool id_in_use(const struct user_struct
*user
,
3250 const struct id_cache_ref
*id
)
3254 return uid_in_use(user
, id
->id
.uid
);
3256 return gid_in_use(user
, id
->id
.gid
);
3258 return sid_in_use(user
, &id
->id
.sid
);
3265 static void smbd_id_cache_kill(struct messaging_context
*msg_ctx
,
3268 struct server_id server_id
,
3271 const char *msg
= (data
&& data
->data
)
3272 ? (const char *)data
->data
: "<NULL>";
3273 struct id_cache_ref id
;
3274 struct smbd_server_connection
*sconn
=
3275 talloc_get_type_abort(private_data
,
3276 struct smbd_server_connection
);
3278 if (!id_cache_ref_parse(msg
, &id
)) {
3279 DEBUG(0, ("Invalid ?ID: %s\n", msg
));
3283 if (id_in_use(sconn
->users
, &id
)) {
3284 exit_server_cleanly(msg
);
3286 id_cache_delete_from_cache(&id
);
3289 NTSTATUS
smbXsrv_connection_init_tables(struct smbXsrv_connection
*conn
,
3290 enum protocol_types protocol
)
3294 set_Protocol(protocol
);
3295 conn
->protocol
= protocol
;
3297 if (protocol
>= PROTOCOL_SMB2_02
) {
3298 status
= smb2srv_session_table_init(conn
);
3299 if (!NT_STATUS_IS_OK(status
)) {
3303 status
= smb2srv_open_table_init(conn
);
3304 if (!NT_STATUS_IS_OK(status
)) {
3308 status
= smb1srv_session_table_init(conn
);
3309 if (!NT_STATUS_IS_OK(status
)) {
3313 status
= smb1srv_tcon_table_init(conn
);
3314 if (!NT_STATUS_IS_OK(status
)) {
3318 status
= smb1srv_open_table_init(conn
);
3319 if (!NT_STATUS_IS_OK(status
)) {
3324 return NT_STATUS_OK
;
3327 static void smbd_tevent_trace_callback(enum tevent_trace_point point
,
3330 struct smbXsrv_connection
*conn
=
3331 talloc_get_type_abort(private_data
,
3332 struct smbXsrv_connection
);
3335 case TEVENT_TRACE_BEFORE_WAIT
:
3337 * This just removes compiler warning
3338 * without profile support
3340 conn
->smbd_idle_profstamp
= 0;
3341 START_PROFILE_STAMP(smbd_idle
, conn
->smbd_idle_profstamp
);
3343 case TEVENT_TRACE_AFTER_WAIT
:
3344 END_PROFILE_STAMP(smbd_idle
, conn
->smbd_idle_profstamp
);
3349 /****************************************************************************
3350 Process commands from the client
3351 ****************************************************************************/
3353 void smbd_process(struct tevent_context
*ev_ctx
,
3354 struct messaging_context
*msg_ctx
,
3358 TALLOC_CTX
*frame
= talloc_stackframe();
3359 struct smbXsrv_connection
*conn
;
3360 struct smbd_server_connection
*sconn
;
3361 struct sockaddr_storage ss
;
3362 struct sockaddr
*sa
= NULL
;
3363 socklen_t sa_socklen
;
3364 struct tsocket_address
*local_address
= NULL
;
3365 struct tsocket_address
*remote_address
= NULL
;
3366 const char *locaddr
= NULL
;
3367 const char *remaddr
= NULL
;
3372 conn
= talloc_zero(ev_ctx
, struct smbXsrv_connection
);
3374 DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
3375 exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n");
3378 conn
->ev_ctx
= ev_ctx
;
3379 conn
->msg_ctx
= msg_ctx
;
3381 sconn
= talloc_zero(conn
, struct smbd_server_connection
);
3383 exit_server("failed to create smbd_server_connection");
3386 conn
->sconn
= sconn
;
3390 * TODO: remove this...:-)
3392 global_smbXsrv_connection
= conn
;
3394 sconn
->ev_ctx
= ev_ctx
;
3395 sconn
->msg_ctx
= msg_ctx
;
3396 sconn
->sock
= sock_fd
;
3397 sconn
->smb1
.echo_handler
.trusted_fd
= -1;
3398 sconn
->smb1
.echo_handler
.socket_lock_fd
= -1;
3401 smbd_setup_sig_term_handler(sconn
);
3402 smbd_setup_sig_hup_handler(sconn
);
3404 if (!serverid_register(messaging_server_id(msg_ctx
),
3405 FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
3407 |FLAG_MSG_PRINT_GENERAL
)) {
3408 exit_server_cleanly("Could not register myself in "
3413 if (lp_srv_maxprotocol() >= PROTOCOL_SMB2_02
) {
3415 * We're not making the decision here,
3416 * we're just allowing the client
3417 * to decide between SMB1 and SMB2
3418 * with the first negprot
3421 sconn
->using_smb2
= true;
3424 /* Ensure child is set to blocking mode */
3425 set_blocking(sconn
->sock
,True
);
3427 set_socket_options(sconn
->sock
, "SO_KEEPALIVE");
3428 set_socket_options(sconn
->sock
, lp_socket_options());
3430 sa
= (struct sockaddr
*)(void *)&ss
;
3431 sa_socklen
= sizeof(ss
);
3432 ret
= getpeername(sconn
->sock
, sa
, &sa_socklen
);
3434 int level
= (errno
== ENOTCONN
)?2:0;
3435 DEBUG(level
,("getpeername() failed - %s\n", strerror(errno
)));
3436 exit_server_cleanly("getpeername() failed.\n");
3438 ret
= tsocket_address_bsd_from_sockaddr(sconn
,
3442 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
3443 __location__
, strerror(errno
)));
3444 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
3447 sa
= (struct sockaddr
*)(void *)&ss
;
3448 sa_socklen
= sizeof(ss
);
3449 ret
= getsockname(sconn
->sock
, sa
, &sa_socklen
);
3451 int level
= (errno
== ENOTCONN
)?2:0;
3452 DEBUG(level
,("getsockname() failed - %s\n", strerror(errno
)));
3453 exit_server_cleanly("getsockname() failed.\n");
3455 ret
= tsocket_address_bsd_from_sockaddr(sconn
,
3459 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
3460 __location__
, strerror(errno
)));
3461 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
3464 sconn
->local_address
= local_address
;
3465 sconn
->remote_address
= remote_address
;
3467 if (tsocket_address_is_inet(local_address
, "ip")) {
3468 locaddr
= tsocket_address_inet_addr_string(
3469 sconn
->local_address
,
3471 if (locaddr
== NULL
) {
3472 DEBUG(0,("%s: tsocket_address_inet_addr_string local failed - %s\n",
3473 __location__
, strerror(errno
)));
3474 exit_server_cleanly("tsocket_address_inet_addr_string local failed.\n");
3477 locaddr
= "0.0.0.0";
3480 if (tsocket_address_is_inet(remote_address
, "ip")) {
3481 remaddr
= tsocket_address_inet_addr_string(
3482 sconn
->remote_address
,
3484 if (remaddr
== NULL
) {
3485 DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
3486 __location__
, strerror(errno
)));
3487 exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
3490 remaddr
= "0.0.0.0";
3493 /* this is needed so that we get decent entries
3494 in smbstatus for port 445 connects */
3495 set_remote_machine_name(remaddr
, false);
3496 reload_services(sconn
, conn_snum_used
, true);
3499 * Before the first packet, check the global hosts allow/ hosts deny
3500 * parameters before doing any parsing of packets passed to us by the
3501 * client. This prevents attacks on our parsing code from hosts not in
3502 * the hosts allow list.
3505 ret
= get_remote_hostname(remote_address
,
3509 DEBUG(0,("%s: get_remote_hostname failed - %s\n",
3510 __location__
, strerror(errno
)));
3511 exit_server_cleanly("get_remote_hostname failed.\n");
3513 if (strequal(rhost
, "UNKNOWN")) {
3514 rhost
= talloc_strdup(talloc_tos(), remaddr
);
3516 sconn
->remote_hostname
= talloc_move(sconn
, &rhost
);
3518 sub_set_socket_ids(remaddr
,
3519 sconn
->remote_hostname
,
3522 if (!allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
3523 sconn
->remote_hostname
,
3526 * send a negative session response "not listening on calling
3529 unsigned char buf
[5] = {0x83, 0, 0, 1, 0x81};
3530 DEBUG( 1, ("Connection denied from %s to %s\n",
3531 tsocket_address_string(remote_address
, talloc_tos()),
3532 tsocket_address_string(local_address
, talloc_tos())));
3533 (void)srv_send_smb(sconn
,(char *)buf
, false,
3535 exit_server_cleanly("connection denied");
3538 DEBUG(10, ("Connection allowed from %s to %s\n",
3539 tsocket_address_string(remote_address
, talloc_tos()),
3540 tsocket_address_string(local_address
, talloc_tos())));
3542 if (lp_preload_modules()) {
3543 smb_load_modules(lp_preload_modules());
3546 smb_perfcount_init();
3548 if (!init_account_policy()) {
3549 exit_server("Could not open account policy tdb.\n");
3552 if (*lp_rootdir(talloc_tos())) {
3553 if (chroot(lp_rootdir(talloc_tos())) != 0) {
3554 DEBUG(0,("Failed to change root to %s\n",
3555 lp_rootdir(talloc_tos())));
3556 exit_server("Failed to chroot()");
3558 if (chdir("/") == -1) {
3559 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir(talloc_tos())));
3560 exit_server("Failed to chroot()");
3562 DEBUG(0,("Changed root to %s\n", lp_rootdir(talloc_tos())));
3565 if (!srv_init_signing(sconn
)) {
3566 exit_server("Failed to init smb_signing");
3569 if (!file_init(sconn
)) {
3570 exit_server("file_init() failed");
3574 if (!init_oplocks(sconn
))
3575 exit_server("Failed to init oplocks");
3577 /* register our message handlers */
3578 messaging_register(sconn
->msg_ctx
, sconn
,
3579 MSG_SMB_FORCE_TDIS
, msg_force_tdis
);
3580 messaging_register(sconn
->msg_ctx
, sconn
,
3581 MSG_SMB_CLOSE_FILE
, msg_close_file
);
3582 messaging_register(sconn
->msg_ctx
, sconn
,
3583 MSG_SMB_FILE_RENAME
, msg_file_was_renamed
);
3585 id_cache_register_msgs(sconn
->msg_ctx
);
3586 messaging_deregister(sconn
->msg_ctx
, ID_CACHE_KILL
, NULL
);
3587 messaging_register(sconn
->msg_ctx
, sconn
,
3588 ID_CACHE_KILL
, smbd_id_cache_kill
);
3590 messaging_deregister(sconn
->msg_ctx
,
3591 MSG_SMB_CONF_UPDATED
, sconn
->ev_ctx
);
3592 messaging_register(sconn
->msg_ctx
, sconn
,
3593 MSG_SMB_CONF_UPDATED
, smbd_conf_updated
);
3596 * Use the default MSG_DEBUG handler to avoid rebroadcasting
3597 * MSGs to all child processes
3599 messaging_deregister(sconn
->msg_ctx
,
3601 messaging_register(sconn
->msg_ctx
, NULL
,
3602 MSG_DEBUG
, debug_message
);
3604 if ((lp_keepalive() != 0)
3605 && !(event_add_idle(ev_ctx
, NULL
,
3606 timeval_set(lp_keepalive(), 0),
3607 "keepalive", keepalive_fn
,
3609 DEBUG(0, ("Could not add keepalive event\n"));
3613 if (!(event_add_idle(ev_ctx
, NULL
,
3614 timeval_set(IDLE_CLOSED_TIMEOUT
, 0),
3615 "deadtime", deadtime_fn
, sconn
))) {
3616 DEBUG(0, ("Could not add deadtime event\n"));
3620 if (!(event_add_idle(ev_ctx
, NULL
,
3621 timeval_set(SMBD_HOUSEKEEPING_INTERVAL
, 0),
3622 "housekeeping", housekeeping_fn
, sconn
))) {
3623 DEBUG(0, ("Could not add housekeeping event\n"));
3627 #ifdef CLUSTER_SUPPORT
3629 if (lp_clustering()) {
3631 * We need to tell ctdb about our client's TCP
3632 * connection, so that for failover ctdbd can send
3633 * tickle acks, triggering a reconnection by the
3637 struct sockaddr_storage srv
, clnt
;
3639 if (client_get_tcp_info(sconn
->sock
, &srv
, &clnt
) == 0) {
3641 status
= smbd_register_ips(sconn
, &srv
, &clnt
);
3642 if (!NT_STATUS_IS_OK(status
)) {
3643 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
3644 nt_errstr(status
)));
3647 int level
= (errno
== ENOTCONN
)?2:0;
3648 DEBUG(level
,("Unable to get tcp info for "
3649 "smbd_register_ips: %s\n",
3651 exit_server_cleanly("client_get_tcp_info() failed.\n");
3657 sconn
->nbt
.got_session
= false;
3659 tmp
= lp_max_xmit();
3660 tmp
= MAX(tmp
, SMB_BUFFER_SIZE_MIN
);
3661 tmp
= MIN(tmp
, SMB_BUFFER_SIZE_MAX
);
3663 sconn
->smb1
.negprot
.max_recv
= tmp
;
3665 sconn
->smb1
.sessions
.done_sesssetup
= false;
3666 sconn
->smb1
.sessions
.max_send
= SMB_BUFFER_SIZE_MAX
;
3668 if (!init_dptrs(sconn
)) {
3669 exit_server("init_dptrs() failed");
3672 sconn
->smb1
.fde
= tevent_add_fd(ev_ctx
,
3676 smbd_server_connection_handler
,
3678 if (!sconn
->smb1
.fde
) {
3679 exit_server("failed to create smbd_server_connection fde");
3682 sconn
->conn
->local_address
= sconn
->local_address
;
3683 sconn
->conn
->remote_address
= sconn
->remote_address
;
3684 sconn
->conn
->remote_hostname
= sconn
->remote_hostname
;
3685 sconn
->conn
->protocol
= PROTOCOL_NONE
;
3689 tevent_set_trace_callback(ev_ctx
, smbd_tevent_trace_callback
, conn
);
3692 frame
= talloc_stackframe_pool(8192);
3695 if (tevent_loop_once(ev_ctx
) == -1) {
3696 if (errno
!= EINTR
) {
3697 DEBUG(3, ("tevent_loop_once failed: %s,"
3698 " exiting\n", strerror(errno
) ));
3706 exit_server_cleanly(NULL
);
3709 bool req_is_in_chain(const struct smb_request
*req
)
3711 if (req
->vwv
!= (const uint16_t *)(req
->inbuf
+smb_vwv
)) {
3713 * We're right now handling a subsequent request, so we must
3719 if (!is_andx_req(req
->cmd
)) {
3725 * Okay, an illegal request, but definitely not chained :-)
3730 return (CVAL(req
->vwv
+0, 0) != 0xFF);