2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "smbd/globals.h"
23 #include "../librpc/gen_ndr/srv_dfs.h"
24 #include "../librpc/gen_ndr/srv_dssetup.h"
25 #include "../librpc/gen_ndr/srv_echo.h"
26 #include "../librpc/gen_ndr/srv_eventlog.h"
27 #include "../librpc/gen_ndr/srv_initshutdown.h"
28 #include "../librpc/gen_ndr/srv_lsa.h"
29 #include "../librpc/gen_ndr/srv_netlogon.h"
30 #include "../librpc/gen_ndr/srv_ntsvcs.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/srv_srvsvc.h"
34 #include "../librpc/gen_ndr/srv_svcctl.h"
35 #include "../librpc/gen_ndr/srv_winreg.h"
36 #include "../librpc/gen_ndr/srv_wkssvc.h"
38 extern bool global_machine_password_needs_changing
;
40 static void construct_reply_common(struct smb_request
*req
, const char *inbuf
,
43 bool smbd_lock_socket(struct smbd_server_connection
*sconn
)
48 bool smbd_unlock_socket(struct smbd_server_connection
*sconn
)
53 /* Accessor function for smb_read_error for smbd functions. */
55 /****************************************************************************
57 ****************************************************************************/
59 bool srv_send_smb(int fd
, char *buffer
,
60 bool do_signing
, uint32_t seqnum
,
62 struct smb_perfcount_data
*pcd
)
67 char *buf_out
= buffer
;
70 ok
= smbd_lock_socket(smbd_server_conn
);
72 exit_server_cleanly("failed to lock socket");
76 /* Sign the outgoing packet if required. */
77 srv_calculate_sign_mac(smbd_server_conn
, buf_out
, seqnum
);
81 NTSTATUS status
= srv_encrypt_buffer(buffer
, &buf_out
);
82 if (!NT_STATUS_IS_OK(status
)) {
83 DEBUG(0, ("send_smb: SMB encryption failed "
84 "on outgoing packet! Error %s\n",
90 len
= smb_len(buf_out
) + 4;
92 ret
= write_data(fd
,buf_out
+nwritten
,len
- nwritten
);
94 DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
95 (int)len
,(int)ret
, strerror(errno
) ));
96 srv_free_enc_buffer(buf_out
);
100 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd
, len
);
101 srv_free_enc_buffer(buf_out
);
103 SMB_PERFCOUNT_END(pcd
);
105 ok
= smbd_unlock_socket(smbd_server_conn
);
107 exit_server_cleanly("failed to unlock socket");
113 /*******************************************************************
114 Setup the word count and byte count for a smb message.
115 ********************************************************************/
117 int srv_set_message(char *buf
,
122 if (zero
&& (num_words
|| num_bytes
)) {
123 memset(buf
+ smb_size
,'\0',num_words
*2 + num_bytes
);
125 SCVAL(buf
,smb_wct
,num_words
);
126 SSVAL(buf
,smb_vwv
+ num_words
*SIZEOFWORD
,num_bytes
);
127 smb_setlen(buf
,(smb_size
+ num_words
*2 + num_bytes
- 4));
128 return (smb_size
+ num_words
*2 + num_bytes
);
131 static bool valid_smb_header(const uint8_t *inbuf
)
133 if (is_encrypted_packet(inbuf
)) {
137 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
138 * but it just looks weird to call strncmp for this one.
140 return (IVAL(smb_base(inbuf
), 0) == 0x424D53FF);
143 /* Socket functions for smbd packet processing. */
145 static bool valid_packet_size(size_t len
)
148 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
149 * of header. Don't print the error if this fits.... JRA.
152 if (len
> (BUFFER_SIZE
+ LARGE_WRITEX_HDR_SIZE
)) {
153 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
154 (unsigned long)len
));
160 static NTSTATUS
read_packet_remainder(int fd
, char *buffer
,
161 unsigned int timeout
, ssize_t len
)
167 return read_fd_with_timeout(fd
, buffer
, len
, len
, timeout
, NULL
);
170 /****************************************************************************
171 Attempt a zerocopy writeX read. We know here that len > smb_size-4
172 ****************************************************************************/
175 * Unfortunately, earlier versions of smbclient/libsmbclient
176 * don't send this "standard" writeX header. I've fixed this
177 * for 3.2 but we'll use the old method with earlier versions.
178 * Windows and CIFSFS at least use this standard size. Not
182 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
183 (2*14) + /* word count (including bcc) */ \
186 static NTSTATUS
receive_smb_raw_talloc_partial_read(TALLOC_CTX
*mem_ctx
,
187 const char lenbuf
[4],
188 int fd
, char **buffer
,
189 unsigned int timeout
,
193 /* Size of a WRITEX call (+4 byte len). */
194 char writeX_header
[4 + STANDARD_WRITE_AND_X_HEADER_SIZE
];
195 ssize_t len
= smb_len_large(lenbuf
); /* Could be a UNIX large writeX. */
199 memcpy(writeX_header
, lenbuf
, 4);
201 status
= read_fd_with_timeout(
202 fd
, writeX_header
+ 4,
203 STANDARD_WRITE_AND_X_HEADER_SIZE
,
204 STANDARD_WRITE_AND_X_HEADER_SIZE
,
207 if (!NT_STATUS_IS_OK(status
)) {
212 * Ok - now try and see if this is a possible
216 if (is_valid_writeX_buffer((uint8_t *)writeX_header
)) {
218 * If the data offset is beyond what
219 * we've read, drain the extra bytes.
221 uint16_t doff
= SVAL(writeX_header
,smb_vwv11
);
224 if (doff
> STANDARD_WRITE_AND_X_HEADER_SIZE
) {
225 size_t drain
= doff
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
226 if (drain_socket(smbd_server_fd(), drain
) != drain
) {
227 smb_panic("receive_smb_raw_talloc_partial_read:"
228 " failed to drain pending bytes");
231 doff
= STANDARD_WRITE_AND_X_HEADER_SIZE
;
234 /* Spoof down the length and null out the bcc. */
235 set_message_bcc(writeX_header
, 0);
236 newlen
= smb_len(writeX_header
);
238 /* Copy the header we've written. */
240 *buffer
= (char *)TALLOC_MEMDUP(mem_ctx
,
242 sizeof(writeX_header
));
244 if (*buffer
== NULL
) {
245 DEBUG(0, ("Could not allocate inbuf of length %d\n",
246 (int)sizeof(writeX_header
)));
247 return NT_STATUS_NO_MEMORY
;
250 /* Work out the remaining bytes. */
251 *p_unread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
252 *len_ret
= newlen
+ 4;
256 if (!valid_packet_size(len
)) {
257 return NT_STATUS_INVALID_PARAMETER
;
261 * Not a valid writeX call. Just do the standard
265 *buffer
= TALLOC_ARRAY(mem_ctx
, char, len
+4);
267 if (*buffer
== NULL
) {
268 DEBUG(0, ("Could not allocate inbuf of length %d\n",
270 return NT_STATUS_NO_MEMORY
;
273 /* Copy in what we already read. */
276 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
);
277 toread
= len
- STANDARD_WRITE_AND_X_HEADER_SIZE
;
280 status
= read_packet_remainder(
281 fd
, (*buffer
) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE
,
284 if (!NT_STATUS_IS_OK(status
)) {
285 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
295 static NTSTATUS
receive_smb_raw_talloc(TALLOC_CTX
*mem_ctx
, int fd
,
296 char **buffer
, unsigned int timeout
,
297 size_t *p_unread
, size_t *plen
)
301 int min_recv_size
= lp_min_receive_file_size();
306 status
= read_smb_length_return_keepalive(fd
, lenbuf
, timeout
, &len
);
307 if (!NT_STATUS_IS_OK(status
)) {
308 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status
)));
312 if (CVAL(lenbuf
,0) == 0 && min_recv_size
&&
313 (smb_len_large(lenbuf
) > /* Could be a UNIX large writeX. */
314 (min_recv_size
+ STANDARD_WRITE_AND_X_HEADER_SIZE
)) &&
315 !srv_is_signing_active(smbd_server_conn
) &&
316 smbd_server_conn
->smb1
.echo_handler
.trusted_fde
== NULL
) {
318 return receive_smb_raw_talloc_partial_read(
319 mem_ctx
, lenbuf
, fd
, buffer
, timeout
, p_unread
, plen
);
322 if (!valid_packet_size(len
)) {
323 return NT_STATUS_INVALID_PARAMETER
;
327 * The +4 here can't wrap, we've checked the length above already.
330 *buffer
= TALLOC_ARRAY(mem_ctx
, char, len
+4);
332 if (*buffer
== NULL
) {
333 DEBUG(0, ("Could not allocate inbuf of length %d\n",
335 return NT_STATUS_NO_MEMORY
;
338 memcpy(*buffer
, lenbuf
, sizeof(lenbuf
));
340 status
= read_packet_remainder(fd
, (*buffer
)+4, timeout
, len
);
341 if (!NT_STATUS_IS_OK(status
)) {
349 static NTSTATUS
receive_smb_talloc(TALLOC_CTX
*mem_ctx
, int fd
,
350 char **buffer
, unsigned int timeout
,
351 size_t *p_unread
, bool *p_encrypted
,
354 bool trusted_channel
)
359 *p_encrypted
= false;
361 status
= receive_smb_raw_talloc(mem_ctx
, fd
, buffer
, timeout
,
363 if (!NT_STATUS_IS_OK(status
)) {
367 if (is_encrypted_packet((uint8_t *)*buffer
)) {
368 status
= srv_decrypt_buffer(*buffer
);
369 if (!NT_STATUS_IS_OK(status
)) {
370 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
371 "incoming packet! Error %s\n",
372 nt_errstr(status
) ));
378 /* Check the incoming SMB signature. */
379 if (!srv_check_sign_mac(smbd_server_conn
, *buffer
, seqnum
, trusted_channel
)) {
380 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
381 "incoming packet!\n"));
382 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
390 * Initialize a struct smb_request from an inbuf
393 static bool init_smb_request(struct smb_request
*req
, const uint8
*inbuf
,
394 size_t unread_bytes
, bool encrypted
,
397 struct smbd_server_connection
*sconn
= smbd_server_conn
;
398 size_t req_size
= smb_len(inbuf
) + 4;
399 /* Ensure we have at least smb_size bytes. */
400 if (req_size
< smb_size
) {
401 DEBUG(0,("init_smb_request: invalid request size %u\n",
402 (unsigned int)req_size
));
405 req
->cmd
= CVAL(inbuf
, smb_com
);
406 req
->flags2
= SVAL(inbuf
, smb_flg2
);
407 req
->smbpid
= SVAL(inbuf
, smb_pid
);
408 req
->mid
= SVAL(inbuf
, smb_mid
);
409 req
->seqnum
= seqnum
;
410 req
->vuid
= SVAL(inbuf
, smb_uid
);
411 req
->tid
= SVAL(inbuf
, smb_tid
);
412 req
->wct
= CVAL(inbuf
, smb_wct
);
413 req
->vwv
= (uint16_t *)(inbuf
+smb_vwv
);
414 req
->buflen
= smb_buflen(inbuf
);
415 req
->buf
= (const uint8_t *)smb_buf(inbuf
);
416 req
->unread_bytes
= unread_bytes
;
417 req
->encrypted
= encrypted
;
418 req
->conn
= conn_find(sconn
,req
->tid
);
419 req
->chain_fsp
= NULL
;
420 req
->chain_outbuf
= NULL
;
422 smb_init_perfcount_data(&req
->pcd
);
424 /* Ensure we have at least wct words and 2 bytes of bcc. */
425 if (smb_size
+ req
->wct
*2 > req_size
) {
426 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
427 (unsigned int)req
->wct
,
428 (unsigned int)req_size
));
431 /* Ensure bcc is correct. */
432 if (((uint8
*)smb_buf(inbuf
)) + req
->buflen
> inbuf
+ req_size
) {
433 DEBUG(0,("init_smb_request: invalid bcc number %u "
434 "(wct = %u, size %u)\n",
435 (unsigned int)req
->buflen
,
436 (unsigned int)req
->wct
,
437 (unsigned int)req_size
));
445 static void process_smb(struct smbd_server_connection
*conn
,
446 uint8_t *inbuf
, size_t nread
, size_t unread_bytes
,
447 uint32_t seqnum
, bool encrypted
,
448 struct smb_perfcount_data
*deferred_pcd
);
450 static void smbd_deferred_open_timer(struct event_context
*ev
,
451 struct timed_event
*te
,
452 struct timeval _tval
,
455 struct pending_message_list
*msg
= talloc_get_type(private_data
,
456 struct pending_message_list
);
457 TALLOC_CTX
*mem_ctx
= talloc_tos();
458 uint16_t mid
= SVAL(msg
->buf
.data
,smb_mid
);
461 inbuf
= (uint8_t *)talloc_memdup(mem_ctx
, msg
->buf
.data
,
464 exit_server("smbd_deferred_open_timer: talloc failed\n");
468 /* We leave this message on the queue so the open code can
469 know this is a retry. */
470 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
471 (unsigned int)mid
));
473 /* Mark the message as processed so this is not
474 * re-processed in error. */
475 msg
->processed
= true;
477 process_smb(smbd_server_conn
, inbuf
,
479 msg
->seqnum
, msg
->encrypted
, &msg
->pcd
);
481 /* If it's still there and was processed, remove it. */
482 msg
= get_open_deferred_message(mid
);
483 if (msg
&& msg
->processed
) {
484 remove_deferred_open_smb_message(mid
);
488 /****************************************************************************
489 Function to push a message onto the tail of a linked list of smb messages ready
491 ****************************************************************************/
493 static bool push_queued_message(struct smb_request
*req
,
494 struct timeval request_time
,
495 struct timeval end_time
,
496 char *private_data
, size_t private_len
)
498 int msg_len
= smb_len(req
->inbuf
) + 4;
499 struct pending_message_list
*msg
;
501 msg
= TALLOC_ZERO_P(NULL
, struct pending_message_list
);
504 DEBUG(0,("push_message: malloc fail (1)\n"));
508 msg
->buf
= data_blob_talloc(msg
, req
->inbuf
, msg_len
);
509 if(msg
->buf
.data
== NULL
) {
510 DEBUG(0,("push_message: malloc fail (2)\n"));
515 msg
->request_time
= request_time
;
516 msg
->seqnum
= req
->seqnum
;
517 msg
->encrypted
= req
->encrypted
;
518 msg
->processed
= false;
519 SMB_PERFCOUNT_DEFER_OP(&req
->pcd
, &msg
->pcd
);
522 msg
->private_data
= data_blob_talloc(msg
, private_data
,
524 if (msg
->private_data
.data
== NULL
) {
525 DEBUG(0,("push_message: malloc fail (3)\n"));
531 msg
->te
= event_add_timed(smbd_event_context(),
534 smbd_deferred_open_timer
,
537 DEBUG(0,("push_message: event_add_timed failed\n"));
542 DLIST_ADD_END(deferred_open_queue
, msg
, struct pending_message_list
*);
544 DEBUG(10,("push_message: pushed message length %u on "
545 "deferred_open_queue\n", (unsigned int)msg_len
));
550 /****************************************************************************
551 Function to delete a sharing violation open message by mid.
552 ****************************************************************************/
554 void remove_deferred_open_smb_message(uint16 mid
)
556 struct pending_message_list
*pml
;
558 for (pml
= deferred_open_queue
; pml
; pml
= pml
->next
) {
559 if (mid
== SVAL(pml
->buf
.data
,smb_mid
)) {
560 DEBUG(10,("remove_deferred_open_smb_message: "
561 "deleting mid %u len %u\n",
563 (unsigned int)pml
->buf
.length
));
564 DLIST_REMOVE(deferred_open_queue
, pml
);
571 /****************************************************************************
572 Move a sharing violation open retry message to the front of the list and
573 schedule it for immediate processing.
574 ****************************************************************************/
576 void schedule_deferred_open_smb_message(uint16 mid
)
578 struct pending_message_list
*pml
;
581 for (pml
= deferred_open_queue
; pml
; pml
= pml
->next
) {
582 uint16 msg_mid
= SVAL(pml
->buf
.data
,smb_mid
);
584 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i
++,
585 (unsigned int)msg_mid
));
587 if (mid
== msg_mid
) {
588 struct timed_event
*te
;
590 if (pml
->processed
) {
591 /* A processed message should not be
593 DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
594 "message mid %u was already processed\n",
599 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
602 te
= event_add_timed(smbd_event_context(),
605 smbd_deferred_open_timer
,
608 DEBUG(10,("schedule_deferred_open_smb_message: "
609 "event_add_timed() failed, skipping mid %u\n",
613 TALLOC_FREE(pml
->te
);
615 DLIST_PROMOTE(deferred_open_queue
, pml
);
620 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
624 /****************************************************************************
625 Return true if this mid is on the deferred queue and was not yet processed.
626 ****************************************************************************/
628 bool open_was_deferred(uint16 mid
)
630 struct pending_message_list
*pml
;
632 for (pml
= deferred_open_queue
; pml
; pml
= pml
->next
) {
633 if (SVAL(pml
->buf
.data
,smb_mid
) == mid
&& !pml
->processed
) {
640 /****************************************************************************
641 Return the message queued by this mid.
642 ****************************************************************************/
644 struct pending_message_list
*get_open_deferred_message(uint16 mid
)
646 struct pending_message_list
*pml
;
648 for (pml
= deferred_open_queue
; pml
; pml
= pml
->next
) {
649 if (SVAL(pml
->buf
.data
,smb_mid
) == mid
) {
656 /****************************************************************************
657 Function to push a deferred open smb message onto a linked list of local smb
658 messages ready for processing.
659 ****************************************************************************/
661 bool push_deferred_smb_message(struct smb_request
*req
,
662 struct timeval request_time
,
663 struct timeval timeout
,
664 char *private_data
, size_t priv_len
)
666 struct timeval end_time
;
668 if (req
->unread_bytes
) {
669 DEBUG(0,("push_deferred_smb_message: logic error ! "
670 "unread_bytes = %u\n",
671 (unsigned int)req
->unread_bytes
));
672 smb_panic("push_deferred_smb_message: "
673 "logic error unread_bytes != 0" );
676 end_time
= timeval_sum(&request_time
, &timeout
);
678 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
679 "timeout time [%u.%06u]\n",
680 (unsigned int) smb_len(req
->inbuf
)+4, (unsigned int)req
->mid
,
681 (unsigned int)end_time
.tv_sec
,
682 (unsigned int)end_time
.tv_usec
));
684 return push_queued_message(req
, request_time
, end_time
,
685 private_data
, priv_len
);
689 struct timed_event
*te
;
690 struct timeval interval
;
692 bool (*handler
)(const struct timeval
*now
, void *private_data
);
696 static void smbd_idle_event_handler(struct event_context
*ctx
,
697 struct timed_event
*te
,
701 struct idle_event
*event
=
702 talloc_get_type_abort(private_data
, struct idle_event
);
704 TALLOC_FREE(event
->te
);
706 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
707 event
->name
, event
->te
));
709 if (!event
->handler(&now
, event
->private_data
)) {
710 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
711 event
->name
, event
->te
));
712 /* Don't repeat, delete ourselves */
717 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
718 event
->name
, event
->te
));
720 event
->te
= event_add_timed(ctx
, event
,
721 timeval_sum(&now
, &event
->interval
),
722 smbd_idle_event_handler
, event
);
724 /* We can't do much but fail here. */
725 SMB_ASSERT(event
->te
!= NULL
);
728 struct idle_event
*event_add_idle(struct event_context
*event_ctx
,
730 struct timeval interval
,
732 bool (*handler
)(const struct timeval
*now
,
736 struct idle_event
*result
;
737 struct timeval now
= timeval_current();
739 result
= TALLOC_P(mem_ctx
, struct idle_event
);
740 if (result
== NULL
) {
741 DEBUG(0, ("talloc failed\n"));
745 result
->interval
= interval
;
746 result
->handler
= handler
;
747 result
->private_data
= private_data
;
749 if (!(result
->name
= talloc_asprintf(result
, "idle_evt(%s)", name
))) {
750 DEBUG(0, ("talloc failed\n"));
755 result
->te
= event_add_timed(event_ctx
, result
,
756 timeval_sum(&now
, &interval
),
757 smbd_idle_event_handler
, result
);
758 if (result
->te
== NULL
) {
759 DEBUG(0, ("event_add_timed failed\n"));
764 DEBUG(10,("event_add_idle: %s %p\n", result
->name
, result
->te
));
768 static void smbd_sig_term_handler(struct tevent_context
*ev
,
769 struct tevent_signal
*se
,
775 exit_server_cleanly("termination signal");
778 void smbd_setup_sig_term_handler(void)
780 struct tevent_signal
*se
;
782 se
= tevent_add_signal(smbd_event_context(),
783 smbd_event_context(),
785 smbd_sig_term_handler
,
788 exit_server("failed to setup SIGTERM handler");
792 static void smbd_sig_hup_handler(struct tevent_context
*ev
,
793 struct tevent_signal
*se
,
799 change_to_root_user();
800 DEBUG(1,("Reloading services after SIGHUP\n"));
801 reload_services(False
);
804 void smbd_setup_sig_hup_handler(void)
806 struct tevent_signal
*se
;
808 se
= tevent_add_signal(smbd_event_context(),
809 smbd_event_context(),
811 smbd_sig_hup_handler
,
814 exit_server("failed to setup SIGHUP handler");
818 static NTSTATUS
smbd_server_connection_loop_once(struct smbd_server_connection
*conn
)
825 to
.tv_sec
= SMBD_SELECT_TIMEOUT
;
829 * Setup the select fd sets.
836 * Are there any timed events waiting ? If so, ensure we don't
837 * select for longer than it would take to wait for them.
844 event_add_to_select_args(smbd_event_context(), &now
,
845 &r_fds
, &w_fds
, &to
, &maxfd
);
848 /* Process a signal and timed events now... */
849 if (run_events(smbd_event_context(), 0, NULL
, NULL
)) {
850 return NT_STATUS_RETRY
;
855 START_PROFILE(smbd_idle
);
857 selrtn
= sys_select(maxfd
+1,&r_fds
,&w_fds
,NULL
,&to
);
860 END_PROFILE(smbd_idle
);
864 if (run_events(smbd_event_context(), selrtn
, &r_fds
, &w_fds
)) {
865 return NT_STATUS_RETRY
;
870 /* something is wrong. Maybe the socket is dead? */
871 return map_nt_error_from_unix(errno
);
874 /* Did we timeout ? */
876 return NT_STATUS_RETRY
;
879 /* should not be reached */
880 return NT_STATUS_INTERNAL_ERROR
;
884 * Only allow 5 outstanding trans requests. We're allocating memory, so
888 NTSTATUS
allow_new_trans(struct trans_state
*list
, int mid
)
891 for (; list
!= NULL
; list
= list
->next
) {
893 if (list
->mid
== mid
) {
894 return NT_STATUS_INVALID_PARAMETER
;
900 return NT_STATUS_INSUFFICIENT_RESOURCES
;
907 These flags determine some of the permissions required to do an operation
909 Note that I don't set NEED_WRITE on some write operations because they
910 are used by some brain-dead clients when printing, and I don't want to
911 force write permissions on print services.
913 #define AS_USER (1<<0)
914 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
915 #define TIME_INIT (1<<2)
916 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
917 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
918 #define DO_CHDIR (1<<6)
921 define a list of possible SMB messages and their corresponding
922 functions. Any message that has a NULL function is unimplemented -
923 please feel free to contribute implementations!
925 static const struct smb_message_struct
{
927 void (*fn
)(struct smb_request
*req
);
929 } smb_messages
[256] = {
931 /* 0x00 */ { "SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
932 /* 0x01 */ { "SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
933 /* 0x02 */ { "SMBopen",reply_open
,AS_USER
},
934 /* 0x03 */ { "SMBcreate",reply_mknew
,AS_USER
},
935 /* 0x04 */ { "SMBclose",reply_close
,AS_USER
| CAN_IPC
},
936 /* 0x05 */ { "SMBflush",reply_flush
,AS_USER
},
937 /* 0x06 */ { "SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
938 /* 0x07 */ { "SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
939 /* 0x08 */ { "SMBgetatr",reply_getatr
,AS_USER
},
940 /* 0x09 */ { "SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
941 /* 0x0a */ { "SMBread",reply_read
,AS_USER
},
942 /* 0x0b */ { "SMBwrite",reply_write
,AS_USER
| CAN_IPC
},
943 /* 0x0c */ { "SMBlock",reply_lock
,AS_USER
},
944 /* 0x0d */ { "SMBunlock",reply_unlock
,AS_USER
},
945 /* 0x0e */ { "SMBctemp",reply_ctemp
,AS_USER
},
946 /* 0x0f */ { "SMBmknew",reply_mknew
,AS_USER
},
947 /* 0x10 */ { "SMBcheckpath",reply_checkpath
,AS_USER
},
948 /* 0x11 */ { "SMBexit",reply_exit
,DO_CHDIR
},
949 /* 0x12 */ { "SMBlseek",reply_lseek
,AS_USER
},
950 /* 0x13 */ { "SMBlockread",reply_lockread
,AS_USER
},
951 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock
,AS_USER
},
952 /* 0x15 */ { NULL
, NULL
, 0 },
953 /* 0x16 */ { NULL
, NULL
, 0 },
954 /* 0x17 */ { NULL
, NULL
, 0 },
955 /* 0x18 */ { NULL
, NULL
, 0 },
956 /* 0x19 */ { NULL
, NULL
, 0 },
957 /* 0x1a */ { "SMBreadbraw",reply_readbraw
,AS_USER
},
958 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx
,AS_USER
},
959 /* 0x1c */ { "SMBreadBs",reply_readbs
,AS_USER
},
960 /* 0x1d */ { "SMBwritebraw",reply_writebraw
,AS_USER
},
961 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx
,AS_USER
},
962 /* 0x1f */ { "SMBwriteBs",reply_writebs
,AS_USER
},
963 /* 0x20 */ { "SMBwritec", NULL
,0},
964 /* 0x21 */ { NULL
, NULL
, 0 },
965 /* 0x22 */ { "SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
966 /* 0x23 */ { "SMBgetattrE",reply_getattrE
,AS_USER
},
967 /* 0x24 */ { "SMBlockingX",reply_lockingX
,AS_USER
},
968 /* 0x25 */ { "SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
969 /* 0x26 */ { "SMBtranss",reply_transs
,AS_USER
| CAN_IPC
},
970 /* 0x27 */ { "SMBioctl",reply_ioctl
,0},
971 /* 0x28 */ { "SMBioctls", NULL
,AS_USER
},
972 /* 0x29 */ { "SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
973 /* 0x2a */ { "SMBmove", NULL
,AS_USER
| NEED_WRITE
},
974 /* 0x2b */ { "SMBecho",reply_echo
,0},
975 /* 0x2c */ { "SMBwriteclose",reply_writeclose
,AS_USER
},
976 /* 0x2d */ { "SMBopenX",reply_open_and_X
,AS_USER
| CAN_IPC
},
977 /* 0x2e */ { "SMBreadX",reply_read_and_X
,AS_USER
| CAN_IPC
},
978 /* 0x2f */ { "SMBwriteX",reply_write_and_X
,AS_USER
| CAN_IPC
},
979 /* 0x30 */ { NULL
, NULL
, 0 },
980 /* 0x31 */ { NULL
, NULL
, 0 },
981 /* 0x32 */ { "SMBtrans2",reply_trans2
, AS_USER
| CAN_IPC
},
982 /* 0x33 */ { "SMBtranss2",reply_transs2
, AS_USER
| CAN_IPC
},
983 /* 0x34 */ { "SMBfindclose",reply_findclose
,AS_USER
},
984 /* 0x35 */ { "SMBfindnclose",reply_findnclose
,AS_USER
},
985 /* 0x36 */ { NULL
, NULL
, 0 },
986 /* 0x37 */ { NULL
, NULL
, 0 },
987 /* 0x38 */ { NULL
, NULL
, 0 },
988 /* 0x39 */ { NULL
, NULL
, 0 },
989 /* 0x3a */ { NULL
, NULL
, 0 },
990 /* 0x3b */ { NULL
, NULL
, 0 },
991 /* 0x3c */ { NULL
, NULL
, 0 },
992 /* 0x3d */ { NULL
, NULL
, 0 },
993 /* 0x3e */ { NULL
, NULL
, 0 },
994 /* 0x3f */ { NULL
, NULL
, 0 },
995 /* 0x40 */ { NULL
, NULL
, 0 },
996 /* 0x41 */ { NULL
, NULL
, 0 },
997 /* 0x42 */ { NULL
, NULL
, 0 },
998 /* 0x43 */ { NULL
, NULL
, 0 },
999 /* 0x44 */ { NULL
, NULL
, 0 },
1000 /* 0x45 */ { NULL
, NULL
, 0 },
1001 /* 0x46 */ { NULL
, NULL
, 0 },
1002 /* 0x47 */ { NULL
, NULL
, 0 },
1003 /* 0x48 */ { NULL
, NULL
, 0 },
1004 /* 0x49 */ { NULL
, NULL
, 0 },
1005 /* 0x4a */ { NULL
, NULL
, 0 },
1006 /* 0x4b */ { NULL
, NULL
, 0 },
1007 /* 0x4c */ { NULL
, NULL
, 0 },
1008 /* 0x4d */ { NULL
, NULL
, 0 },
1009 /* 0x4e */ { NULL
, NULL
, 0 },
1010 /* 0x4f */ { NULL
, NULL
, 0 },
1011 /* 0x50 */ { NULL
, NULL
, 0 },
1012 /* 0x51 */ { NULL
, NULL
, 0 },
1013 /* 0x52 */ { NULL
, NULL
, 0 },
1014 /* 0x53 */ { NULL
, NULL
, 0 },
1015 /* 0x54 */ { NULL
, NULL
, 0 },
1016 /* 0x55 */ { NULL
, NULL
, 0 },
1017 /* 0x56 */ { NULL
, NULL
, 0 },
1018 /* 0x57 */ { NULL
, NULL
, 0 },
1019 /* 0x58 */ { NULL
, NULL
, 0 },
1020 /* 0x59 */ { NULL
, NULL
, 0 },
1021 /* 0x5a */ { NULL
, NULL
, 0 },
1022 /* 0x5b */ { NULL
, NULL
, 0 },
1023 /* 0x5c */ { NULL
, NULL
, 0 },
1024 /* 0x5d */ { NULL
, NULL
, 0 },
1025 /* 0x5e */ { NULL
, NULL
, 0 },
1026 /* 0x5f */ { NULL
, NULL
, 0 },
1027 /* 0x60 */ { NULL
, NULL
, 0 },
1028 /* 0x61 */ { NULL
, NULL
, 0 },
1029 /* 0x62 */ { NULL
, NULL
, 0 },
1030 /* 0x63 */ { NULL
, NULL
, 0 },
1031 /* 0x64 */ { NULL
, NULL
, 0 },
1032 /* 0x65 */ { NULL
, NULL
, 0 },
1033 /* 0x66 */ { NULL
, NULL
, 0 },
1034 /* 0x67 */ { NULL
, NULL
, 0 },
1035 /* 0x68 */ { NULL
, NULL
, 0 },
1036 /* 0x69 */ { NULL
, NULL
, 0 },
1037 /* 0x6a */ { NULL
, NULL
, 0 },
1038 /* 0x6b */ { NULL
, NULL
, 0 },
1039 /* 0x6c */ { NULL
, NULL
, 0 },
1040 /* 0x6d */ { NULL
, NULL
, 0 },
1041 /* 0x6e */ { NULL
, NULL
, 0 },
1042 /* 0x6f */ { NULL
, NULL
, 0 },
1043 /* 0x70 */ { "SMBtcon",reply_tcon
,0},
1044 /* 0x71 */ { "SMBtdis",reply_tdis
,DO_CHDIR
},
1045 /* 0x72 */ { "SMBnegprot",reply_negprot
,0},
1046 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X
,0},
1047 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX
, 0}, /* ulogoff doesn't give a valid TID */
1048 /* 0x75 */ { "SMBtconX",reply_tcon_and_X
,0},
1049 /* 0x76 */ { NULL
, NULL
, 0 },
1050 /* 0x77 */ { NULL
, NULL
, 0 },
1051 /* 0x78 */ { NULL
, NULL
, 0 },
1052 /* 0x79 */ { NULL
, NULL
, 0 },
1053 /* 0x7a */ { NULL
, NULL
, 0 },
1054 /* 0x7b */ { NULL
, NULL
, 0 },
1055 /* 0x7c */ { NULL
, NULL
, 0 },
1056 /* 0x7d */ { NULL
, NULL
, 0 },
1057 /* 0x7e */ { NULL
, NULL
, 0 },
1058 /* 0x7f */ { NULL
, NULL
, 0 },
1059 /* 0x80 */ { "SMBdskattr",reply_dskattr
,AS_USER
},
1060 /* 0x81 */ { "SMBsearch",reply_search
,AS_USER
},
1061 /* 0x82 */ { "SMBffirst",reply_search
,AS_USER
},
1062 /* 0x83 */ { "SMBfunique",reply_search
,AS_USER
},
1063 /* 0x84 */ { "SMBfclose",reply_fclose
,AS_USER
},
1064 /* 0x85 */ { NULL
, NULL
, 0 },
1065 /* 0x86 */ { NULL
, NULL
, 0 },
1066 /* 0x87 */ { NULL
, NULL
, 0 },
1067 /* 0x88 */ { NULL
, NULL
, 0 },
1068 /* 0x89 */ { NULL
, NULL
, 0 },
1069 /* 0x8a */ { NULL
, NULL
, 0 },
1070 /* 0x8b */ { NULL
, NULL
, 0 },
1071 /* 0x8c */ { NULL
, NULL
, 0 },
1072 /* 0x8d */ { NULL
, NULL
, 0 },
1073 /* 0x8e */ { NULL
, NULL
, 0 },
1074 /* 0x8f */ { NULL
, NULL
, 0 },
1075 /* 0x90 */ { NULL
, NULL
, 0 },
1076 /* 0x91 */ { NULL
, NULL
, 0 },
1077 /* 0x92 */ { NULL
, NULL
, 0 },
1078 /* 0x93 */ { NULL
, NULL
, 0 },
1079 /* 0x94 */ { NULL
, NULL
, 0 },
1080 /* 0x95 */ { NULL
, NULL
, 0 },
1081 /* 0x96 */ { NULL
, NULL
, 0 },
1082 /* 0x97 */ { NULL
, NULL
, 0 },
1083 /* 0x98 */ { NULL
, NULL
, 0 },
1084 /* 0x99 */ { NULL
, NULL
, 0 },
1085 /* 0x9a */ { NULL
, NULL
, 0 },
1086 /* 0x9b */ { NULL
, NULL
, 0 },
1087 /* 0x9c */ { NULL
, NULL
, 0 },
1088 /* 0x9d */ { NULL
, NULL
, 0 },
1089 /* 0x9e */ { NULL
, NULL
, 0 },
1090 /* 0x9f */ { NULL
, NULL
, 0 },
1091 /* 0xa0 */ { "SMBnttrans",reply_nttrans
, AS_USER
| CAN_IPC
},
1092 /* 0xa1 */ { "SMBnttranss",reply_nttranss
, AS_USER
| CAN_IPC
},
1093 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X
, AS_USER
| CAN_IPC
},
1094 /* 0xa3 */ { NULL
, NULL
, 0 },
1095 /* 0xa4 */ { "SMBntcancel",reply_ntcancel
, 0 },
1096 /* 0xa5 */ { "SMBntrename",reply_ntrename
, AS_USER
| NEED_WRITE
},
1097 /* 0xa6 */ { NULL
, NULL
, 0 },
1098 /* 0xa7 */ { NULL
, NULL
, 0 },
1099 /* 0xa8 */ { NULL
, NULL
, 0 },
1100 /* 0xa9 */ { NULL
, NULL
, 0 },
1101 /* 0xaa */ { NULL
, NULL
, 0 },
1102 /* 0xab */ { NULL
, NULL
, 0 },
1103 /* 0xac */ { NULL
, NULL
, 0 },
1104 /* 0xad */ { NULL
, NULL
, 0 },
1105 /* 0xae */ { NULL
, NULL
, 0 },
1106 /* 0xaf */ { NULL
, NULL
, 0 },
1107 /* 0xb0 */ { NULL
, NULL
, 0 },
1108 /* 0xb1 */ { NULL
, NULL
, 0 },
1109 /* 0xb2 */ { NULL
, NULL
, 0 },
1110 /* 0xb3 */ { NULL
, NULL
, 0 },
1111 /* 0xb4 */ { NULL
, NULL
, 0 },
1112 /* 0xb5 */ { NULL
, NULL
, 0 },
1113 /* 0xb6 */ { NULL
, NULL
, 0 },
1114 /* 0xb7 */ { NULL
, NULL
, 0 },
1115 /* 0xb8 */ { NULL
, NULL
, 0 },
1116 /* 0xb9 */ { NULL
, NULL
, 0 },
1117 /* 0xba */ { NULL
, NULL
, 0 },
1118 /* 0xbb */ { NULL
, NULL
, 0 },
1119 /* 0xbc */ { NULL
, NULL
, 0 },
1120 /* 0xbd */ { NULL
, NULL
, 0 },
1121 /* 0xbe */ { NULL
, NULL
, 0 },
1122 /* 0xbf */ { NULL
, NULL
, 0 },
1123 /* 0xc0 */ { "SMBsplopen",reply_printopen
,AS_USER
},
1124 /* 0xc1 */ { "SMBsplwr",reply_printwrite
,AS_USER
},
1125 /* 0xc2 */ { "SMBsplclose",reply_printclose
,AS_USER
},
1126 /* 0xc3 */ { "SMBsplretq",reply_printqueue
,AS_USER
},
1127 /* 0xc4 */ { NULL
, NULL
, 0 },
1128 /* 0xc5 */ { NULL
, NULL
, 0 },
1129 /* 0xc6 */ { NULL
, NULL
, 0 },
1130 /* 0xc7 */ { NULL
, NULL
, 0 },
1131 /* 0xc8 */ { NULL
, NULL
, 0 },
1132 /* 0xc9 */ { NULL
, NULL
, 0 },
1133 /* 0xca */ { NULL
, NULL
, 0 },
1134 /* 0xcb */ { NULL
, NULL
, 0 },
1135 /* 0xcc */ { NULL
, NULL
, 0 },
1136 /* 0xcd */ { NULL
, NULL
, 0 },
1137 /* 0xce */ { NULL
, NULL
, 0 },
1138 /* 0xcf */ { NULL
, NULL
, 0 },
1139 /* 0xd0 */ { "SMBsends",reply_sends
,AS_GUEST
},
1140 /* 0xd1 */ { "SMBsendb", NULL
,AS_GUEST
},
1141 /* 0xd2 */ { "SMBfwdname", NULL
,AS_GUEST
},
1142 /* 0xd3 */ { "SMBcancelf", NULL
,AS_GUEST
},
1143 /* 0xd4 */ { "SMBgetmac", NULL
,AS_GUEST
},
1144 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt
,AS_GUEST
},
1145 /* 0xd6 */ { "SMBsendend",reply_sendend
,AS_GUEST
},
1146 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt
,AS_GUEST
},
1147 /* 0xd8 */ { NULL
, NULL
, 0 },
1148 /* 0xd9 */ { NULL
, NULL
, 0 },
1149 /* 0xda */ { NULL
, NULL
, 0 },
1150 /* 0xdb */ { NULL
, NULL
, 0 },
1151 /* 0xdc */ { NULL
, NULL
, 0 },
1152 /* 0xdd */ { NULL
, NULL
, 0 },
1153 /* 0xde */ { NULL
, NULL
, 0 },
1154 /* 0xdf */ { NULL
, NULL
, 0 },
1155 /* 0xe0 */ { NULL
, NULL
, 0 },
1156 /* 0xe1 */ { NULL
, NULL
, 0 },
1157 /* 0xe2 */ { NULL
, NULL
, 0 },
1158 /* 0xe3 */ { NULL
, NULL
, 0 },
1159 /* 0xe4 */ { NULL
, NULL
, 0 },
1160 /* 0xe5 */ { NULL
, NULL
, 0 },
1161 /* 0xe6 */ { NULL
, NULL
, 0 },
1162 /* 0xe7 */ { NULL
, NULL
, 0 },
1163 /* 0xe8 */ { NULL
, NULL
, 0 },
1164 /* 0xe9 */ { NULL
, NULL
, 0 },
1165 /* 0xea */ { NULL
, NULL
, 0 },
1166 /* 0xeb */ { NULL
, NULL
, 0 },
1167 /* 0xec */ { NULL
, NULL
, 0 },
1168 /* 0xed */ { NULL
, NULL
, 0 },
1169 /* 0xee */ { NULL
, NULL
, 0 },
1170 /* 0xef */ { NULL
, NULL
, 0 },
1171 /* 0xf0 */ { NULL
, NULL
, 0 },
1172 /* 0xf1 */ { NULL
, NULL
, 0 },
1173 /* 0xf2 */ { NULL
, NULL
, 0 },
1174 /* 0xf3 */ { NULL
, NULL
, 0 },
1175 /* 0xf4 */ { NULL
, NULL
, 0 },
1176 /* 0xf5 */ { NULL
, NULL
, 0 },
1177 /* 0xf6 */ { NULL
, NULL
, 0 },
1178 /* 0xf7 */ { NULL
, NULL
, 0 },
1179 /* 0xf8 */ { NULL
, NULL
, 0 },
1180 /* 0xf9 */ { NULL
, NULL
, 0 },
1181 /* 0xfa */ { NULL
, NULL
, 0 },
1182 /* 0xfb */ { NULL
, NULL
, 0 },
1183 /* 0xfc */ { NULL
, NULL
, 0 },
1184 /* 0xfd */ { NULL
, NULL
, 0 },
1185 /* 0xfe */ { NULL
, NULL
, 0 },
1186 /* 0xff */ { NULL
, NULL
, 0 }
1190 /*******************************************************************
1191 allocate and initialize a reply packet
1192 ********************************************************************/
1194 static bool create_outbuf(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
1195 const char *inbuf
, char **outbuf
, uint8_t num_words
,
1199 * Protect against integer wrap
1201 if ((num_bytes
> 0xffffff)
1202 || ((num_bytes
+ smb_size
+ num_words
*2) > 0xffffff)) {
1204 if (asprintf(&msg
, "num_bytes too large: %u",
1205 (unsigned)num_bytes
) == -1) {
1206 msg
= CONST_DISCARD(char *, "num_bytes too large");
1211 *outbuf
= TALLOC_ARRAY(mem_ctx
, char,
1212 smb_size
+ num_words
*2 + num_bytes
);
1213 if (*outbuf
== NULL
) {
1217 construct_reply_common(req
, inbuf
, *outbuf
);
1218 srv_set_message(*outbuf
, num_words
, num_bytes
, false);
1220 * Zero out the word area, the caller has to take care of the bcc area
1223 if (num_words
!= 0) {
1224 memset(*outbuf
+ smb_vwv0
, 0, num_words
*2);
1230 void reply_outbuf(struct smb_request
*req
, uint8 num_words
, uint32 num_bytes
)
1233 if (!create_outbuf(req
, req
, (char *)req
->inbuf
, &outbuf
, num_words
,
1235 smb_panic("could not allocate output buffer\n");
1237 req
->outbuf
= (uint8_t *)outbuf
;
1241 /*******************************************************************
1242 Dump a packet to a file.
1243 ********************************************************************/
1245 static void smb_dump(const char *name
, int type
, const char *data
, ssize_t len
)
1249 if (DEBUGLEVEL
< 50) {
1253 if (len
< 4) len
= smb_len(data
)+4;
1254 for (i
=1;i
<100;i
++) {
1255 if (asprintf(&fname
, "/tmp/%s.%d.%s", name
, i
,
1256 type
? "req" : "resp") == -1) {
1259 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644);
1260 if (fd
!= -1 || errno
!= EEXIST
) break;
1263 ssize_t ret
= write(fd
, data
, len
);
1265 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret
));
1267 DEBUG(0,("created %s len %lu\n", fname
, (unsigned long)len
));
1272 /****************************************************************************
1273 Prepare everything for calling the actual request function, and potentially
1274 call the request function via the "new" interface.
1276 Return False if the "legacy" function needs to be called, everything is
1279 Return True if we're done.
1281 I know this API sucks, but it is the one with the least code change I could
1283 ****************************************************************************/
1285 static connection_struct
*switch_message(uint8 type
, struct smb_request
*req
, int size
)
1289 connection_struct
*conn
= NULL
;
1290 struct smbd_server_connection
*sconn
= smbd_server_conn
;
1294 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1295 * so subtract 4 from it. */
1296 if (!valid_smb_header(req
->inbuf
)
1297 || (size
< (smb_size
- 4))) {
1298 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1299 smb_len(req
->inbuf
)));
1300 exit_server_cleanly("Non-SMB packet");
1303 if (smb_messages
[type
].fn
== NULL
) {
1304 DEBUG(0,("Unknown message type %d!\n",type
));
1305 smb_dump("Unknown", 1, (char *)req
->inbuf
, size
);
1306 reply_unknown_new(req
, type
);
1310 flags
= smb_messages
[type
].flags
;
1312 /* In share mode security we must ignore the vuid. */
1313 session_tag
= (lp_security() == SEC_SHARE
)
1314 ? UID_FIELD_INVALID
: req
->vuid
;
1317 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type
),
1318 (int)sys_getpid(), (unsigned long)conn
));
1320 smb_dump(smb_fn_name(type
), 1, (char *)req
->inbuf
, size
);
1322 /* Ensure this value is replaced in the incoming packet. */
1323 SSVAL(req
->inbuf
,smb_uid
,session_tag
);
1326 * Ensure the correct username is in current_user_info. This is a
1327 * really ugly bugfix for problems with multiple session_setup_and_X's
1328 * being done and allowing %U and %G substitutions to work correctly.
1329 * There is a reason this code is done here, don't move it unless you
1330 * know what you're doing... :-).
1334 if (session_tag
!= sconn
->smb1
.sessions
.last_session_tag
) {
1335 user_struct
*vuser
= NULL
;
1337 sconn
->smb1
.sessions
.last_session_tag
= session_tag
;
1338 if(session_tag
!= UID_FIELD_INVALID
) {
1339 vuser
= get_valid_user_struct(sconn
, session_tag
);
1341 set_current_user_info(
1342 vuser
->server_info
->sanitized_username
,
1343 vuser
->server_info
->unix_name
,
1344 pdb_get_domain(vuser
->server_info
1350 /* Does this call need to be run as the connected user? */
1351 if (flags
& AS_USER
) {
1353 /* Does this call need a valid tree connection? */
1356 * Amazingly, the error code depends on the command
1359 if (type
== SMBntcreateX
) {
1360 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1362 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
1367 if (!change_to_user(conn
,session_tag
)) {
1368 DEBUG(0, ("Error: Could not change to user. Removing "
1369 "deferred open, mid=%d.\n", req
->mid
));
1370 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
1374 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1376 /* Does it need write permission? */
1377 if ((flags
& NEED_WRITE
) && !CAN_WRITE(conn
)) {
1378 reply_nterror(req
, NT_STATUS_MEDIA_WRITE_PROTECTED
);
1382 /* IPC services are limited */
1383 if (IS_IPC(conn
) && !(flags
& CAN_IPC
)) {
1384 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1388 /* This call needs to be run as root */
1389 change_to_root_user();
1392 /* load service specific parameters */
1394 if (req
->encrypted
) {
1395 conn
->encrypted_tid
= true;
1396 /* encrypted required from now on. */
1397 conn
->encrypt_level
= Required
;
1398 } else if (ENCRYPTION_REQUIRED(conn
)) {
1399 if (req
->cmd
!= SMBtrans2
&& req
->cmd
!= SMBtranss2
) {
1400 exit_server_cleanly("encryption required "
1406 if (!set_current_service(conn
,SVAL(req
->inbuf
,smb_flg
),
1407 (flags
& (AS_USER
|DO_CHDIR
)
1409 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1412 conn
->num_smb_operations
++;
1415 /* does this protocol need to be run as guest? */
1416 if ((flags
& AS_GUEST
)
1417 && (!change_to_guest() ||
1418 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1419 lp_hostsdeny(-1)))) {
1420 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1424 smb_messages
[type
].fn(req
);
1428 /****************************************************************************
1429 Construct a reply to the incoming packet.
1430 ****************************************************************************/
1432 static void construct_reply(char *inbuf
, int size
, size_t unread_bytes
,
1433 uint32_t seqnum
, bool encrypted
,
1434 struct smb_perfcount_data
*deferred_pcd
)
1436 connection_struct
*conn
;
1437 struct smb_request
*req
;
1439 if (!(req
= talloc(talloc_tos(), struct smb_request
))) {
1440 smb_panic("could not allocate smb_request");
1443 if (!init_smb_request(req
, (uint8
*)inbuf
, unread_bytes
, encrypted
,
1445 exit_server_cleanly("Invalid SMB request");
1448 req
->inbuf
= (uint8_t *)talloc_move(req
, &inbuf
);
1450 /* we popped this message off the queue - keep original perf data */
1452 req
->pcd
= *deferred_pcd
;
1454 SMB_PERFCOUNT_START(&req
->pcd
);
1455 SMB_PERFCOUNT_SET_OP(&req
->pcd
, req
->cmd
);
1456 SMB_PERFCOUNT_SET_MSGLEN_IN(&req
->pcd
, size
);
1459 conn
= switch_message(req
->cmd
, req
, size
);
1461 if (req
->unread_bytes
) {
1462 /* writeX failed. drain socket. */
1463 if (drain_socket(smbd_server_fd(), req
->unread_bytes
) !=
1464 req
->unread_bytes
) {
1465 smb_panic("failed to drain pending bytes");
1467 req
->unread_bytes
= 0;
1475 if (req
->outbuf
== NULL
) {
1479 if (CVAL(req
->outbuf
,0) == 0) {
1480 show_msg((char *)req
->outbuf
);
1483 if (!srv_send_smb(smbd_server_fd(),
1484 (char *)req
->outbuf
,
1485 true, req
->seqnum
+1,
1486 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
1488 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1496 /****************************************************************************
1497 Process an smb from the client
1498 ****************************************************************************/
1499 static void process_smb(struct smbd_server_connection
*conn
,
1500 uint8_t *inbuf
, size_t nread
, size_t unread_bytes
,
1501 uint32_t seqnum
, bool encrypted
,
1502 struct smb_perfcount_data
*deferred_pcd
)
1504 int msg_type
= CVAL(inbuf
,0);
1506 DO_PROFILE_INC(smb_count
);
1508 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type
,
1510 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num
,
1512 (unsigned int)unread_bytes
));
1514 if (msg_type
!= 0) {
1516 * NetBIOS session request, keepalive, etc.
1518 reply_special((char *)inbuf
);
1522 if (smbd_server_conn
->allow_smb2
) {
1523 if (smbd_is_smb2_header(inbuf
, nread
)) {
1524 smbd_smb2_first_negprot(smbd_server_conn
, inbuf
, nread
);
1527 smbd_server_conn
->allow_smb2
= false;
1530 show_msg((char *)inbuf
);
1532 construct_reply((char *)inbuf
,nread
,unread_bytes
,seqnum
,encrypted
,deferred_pcd
);
1536 conn
->smb1
.num_requests
++;
1538 /* The timeout_processing function isn't run nearly
1539 often enough to implement 'max log size' without
1540 overrunning the size of the file by many megabytes.
1541 This is especially true if we are running at debug
1542 level 10. Checking every 50 SMBs is a nice
1543 tradeoff of performance vs log file size overrun. */
1545 if ((conn
->smb1
.num_requests
% 50) == 0 &&
1546 need_to_check_log_size()) {
1547 change_to_root_user();
1552 /****************************************************************************
1553 Return a string containing the function name of a SMB command.
1554 ****************************************************************************/
1556 const char *smb_fn_name(int type
)
1558 const char *unknown_name
= "SMBunknown";
1560 if (smb_messages
[type
].name
== NULL
)
1561 return(unknown_name
);
1563 return(smb_messages
[type
].name
);
1566 /****************************************************************************
1567 Helper functions for contruct_reply.
1568 ****************************************************************************/
1570 void add_to_common_flags2(uint32 v
)
1575 void remove_from_common_flags2(uint32 v
)
1577 common_flags2
&= ~v
;
1580 static void construct_reply_common(struct smb_request
*req
, const char *inbuf
,
1583 srv_set_message(outbuf
,0,0,false);
1585 SCVAL(outbuf
, smb_com
, req
->cmd
);
1586 SIVAL(outbuf
,smb_rcls
,0);
1587 SCVAL(outbuf
,smb_flg
, FLAG_REPLY
| (CVAL(inbuf
,smb_flg
) & FLAG_CASELESS_PATHNAMES
));
1588 SSVAL(outbuf
,smb_flg2
,
1589 (SVAL(inbuf
,smb_flg2
) & FLAGS2_UNICODE_STRINGS
) |
1591 memset(outbuf
+smb_pidhigh
,'\0',(smb_tid
-smb_pidhigh
));
1593 SSVAL(outbuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
1594 SSVAL(outbuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
1595 SSVAL(outbuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
1596 SSVAL(outbuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
1599 void construct_reply_common_req(struct smb_request
*req
, char *outbuf
)
1601 construct_reply_common(req
, (char *)req
->inbuf
, outbuf
);
1605 * How many bytes have we already accumulated up to the current wct field
1609 size_t req_wct_ofs(struct smb_request
*req
)
1613 if (req
->chain_outbuf
== NULL
) {
1616 buf_size
= talloc_get_size(req
->chain_outbuf
);
1617 if ((buf_size
% 4) != 0) {
1618 buf_size
+= (4 - (buf_size
% 4));
1620 return buf_size
- 4;
1624 * Hack around reply_nterror & friends not being aware of chained requests,
1625 * generating illegal (i.e. wct==0) chain replies.
1628 static void fixup_chain_error_packet(struct smb_request
*req
)
1630 uint8_t *outbuf
= req
->outbuf
;
1632 reply_outbuf(req
, 2, 0);
1633 memcpy(req
->outbuf
, outbuf
, smb_wct
);
1634 TALLOC_FREE(outbuf
);
1635 SCVAL(req
->outbuf
, smb_vwv0
, 0xff);
1639 * @brief Find the smb_cmd offset of the last command pushed
1640 * @param[in] buf The buffer we're building up
1641 * @retval Where can we put our next andx cmd?
1643 * While chaining requests, the "next" request we're looking at needs to put
1644 * its SMB_Command before the data the previous request already built up added
1645 * to the chain. Find the offset to the place where we have to put our cmd.
1648 static bool find_andx_cmd_ofs(uint8_t *buf
, size_t *pofs
)
1653 cmd
= CVAL(buf
, smb_com
);
1655 SMB_ASSERT(is_andx_req(cmd
));
1659 while (CVAL(buf
, ofs
) != 0xff) {
1661 if (!is_andx_req(CVAL(buf
, ofs
))) {
1666 * ofs is from start of smb header, so add the 4 length
1667 * bytes. The next cmd is right after the wct field.
1669 ofs
= SVAL(buf
, ofs
+2) + 4 + 1;
1671 SMB_ASSERT(ofs
+4 < talloc_get_size(buf
));
1679 * @brief Do the smb chaining at a buffer level
1680 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1681 * @param[in] smb_command The command that we want to issue
1682 * @param[in] wct How many words?
1683 * @param[in] vwv The words, already in network order
1684 * @param[in] bytes_alignment How shall we align "bytes"?
1685 * @param[in] num_bytes How many bytes?
1686 * @param[in] bytes The data the request ships
1688 * smb_splice_chain() adds the vwv and bytes to the request already present in
1692 static bool smb_splice_chain(uint8_t **poutbuf
, uint8_t smb_command
,
1693 uint8_t wct
, const uint16_t *vwv
,
1694 size_t bytes_alignment
,
1695 uint32_t num_bytes
, const uint8_t *bytes
)
1698 size_t old_size
, new_size
;
1700 size_t chain_padding
= 0;
1701 size_t bytes_padding
= 0;
1704 old_size
= talloc_get_size(*poutbuf
);
1707 * old_size == smb_wct means we're pushing the first request in for
1711 first_request
= (old_size
== smb_wct
);
1713 if (!first_request
&& ((old_size
% 4) != 0)) {
1715 * Align the wct field of subsequent requests to a 4-byte
1718 chain_padding
= 4 - (old_size
% 4);
1722 * After the old request comes the new wct field (1 byte), the vwv's
1723 * and the num_bytes field. After at we might need to align the bytes
1724 * given to us to "bytes_alignment", increasing the num_bytes value.
1727 new_size
= old_size
+ chain_padding
+ 1 + wct
* sizeof(uint16_t) + 2;
1729 if ((bytes_alignment
!= 0) && ((new_size
% bytes_alignment
) != 0)) {
1730 bytes_padding
= bytes_alignment
- (new_size
% bytes_alignment
);
1733 new_size
+= bytes_padding
+ num_bytes
;
1735 if ((smb_command
!= SMBwriteX
) && (new_size
> 0xffff)) {
1736 DEBUG(1, ("splice_chain: %u bytes won't fit\n",
1737 (unsigned)new_size
));
1741 outbuf
= TALLOC_REALLOC_ARRAY(NULL
, *poutbuf
, uint8_t, new_size
);
1742 if (outbuf
== NULL
) {
1743 DEBUG(0, ("talloc failed\n"));
1748 if (first_request
) {
1749 SCVAL(outbuf
, smb_com
, smb_command
);
1751 size_t andx_cmd_ofs
;
1753 if (!find_andx_cmd_ofs(outbuf
, &andx_cmd_ofs
)) {
1754 DEBUG(1, ("invalid command chain\n"));
1755 *poutbuf
= TALLOC_REALLOC_ARRAY(
1756 NULL
, *poutbuf
, uint8_t, old_size
);
1760 if (chain_padding
!= 0) {
1761 memset(outbuf
+ old_size
, 0, chain_padding
);
1762 old_size
+= chain_padding
;
1765 SCVAL(outbuf
, andx_cmd_ofs
, smb_command
);
1766 SSVAL(outbuf
, andx_cmd_ofs
+ 2, old_size
- 4);
1772 * Push the chained request:
1777 SCVAL(outbuf
, ofs
, wct
);
1784 memcpy(outbuf
+ ofs
, vwv
, sizeof(uint16_t) * wct
);
1785 ofs
+= sizeof(uint16_t) * wct
;
1791 SSVAL(outbuf
, ofs
, num_bytes
+ bytes_padding
);
1792 ofs
+= sizeof(uint16_t);
1798 if (bytes_padding
!= 0) {
1799 memset(outbuf
+ ofs
, 0, bytes_padding
);
1800 ofs
+= bytes_padding
;
1807 memcpy(outbuf
+ ofs
, bytes
, num_bytes
);
1812 /****************************************************************************
1813 Construct a chained reply and add it to the already made reply
1814 ****************************************************************************/
1816 void chain_reply(struct smb_request
*req
)
1818 size_t smblen
= smb_len(req
->inbuf
);
1819 size_t already_used
, length_needed
;
1821 uint32_t chain_offset
; /* uint32_t to avoid overflow */
1828 if (IVAL(req
->outbuf
, smb_rcls
) != 0) {
1829 fixup_chain_error_packet(req
);
1833 * Any of the AndX requests and replies have at least a wct of
1834 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1835 * beginning of the SMB header to the next wct field.
1837 * None of the AndX requests put anything valuable in vwv[0] and [1],
1838 * so we can overwrite it here to form the chain.
1841 if ((req
->wct
< 2) || (CVAL(req
->outbuf
, smb_wct
) < 2)) {
1842 if (req
->chain_outbuf
== NULL
) {
1843 req
->chain_outbuf
= TALLOC_REALLOC_ARRAY(
1844 req
, req
->outbuf
, uint8_t,
1845 smb_len(req
->outbuf
) + 4);
1846 if (req
->chain_outbuf
== NULL
) {
1847 smb_panic("talloc failed");
1855 * Here we assume that this is the end of the chain. For that we need
1856 * to set "next command" to 0xff and the offset to 0. If we later find
1857 * more commands in the chain, this will be overwritten again.
1860 SCVAL(req
->outbuf
, smb_vwv0
, 0xff);
1861 SCVAL(req
->outbuf
, smb_vwv0
+1, 0);
1862 SSVAL(req
->outbuf
, smb_vwv1
, 0);
1864 if (req
->chain_outbuf
== NULL
) {
1866 * In req->chain_outbuf we collect all the replies. Start the
1867 * chain by copying in the first reply.
1869 * We do the realloc because later on we depend on
1870 * talloc_get_size to determine the length of
1871 * chain_outbuf. The reply_xxx routines might have
1872 * over-allocated (reply_pipe_read_and_X used to be such an
1875 req
->chain_outbuf
= TALLOC_REALLOC_ARRAY(
1876 req
, req
->outbuf
, uint8_t, smb_len(req
->outbuf
) + 4);
1877 if (req
->chain_outbuf
== NULL
) {
1878 smb_panic("talloc failed");
1883 * Update smb headers where subsequent chained commands
1884 * may have updated them.
1886 SCVAL(req
->chain_outbuf
, smb_tid
, CVAL(req
->outbuf
, smb_tid
));
1887 SCVAL(req
->chain_outbuf
, smb_uid
, CVAL(req
->outbuf
, smb_uid
));
1889 if (!smb_splice_chain(&req
->chain_outbuf
,
1890 CVAL(req
->outbuf
, smb_com
),
1891 CVAL(req
->outbuf
, smb_wct
),
1892 (uint16_t *)(req
->outbuf
+ smb_vwv
),
1893 0, smb_buflen(req
->outbuf
),
1894 (uint8_t *)smb_buf(req
->outbuf
))) {
1897 TALLOC_FREE(req
->outbuf
);
1901 * We use the old request's vwv field to grab the next chained command
1902 * and offset into the chained fields.
1905 chain_cmd
= CVAL(req
->vwv
+0, 0);
1906 chain_offset
= SVAL(req
->vwv
+1, 0);
1908 if (chain_cmd
== 0xff) {
1910 * End of chain, no more requests from the client. So ship the
1913 smb_setlen((char *)(req
->chain_outbuf
),
1914 talloc_get_size(req
->chain_outbuf
) - 4);
1916 if (!srv_send_smb(smbd_server_fd(), (char *)req
->chain_outbuf
,
1917 true, req
->seqnum
+1,
1918 IS_CONN_ENCRYPTED(req
->conn
)
1921 exit_server_cleanly("chain_reply: srv_send_smb "
1924 TALLOC_FREE(req
->chain_outbuf
);
1929 /* add a new perfcounter for this element of chain */
1930 SMB_PERFCOUNT_ADD(&req
->pcd
);
1931 SMB_PERFCOUNT_SET_OP(&req
->pcd
, chain_cmd
);
1932 SMB_PERFCOUNT_SET_MSGLEN_IN(&req
->pcd
, smblen
);
1935 * Check if the client tries to fool us. The request so far uses the
1936 * space to the end of the byte buffer in the request just
1937 * processed. The chain_offset can't point into that area. If that was
1938 * the case, we could end up with an endless processing of the chain,
1939 * we would always handle the same request.
1942 already_used
= PTR_DIFF(req
->buf
+req
->buflen
, smb_base(req
->inbuf
));
1943 if (chain_offset
< already_used
) {
1948 * Next check: Make sure the chain offset does not point beyond the
1949 * overall smb request length.
1952 length_needed
= chain_offset
+1; /* wct */
1953 if (length_needed
> smblen
) {
1958 * Now comes the pointer magic. Goal here is to set up req->vwv and
1959 * req->buf correctly again to be able to call the subsequent
1960 * switch_message(). The chain offset (the former vwv[1]) points at
1961 * the new wct field.
1964 wct
= CVAL(smb_base(req
->inbuf
), chain_offset
);
1967 * Next consistency check: Make the new vwv array fits in the overall
1971 length_needed
+= (wct
+1)*sizeof(uint16_t); /* vwv+buflen */
1972 if (length_needed
> smblen
) {
1975 vwv
= (uint16_t *)(smb_base(req
->inbuf
) + chain_offset
+ 1);
1978 * Now grab the new byte buffer....
1981 buflen
= SVAL(vwv
+wct
, 0);
1984 * .. and check that it fits.
1987 length_needed
+= buflen
;
1988 if (length_needed
> smblen
) {
1991 buf
= (uint8_t *)(vwv
+wct
+1);
1993 req
->cmd
= chain_cmd
;
1996 req
->buflen
= buflen
;
1999 switch_message(chain_cmd
, req
, smblen
);
2001 if (req
->outbuf
== NULL
) {
2003 * This happens if the chained command has suspended itself or
2004 * if it has called srv_send_smb() itself.
2010 * We end up here if the chained command was not itself chained or
2011 * suspended, but for example a close() command. We now need to splice
2012 * the chained commands' outbuf into the already built up chain_outbuf
2013 * and ship the result.
2019 * We end up here if there's any error in the chain syntax. Report a
2020 * DOS error, just like Windows does.
2022 reply_force_doserror(req
, ERRSRV
, ERRerror
);
2023 fixup_chain_error_packet(req
);
2027 * This scary statement intends to set the
2028 * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
2029 * to the value req->outbuf carries
2031 SSVAL(req
->chain_outbuf
, smb_flg2
,
2032 (SVAL(req
->chain_outbuf
, smb_flg2
) & ~FLAGS2_32_BIT_ERROR_CODES
)
2033 | (SVAL(req
->outbuf
, smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
));
2036 * Transfer the error codes from the subrequest to the main one
2038 SSVAL(req
->chain_outbuf
, smb_rcls
, SVAL(req
->outbuf
, smb_rcls
));
2039 SSVAL(req
->chain_outbuf
, smb_err
, SVAL(req
->outbuf
, smb_err
));
2041 if (!smb_splice_chain(&req
->chain_outbuf
,
2042 CVAL(req
->outbuf
, smb_com
),
2043 CVAL(req
->outbuf
, smb_wct
),
2044 (uint16_t *)(req
->outbuf
+ smb_vwv
),
2045 0, smb_buflen(req
->outbuf
),
2046 (uint8_t *)smb_buf(req
->outbuf
))) {
2047 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
2049 TALLOC_FREE(req
->outbuf
);
2051 smb_setlen((char *)(req
->chain_outbuf
),
2052 talloc_get_size(req
->chain_outbuf
) - 4);
2054 show_msg((char *)(req
->chain_outbuf
));
2056 if (!srv_send_smb(smbd_server_fd(), (char *)req
->chain_outbuf
,
2057 true, req
->seqnum
+1,
2058 IS_CONN_ENCRYPTED(req
->conn
)||req
->encrypted
,
2060 exit_server_cleanly("construct_reply: srv_send_smb failed.");
2062 TALLOC_FREE(req
->chain_outbuf
);
2066 /****************************************************************************
2067 Check if services need reloading.
2068 ****************************************************************************/
2070 void check_reload(time_t t
)
2072 time_t printcap_cache_time
= (time_t)lp_printcap_cache_time();
2074 if(last_smb_conf_reload_time
== 0) {
2075 last_smb_conf_reload_time
= t
;
2076 /* Our printing subsystem might not be ready at smbd start up.
2077 Then no printer is available till the first printers check
2078 is performed. A lower initial interval circumvents this. */
2079 if ( printcap_cache_time
> 60 )
2080 last_printer_reload_time
= t
- printcap_cache_time
+ 60;
2082 last_printer_reload_time
= t
;
2085 if (mypid
!= getpid()) { /* First time or fork happened meanwhile */
2086 /* randomize over 60 second the printcap reload to avoid all
2087 * process hitting cupsd at the same time */
2088 int time_range
= 60;
2090 last_printer_reload_time
+= random() % time_range
;
2094 if (t
>= last_smb_conf_reload_time
+SMBD_RELOAD_CHECK
) {
2095 reload_services(True
);
2096 last_smb_conf_reload_time
= t
;
2099 /* 'printcap cache time = 0' disable the feature */
2101 if ( printcap_cache_time
!= 0 )
2103 /* see if it's time to reload or if the clock has been set back */
2105 if ( (t
>= last_printer_reload_time
+printcap_cache_time
)
2106 || (t
-last_printer_reload_time
< 0) )
2108 DEBUG( 3,( "Printcap cache time expired.\n"));
2110 last_printer_reload_time
= t
;
2115 static void smbd_server_connection_write_handler(struct smbd_server_connection
*conn
)
2117 /* TODO: make write nonblocking */
2120 static void smbd_server_connection_read_handler(struct smbd_server_connection
*conn
)
2122 uint8_t *inbuf
= NULL
;
2123 size_t inbuf_len
= 0;
2124 size_t unread_bytes
= 0;
2125 bool encrypted
= false;
2126 TALLOC_CTX
*mem_ctx
= talloc_tos();
2132 ok
= smbd_lock_socket(conn
);
2134 exit_server_cleanly("failed to lock socket");
2137 /* TODO: make this completely nonblocking */
2138 status
= receive_smb_talloc(mem_ctx
, smbd_server_fd(),
2139 (char **)(void *)&inbuf
,
2143 &inbuf_len
, &seqnum
,
2144 false /* trusted channel */);
2145 ok
= smbd_unlock_socket(conn
);
2147 exit_server_cleanly("failed to unlock");
2150 if (NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
2153 if (NT_STATUS_IS_ERR(status
)) {
2154 exit_server_cleanly("failed to receive smb request");
2156 if (!NT_STATUS_IS_OK(status
)) {
2161 process_smb(conn
, inbuf
, inbuf_len
, unread_bytes
,
2162 seqnum
, encrypted
, NULL
);
2165 static void smbd_server_connection_handler(struct event_context
*ev
,
2166 struct fd_event
*fde
,
2170 struct smbd_server_connection
*conn
= talloc_get_type(private_data
,
2171 struct smbd_server_connection
);
2173 if (flags
& EVENT_FD_WRITE
) {
2174 smbd_server_connection_write_handler(conn
);
2175 } else if (flags
& EVENT_FD_READ
) {
2176 smbd_server_connection_read_handler(conn
);
2181 /****************************************************************************
2182 received when we should release a specific IP
2183 ****************************************************************************/
2184 static void release_ip(const char *ip
, void *priv
)
2186 char addr
[INET6_ADDRSTRLEN
];
2189 client_socket_addr(get_client_fd(),addr
,sizeof(addr
));
2191 if (strncmp("::ffff:", addr
, 7) == 0) {
2195 if ((strcmp(p
, ip
) == 0) || ((p
!= addr
) && strcmp(addr
, ip
) == 0)) {
2196 /* we can't afford to do a clean exit - that involves
2197 database writes, which would potentially mean we
2198 are still running after the failover has finished -
2199 we have to get rid of this process ID straight
2201 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
2203 /* note we must exit with non-zero status so the unclean handler gets
2204 called in the parent, so that the brl database is tickled */
2209 static void msg_release_ip(struct messaging_context
*msg_ctx
, void *private_data
,
2210 uint32_t msg_type
, struct server_id server_id
, DATA_BLOB
*data
)
2212 release_ip((char *)data
->data
, NULL
);
2215 #ifdef CLUSTER_SUPPORT
2216 static int client_get_tcp_info(struct sockaddr_storage
*server
,
2217 struct sockaddr_storage
*client
)
2220 if (server_fd
== -1) {
2223 length
= sizeof(*server
);
2224 if (getsockname(server_fd
, (struct sockaddr
*)server
, &length
) != 0) {
2227 length
= sizeof(*client
);
2228 if (getpeername(server_fd
, (struct sockaddr
*)client
, &length
) != 0) {
2236 * Send keepalive packets to our client
2238 static bool keepalive_fn(const struct timeval
*now
, void *private_data
)
2243 ok
= smbd_lock_socket(smbd_server_conn
);
2245 exit_server_cleanly("failed to lock socket");
2248 ret
= send_keepalive(smbd_server_fd());
2250 ok
= smbd_unlock_socket(smbd_server_conn
);
2252 exit_server_cleanly("failed to unlock socket");
2256 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
2263 * Do the recurring check if we're idle
2265 static bool deadtime_fn(const struct timeval
*now
, void *private_data
)
2267 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2268 if ((conn_num_open(sconn
) == 0)
2269 || (conn_idle_all(sconn
, now
->tv_sec
))) {
2270 DEBUG( 2, ( "Closing idle connection\n" ) );
2271 messaging_send(smbd_messaging_context(), procid_self(),
2272 MSG_SHUTDOWN
, &data_blob_null
);
2280 * Do the recurring log file and smb.conf reload checks.
2283 static bool housekeeping_fn(const struct timeval
*now
, void *private_data
)
2285 change_to_root_user();
2287 /* update printer queue caches if necessary */
2288 update_monitored_printq_cache();
2290 /* check if we need to reload services */
2291 check_reload(time(NULL
));
2293 /* Change machine password if neccessary. */
2294 attempt_machine_password_change();
2297 * Force a log file check.
2299 force_check_log_size();
2304 /****************************************************************************
2305 Process commands from the client
2306 ****************************************************************************/
2308 void smbd_process(void)
2310 TALLOC_CTX
*frame
= talloc_stackframe();
2311 char remaddr
[INET6_ADDRSTRLEN
];
2313 if (lp_maxprotocol() == PROTOCOL_SMB2
&&
2314 lp_security() != SEC_SHARE
) {
2315 smbd_server_conn
->allow_smb2
= true;
2318 /* Ensure child is set to blocking mode */
2319 set_blocking(smbd_server_fd(),True
);
2321 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2322 set_socket_options(smbd_server_fd(), lp_socket_options());
2324 /* this is needed so that we get decent entries
2325 in smbstatus for port 445 connects */
2326 set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2330 reload_services(true);
2333 * Before the first packet, check the global hosts allow/ hosts deny
2334 * parameters before doing any parsing of packets passed to us by the
2335 * client. This prevents attacks on our parsing code from hosts not in
2336 * the hosts allow list.
2339 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2340 lp_hostsdeny(-1))) {
2341 char addr
[INET6_ADDRSTRLEN
];
2344 * send a negative session response "not listening on calling
2347 unsigned char buf
[5] = {0x83, 0, 0, 1, 0x81};
2348 DEBUG( 1, ("Connection denied from %s\n",
2349 client_addr(get_client_fd(),addr
,sizeof(addr
)) ) );
2350 (void)srv_send_smb(smbd_server_fd(),(char *)buf
, false,
2352 exit_server_cleanly("connection denied");
2359 smb_perfcount_init();
2361 if (!init_account_policy()) {
2362 exit_server("Could not open account policy tdb.\n");
2365 if (*lp_rootdir()) {
2366 if (chroot(lp_rootdir()) != 0) {
2367 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2368 exit_server("Failed to chroot()");
2370 if (chdir("/") == -1) {
2371 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
2372 exit_server("Failed to chroot()");
2374 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2377 if (!srv_init_signing(smbd_server_conn
)) {
2378 exit_server("Failed to init smb_signing");
2382 if (!init_oplocks(smbd_messaging_context()))
2383 exit_server("Failed to init oplocks");
2385 /* Setup aio signal handler. */
2386 initialize_async_io_handler();
2388 /* register our message handlers */
2389 messaging_register(smbd_messaging_context(), NULL
,
2390 MSG_SMB_FORCE_TDIS
, msg_force_tdis
);
2391 messaging_register(smbd_messaging_context(), NULL
,
2392 MSG_SMB_RELEASE_IP
, msg_release_ip
);
2393 messaging_register(smbd_messaging_context(), NULL
,
2394 MSG_SMB_CLOSE_FILE
, msg_close_file
);
2397 * Use the default MSG_DEBUG handler to avoid rebroadcasting
2398 * MSGs to all child processes
2400 messaging_deregister(smbd_messaging_context(),
2402 messaging_register(smbd_messaging_context(), NULL
,
2403 MSG_DEBUG
, debug_message
);
2405 if ((lp_keepalive() != 0)
2406 && !(event_add_idle(smbd_event_context(), NULL
,
2407 timeval_set(lp_keepalive(), 0),
2408 "keepalive", keepalive_fn
,
2410 DEBUG(0, ("Could not add keepalive event\n"));
2414 if (!(event_add_idle(smbd_event_context(), NULL
,
2415 timeval_set(IDLE_CLOSED_TIMEOUT
, 0),
2416 "deadtime", deadtime_fn
, NULL
))) {
2417 DEBUG(0, ("Could not add deadtime event\n"));
2421 if (!(event_add_idle(smbd_event_context(), NULL
,
2422 timeval_set(SMBD_SELECT_TIMEOUT
, 0),
2423 "housekeeping", housekeeping_fn
, NULL
))) {
2424 DEBUG(0, ("Could not add housekeeping event\n"));
2428 #ifdef CLUSTER_SUPPORT
2430 if (lp_clustering()) {
2432 * We need to tell ctdb about our client's TCP
2433 * connection, so that for failover ctdbd can send
2434 * tickle acks, triggering a reconnection by the
2438 struct sockaddr_storage srv
, clnt
;
2440 if (client_get_tcp_info(&srv
, &clnt
) == 0) {
2444 status
= ctdbd_register_ips(
2445 messaging_ctdbd_connection(),
2446 &srv
, &clnt
, release_ip
, NULL
);
2448 if (!NT_STATUS_IS_OK(status
)) {
2449 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2450 nt_errstr(status
)));
2454 DEBUG(0,("Unable to get tcp info for "
2455 "CTDB_CONTROL_TCP_CLIENT: %s\n",
2462 smbd_server_conn
->nbt
.got_session
= false;
2464 smbd_server_conn
->smb1
.negprot
.max_recv
= MIN(lp_maxxmit(),BUFFER_SIZE
);
2466 smbd_server_conn
->smb1
.sessions
.done_sesssetup
= false;
2467 smbd_server_conn
->smb1
.sessions
.max_send
= BUFFER_SIZE
;
2468 smbd_server_conn
->smb1
.sessions
.last_session_tag
= UID_FIELD_INVALID
;
2469 /* users from session setup */
2470 smbd_server_conn
->smb1
.sessions
.session_userlist
= NULL
;
2471 /* workgroup from session setup. */
2472 smbd_server_conn
->smb1
.sessions
.session_workgroup
= NULL
;
2473 /* this holds info on user ids that are already validated for this VC */
2474 smbd_server_conn
->smb1
.sessions
.validated_users
= NULL
;
2475 smbd_server_conn
->smb1
.sessions
.next_vuid
= VUID_OFFSET
;
2476 smbd_server_conn
->smb1
.sessions
.num_validated_vuids
= 0;
2477 #ifdef HAVE_NETGROUP
2478 smbd_server_conn
->smb1
.sessions
.my_yp_domain
= NULL
;
2481 conn_init(smbd_server_conn
);
2482 if (!init_dptrs(smbd_server_conn
)) {
2483 exit_server("init_dptrs() failed");
2486 smbd_server_conn
->smb1
.fde
= event_add_fd(smbd_event_context(),
2490 smbd_server_connection_handler
,
2492 if (!smbd_server_conn
->smb1
.fde
) {
2493 exit_server("failed to create smbd_server_connection fde");
2501 frame
= talloc_stackframe_pool(8192);
2505 status
= smbd_server_connection_loop_once(smbd_server_conn
);
2506 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
) &&
2507 !NT_STATUS_IS_OK(status
)) {
2508 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2509 " exiting\n", nt_errstr(status
)));
2516 exit_server_cleanly(NULL
);
2519 bool req_is_in_chain(struct smb_request
*req
)
2521 if (req
->vwv
!= (uint16_t *)(req
->inbuf
+smb_vwv
)) {
2523 * We're right now handling a subsequent request, so we must
2529 if (!is_andx_req(req
->cmd
)) {
2535 * Okay, an illegal request, but definitely not chained :-)
2540 return (CVAL(req
->vwv
+0, 0) != 0xFF);